2017-02-28 12 views
2

비슷한 질문을 보았지만 아무 것도 해결하지 못했습니다. 시나리오는 - 나는 외부 저장소에 두 개의 DLL을 가지고 있는데, 나는 그들에 대한 정보 (Assembly 버전과 AssemblyInformationalVersion을 특정해야 함)를 얻을 필요가있다. 다음 코드로 시작했습니다.어셈블리를 임시 AppDomain에로드하십시오.

List<byte[]> assemblies = _client.DownloadAllAssemblies(); 
foreach(var assemblyBytes in assemblies) 
{ 
    var assembly = Assembly.ReflectionOnlyLoad(assemblyBytes); 
    var assemblyName = assembly.GetName(); 
    ... // read version from assembly name 
} 

위 코드는 한 번만 작동합니다. 보기를 새로 고치기 위해 단추를 클릭하면 어셈블리가 이미로드되어 다시로드 할 수 없다는 예외가 발생합니다. 그런 다음 임시 도메인을 만들고 어셈블리를로드하여 AppDomain을 언로드 할 수 있도록해야한다고 읽었습니다. 나는 다음 코드를 시도 : 코드 위

List<byte[]> assemblies = _client.DownloadAllAssemblies(); 
var tempDomain = AppDomain.Create("TemporaryDomain"); 
foreach(var assemblyBytes in assemblies) 
{ 
    var assembly = tempDomain.Load(assemblyBytes); 
    var assemblyName = assembly.GetName(); 
    ... // read version from assembly name 
} 
AppDomain.Unload(tempDomain); 

나는 그것이 일어나는 이유를 이해하지만 난이 문제를 해결하는 방법을 아무 생각이 없다 "... 파일이나 어셈블리를로드 할 수 없습니다"라는 FileNotFound 예외가 발생합니다. 이 작업은 매우 사소한 것 같다

  1. 로드 파일,
  2. 이 버전을 읽고,
  3. 그것에 대해 잊어 버려.

위의 논리는 복잡하지 않습니다. 런타임 요구 사항에 지나치게 복잡해진 것처럼 보입니다. 누구든지 내가 어떻게 작동하게 할 수 있는지 알고 있니?

+0

더 많은 스택 트레이스 (항상 완전한 정보를 제공)가 필요합니다. 전달할 바이트 배열을로드하기 전에 종속 어셈블리를로드 할 수 없었을 가능성이 있습니다. 'AppDomain'에 몇 가지 속성이 있습니다. 프로빙 경로와 같은 기본값입니다. 또한 당신은 여전히'ReflectionOnlyLoad'를 사용하여 모든 것을 해결하려고 시도하지 않을 것입니다. –

+0

@ escape-llc AppDomain은 "ReflectionOnlyLoad"함수를 노출하지 않습니다. 나중에 StackTrace로 질문을 업데이트 할 것입니다. 감사. – MajkeloDev

답변

2

작업은 사소한 것처럼 보이지 않습니다. AppDomain.Load 메서드는 이런 방식으로 사용하지 않습니다.

System.AppDomain 클래스의 Load 메서드는 어셈블리를로드 할 수 있지만 주로 COM 상호 운용성에 사용됩니다. 어셈블리를 호출 한 응용 프로그램 도메인이 아닌 응용 프로그램 도메인에 어셈블리를로드하는 데 사용해서는 안됩니다.

  1. 간단한 방법 :

나는 귀하의 경우에이 개 솔루션을 참조하십시오. 어셈블리 바이트 배열을 임시 파일에 쓰고 FileVersionProductVersionFileVersionInfo.GetVersionInfo 통해 읽습니다. 대부분의 경우 이러한 값은 AssemblyVersionAssemblyInformalVersion과 같아야합니다.

  • 올바른 방법은 AppDomain입니다. 앱 도메인의 문제는로드하려는 어셈블리가 외부가 아닌 해당 도메인 내부에서로드되어야한다는 것입니다.

  • 는이를 달성하기 위해, 당신은 필요한 모든 로직을 포함 특별한 클래스를 작성해야하고 그 클래스는 (MarshalByRef 클래스에서 상속) 참조로 정렬 화되어야한다.

    그런 다음 새 도메인을 만든 후에 새로 만든 도메인 내에 해당 클래스를로드하고 unwrap해야합니다. 당신은 CreateInstanceAndUnwrap 방법으로 이것을 할 수 있습니다.

    이 클래스는 다른 도메인에 있으며 해당 메서드와 속성에 대한 모든 호출이 해당 도메인에 정렬되므로 논리를 사용하여 어셈블리를로드하고 필요한 정보를 읽을 수 있습니다. 또는 다른 도메인 내부에 다른 작업을 수행하십시오.

    완료되면 해당 도메인을 언로드 할 수 있고 언로드해야합니다.

    처음 응용 프로그램 도메인이 완전히 비어 있으므로 클래스의 인스턴스를 만들거나 추가 어셈블리를로드 할 때 .Net이 해당 도메인에 관련된 모든 어셈블리를 확인하고로드해야합니다. 때로는 시스템에서이 작업을 자동으로 수행 할 수 없지만이 경우 새 도메인의 AssemblyResolve 이벤트에 가입하여 시스템에서 도움을받을 수 있습니다.

    +0

    응답 해 주셔서 감사합니다. "AppDomain.Load 메서드가 그런 식으로 사용할 수 없습니다." 그때 나는 그것을 "missuse"하고 싶지 않다. 임시 다운로드 솔루션을 사용해보고 성공하면 알려 드리겠습니다. DLLV 생성을 제어 할 수 있으므로 FileVerison을 AssemblyVersion과 같게 설정할 수 있어야합니다. – MajkeloDev

    +0

    나는 steve16351의 솔루션으로 끝났다. http://stackoverflow.com/questions/26106431/loading-byte-array-assembly-into-new-appdomain-throws-a-filenotfound-exception/26107788?noredirect=1#comment72198604_26107788 – MajkeloDev