2011-08-07 3 views
5

타사 프로그램에 포함 된 일부 DLL에 따라 프로그램을 만들고 있습니다. 나는이 DLL들을 직접 배포 할 수 없다. 내 프로그램이 작동하려면 타사 프로그램이 설치되어 있어야합니다..NET 참조 dll from other location

어떻게 이러한 DLL을 참조 할 수 있습니까? 나는 프로그램에 의해 설정된 레지스트리 키를 통해 그들의 정확한 위치를 안다.

Project-> References에 파일을 추가하고 CopyLocal을 false로 설정하려고했지만 파일을 시작할 때 FileNotFoundException이 발생합니다. "파일 또는 어셈블리를로드 할 수 없습니다."

AppDomain.CurrentDomain.AssemblyResolve에 이벤트를 추가하고 거기에 파일을로드하려고 시도했지만 문제는 내 프로그램이 시작되기 전에 예외가 발생한다는 것입니다. 첫 번째 줄에 중단 점을 놓을지라도 중단 점에 도달하기 전에 예외가 throw됩니다.

+0

일반적으로 타사 공급 업체는 표준 사례를 따르지 않을 경우 프로덕션 환경에서 해당 구성 요소를 사용하는 방법을 설명합니다. 괜찮은 서류가 없습니까? –

+0

사이먼 (Simon)은 일반적으로 제 3 자 협의회와 배포 가능한 계약이 있다고 말합니다. –

+0

가능한 한 빨리 'AssemblyResolve' 이벤트에 가입 하시겠습니까? 일찌기 구독하지 않으면 문제를 해결하기 전에 타사 어셈블리에 따라 일부 코드가 실행될 수 있습니다. –

답변

9

C# 3.0 in a Nutshell, 3rd edition, by Joseph and Ben Albahari, p. 557-558 : 응용 프로그램의 기본 디렉토리가 아닌 다른 위치에 어셈블리를 배포하도록 선택할 수 있습니다 때로는

기본 폴더 외부

배포 어셈블리는 [...] 이를 만들려면 작업을 수행하려면 기본 폴더 외부에서 어셈블리를 찾는 데 CLR을 지원해야합니다. 가장 쉬운 해결책은 AssemblyResolve 이벤트를 처리하는 것입니다.

(우리는 당신의 경우에, 당신이 아닌 다른 사람이 어셈블리를 배포한다는 사실을 무시할 수 있습니다.) 당신이 시도

. 그러나 나중에 매우 중요한 단서가 있습니다. 두 코드 주석을 읽어 보시다시피

public static void Loader 
{ 
    static void Main(string[] args) 
    { 
     AppDomain.CurrentDomain.AssemblyResolve += FindAssem; 

     // We must switch to another class before attempting to use 
     // any of the types in C:\ExtraAssemblies: 
     Program.Go(); 
    } 

    static Assembly FindAssem(object sender, ResolveEventArgs args) 
    { 
     string simpleName = new AssemblyName(args.Name).Name; 
     string path = @"C:\ExtraAssemblies\" + simpleName + ".dll"; 

     if (!File.Exists(path)) return null; 
     return Assembly.LoadFrom(path); 
    } 
} 

public class Program 
{ 
    public static void Go() 
    { 
     // Now we can reference types defined in C:\ExtraAssemblies 
    } 
} 

, 당신이 외부 DLL을 어디의에서 모든 형식을 참조하지 않아야합니다 외부 어셈블리를 해결 클래스입니다. 그랬다면 AssemblyResolve이 실행되기 전에 코드 실행이 멈출 것입니다.

+0

빙고! 참조 된 항목의 사용을 Main()이 아닌 다른 클래스로 이동하면 해결됩니다. 감사합니다 :) – aero

+0

P.S .:이 솔루션이 공식적으로 문서화되었는지 또는 일부 프레임 워크 버전에서 작동하는 것은 영리한 트릭인지는 모르지만 다른 사람들과 함께 실패 할 수 있음을 인정해야합니다. 그러므로 나는 Hans Passant의 마지막 진술에 완전히 동의한다 : 더 쉬운 방법이 있어야한다. – stakx

+0

이것은 훌륭합니다! 질문 : FindAssem()이 null을 반환하면 Go()가 FileNotFoundException을 발생시키지 않도록 방지하려면 어떻게해야합니까? – Eddie

4

어셈블리를로드해야하는 JIT 컴파일러이기 때문에 앱 폭탄이 발생합니다. Main() 메서드에서 어셈블리의 형식을 사용하지 않도록주의해야합니다. 그렇게하기가 어렵지 않습니다. 다른 Main 메소드를 작성하고 지터에게 해당 메소드를 인라인해서는 안된다는 것을 알려주는 속성을 지정하십시오. 이 속성이 없으면 최적화 프로그램이 메소드를 인라인 할 때 릴리즈 빌드에 여전히 폭탄이있을 수 있습니다. 이와 같이 :

이렇게하기 전에 공급 업체에 문의하고 권장 사항을 요청하십시오. 라이센스 권한을 행사할 수있는 더 쉬운 방법이 있어야합니다. GAC는 일반적인 선택 일 것입니다. 아마도 여러분의 dev 컴퓨터에서 gacutil을 실행할 필요가있을 것입니다.