2015-01-28 6 views
0

외부 어셈블리로드를 직접 처리해야하는 환경에서 사용하는 DLL이 있습니다. 어셈블리를 AppDomain에로드하려고합니다. 이 잘 CurrentAppDomain 함께 시도 할 때 작동하지만이 자신을 만드는 appdomain이 작업을 수행 할 때 실패합니다. 배경은 결국 어셈블리가 "해제"되도록 맨 끝에서 appdomain을 언로드하려고합니다.MyAppDomain AssemblyResolve C#

public ZipEx() 
{ 
    try 
    { 
     AppDomainSetup domaininfo = new AppDomainSetup(); 
     domaininfo.ApplicationBase = System.Environment.CurrentDirectory; 
     Evidence adevidence = AppDomain.CurrentDomain.Evidence; 

     //THIS CODE WORKS 
     //System.AppDomain.CurrentDomain.AssemblyResolve += CurrentDomain_AssemblyResolve; 
     //System.AppDomain.CurrentDomain.Load("ICSharpCode.SharpZipLib"); 

     //THIS CODE DOES NOT WORK 
     AppDomain zipDomain2 = AppDomain.CreateDomain("ADZib2", adevidence, domaininfo); 
     PolicyLevel polLevel = PolicyLevel.CreateAppDomainLevel(); 
     PermissionSet permSet = new PermissionSet(PermissionState.Unrestricted); 
     permSet.AddPermission(new SecurityPermission(SecurityPermissionFlag.AllFlags)); 
     polLevel.RootCodeGroup.PolicyStatement = new PolicyStatement(permSet); 
     zipDomain2.SetAppDomainPolicy(polLevel); 
     zipDomain2.AssemblyResolve += CurrentDomain_AssemblyResolve; 
    } 
    catch (Exception ex) 
    { 
     System.Windows.Forms.MessageBox.Show("ex in ctor" + Environment.NewLine + ex.ToString()); 
    } 
    if (_loadedAssembly == null) 
    { 
    } 
} 

Assembly CurrentDomain_AssemblyResolve(object sender, ResolveEventArgs args) 
{ 
    System.Windows.Forms.MessageBox.Show("CurrentDomain_AssemblyResolve"); 
    Assembly assembly = null; 
    bool foundAssembly = false; 

    int idx = args.Name.IndexOf(','); 
    if (idx > 0) 
    { 
     string partialName = args.Name.Substring(0, idx); 
     string dllName = partialName + ".dll"; 

     //Add the directorys where the assembly hould be resolved 
     List<string> directorySearch = new List<string> 
     { 
      string.Format("{0}{1}{2}",Environment.CurrentDirectory,Path.DirectorySeparatorChar, dllName), 
      string.Format("{0}{1}{2}",AppPath,Path.DirectorySeparatorChar, dllName) 
     }; 

     foreach (string fileName in directorySearch) 
     { 
      if (File.Exists(fileName)) 
      { 
       foundAssembly = true; 
       assembly = Assembly.LoadFrom(fileName); 
       break; 
      } 
     } 

     if (assembly == null) 
     { 
      if (!foundAssembly) 
      { 
       foreach (string fileName in directorySearch) 
       { 
       } 
      } 
      else 
      { 
      } 
     } 
    } 
    if (assembly != null) 
    { 
     System.Windows.Forms.MessageBox.Show("assembly is not null"); 
    } 
    return assembly; 
} 

제 질문은 어떻게 어셈블리를로드하기 위해 만든 appdomain을 사용합니까?

+0

"작동하지 않는다"고 할 때, 당신은 무엇을 의미합니까? 이벤트, 예외 등이 없습니까? –

+0

왜 zipDomain2.AssemblyResolve 이벤트를 사용하지 않는지 알기가 어렵습니다. 아니면 AppDomainSetup을 좋아하는 방식으로 설정하지 않아도됩니다. 문제 해결을 위해 Fuslogvw.exe를 사용하십시오. –

+0

@Steve Mitcham 어셈블리를 찾을 수 없다는 예외가 제기됩니다. 내 문제는 CurrentDomain과 함께 작동한다는 것입니다. – Bongo

답변

1

현재 예제에서는 새로 만든 AppDomain에서 어셈블리를로드하려고 시도하는 주석 처리되지 않은 코드가 표시되지 않습니다. 이 답변에서 주석 처리되지 않은 코드에서 누락 된 Load에 대한 호출이 있다고 가정합니다.

AppDomain.Load에 대한 도움말의 설명에 따르면 현재 AppDomain에서만 사용해야합니다. 그렇지 않으면 예외가 발생하는 이유 인 어셈블리를 두 AppDomains에 모두로드하려고하기 때문에 현재 AppDomain에서만 사용해야합니다. 어셈블리를 다른 AppDomain에만로드하려면 CreateInstance 함수 중 하나를 호출해야합니다. 이 특별한 경우에는 CreateInstanceFromAndUnwrap 함수를 권하고 싶습니다. 유형을 포함하여 이름과 함께 어셈블리를 지정할 수 있기 때문입니다.

인스턴스화하고 AppDomain 경계를 넘어서 상호 작용할 수있는 유형이없는 경우 (가능성은 희박하지만 가능할 수 있음), 열거 형 또는 구조체와 같은 간단한 유형을 만들어 폐기해야 할 수 있습니다 이게 작동합니다.

+1

코드가 DLL을 로딩한다는 것을 명확히 알 수 있으므로이 질문에 의해 멈추는 코드에 대해서는 [AppDomain.ExecuteAssembly] (https://msdn.microsoft. 다른 AppDomain에서 명시 적으로 해당 형식을 만들지 않고 실행 파일을 실행하려면 com/ko-kr/library/sxx9f4c2 (v = vs.110). –

+0

나는 모든 것을 시험해 볼 것입니다. 힌트를 주셔서 감사합니다, 내가 그걸로 성취 할 수있는 것을 볼 수 있습니다. – Bongo

+0

젠장, 방금 다른 것을 깨달았습니다. 위에있는 코드가 사용중인 코드이고 Load를 호출하지 않아도 실패하는 경우 새 AppDomain이 원래 DLL 또는 EXE를로드하려고하기 때문에 AssemblyResolve 이벤트를 연결할 때이 예외가 발생할 수 있습니다 (CurrentDomain_AssemblyResolve 메소드가있는 메소드) 새 AppDomain의 Applicationbase 경로에 없기 때문에 할 수 없습니다. 그렇다면 원본 실행 파일의 사본을로드하려는 디렉토리에 넣고 그 파일이 전혀 도움이되는지 확인할 수 있습니다. –