2012-02-13 2 views
3

가능한 중복 :
Specify the search path for DllImport in .NET상대 경로

내가 관리되지 않는 DLL이있다. 클리어런스에 대해서는 C# 코드에서 사용하려는 C++ DLL입니다. 문제는 자사의 윈도우 응용 프로그램과 사용자가 자신이 선택한 임의의 디렉토리에 설치 할 수 있다는 것입니다. 그래서 정적 경로로 참조 할 수 없으며 상대 경로를 제공하는 방법을 찾을 수 없습니다. 여기에 내가 노력 코드입니다 :

[DllImport("mydll.dll", CharSet = CharSet.Auto, SetLastError = true)] 
    static extern bool SetDllDirectory(string lpPathName); 

    public void SetDllDirectory(string lpPathName) 
     { 
      try 
      { 
       bool r = SetDllDirectory(lpPathName); 
      } 
      catch (Exception ex) 
      { 
       throw ex; 
      } 
     } 

     public void SetDirectoryPath() 
     { 
      try 
      { 
       DirectoryInfo directory = new DirectoryInfo(System.IO.Path.GetDirectoryName(System.Windows.Forms.Application.ExecutablePath)); 
       if (directory.Exists) 
        SetDllDirectory(directory.ToString() + "\\mydll.dll"); 

      } 
      catch (Exception ex) 
      { 
       throw ex; 
      } 
     } 

는 그리고 아래 나는 수신하고있는 오류입니다.

'mydll.dll'DLL에서 'SetDllDirectory'라는 항목 포인트를 찾을 수 없습니다.

이 질문은

"C++ unmanaged DLL in c#"

그 죄송합니다 "Relative Path to DLL in Platform Invoke Statement"

의 복제 될 수 있지만 이러한 참조 어떤 해결책을 찾지 못했습니다.

+0

예, 그 방법을 시도했습니다. 그러나 그것은 효과가 없었습니다. 그 죄송합니다. –

+0

PATH 해킹 또는 SetDllDirectory()를 시도 했습니까? – IanNorton

+0

난 SetDllDirectory()를 시도했다 –

답변

1

이 오류 메시지 :

DLL 'mydll에'있는 SetDllDirectory '라는 진입 점을 찾을 수

수 없습니다. dll '.

는 DLL을 찾을 수 없다는 아무것도 말하지 않는다. P/Invoke 정의가 올바르지 않습니다. 당신의 DLL (mydll.dll)에 SetDllDirectory라는 이름의 기능은 없습니다. 왜 그럴까요? DLL에서 내보내는 유일한 함수는 명시 적으로 코드를 작성하고 내보내는 함수입니다. SetDllDirectory에 대한 코드를 작성하지 않았으므로 mydll.dll에서 내 보낸다는 것을 나타내므로 DLL에 존재하지 않습니다.

그 외에도 질문을 실제 코드로 업데이트하지 않는 한이 질문에 답할 수 없습니다. 최소한 C# (관리) 측에서 시도한 P/Invoke 코드와 함께 관리되지 않는 DLL에서 호출하려는 함수의 서명을 게시해야합니다.

문제는 Windows 응용 프로그램과 사용자가 원하는 디렉토리에 설치할 수 있다는 것입니다. 그래서 정적 경로로 참조 할 수 없으며 상대 경로를 제공하는 방법을 찾을 수 없습니다.

이것은 실제 문제는 아닙니다. 상대 경로는 정상적으로 작동하며 질문에 이미 시도한 바를 정확하게 나타냅니다. P/Invoke 정의에 DLL 이름 만 포함하면됩니다. 기본 DLL 검색 순서는 다른 모든 것을 처리합니다. 관리되는 EXE가 P/Invoke 할 관리되지 않는 DLL과 동일한 디렉터리에 있으면 모든 것이 원활하게 작동합니다.

DLL과 EXE가 같은 폴더에있는 한 사용자가 응용 프로그램을 설치하도록 선택하지 않아도됩니다. 이것이 설치 프로그램의 일입니다.

그래서 당신이 상대 경로를 사용할 때, 당신은 절대적 (실제로 kernel32.dll에 정의되어 있습니다)는 Win32 API에서 SetDllDirectory 기능을 사용하지 필요성을한다.

+0

- 감사합니다. 당신은 내 하루를 보냈습니다. –

4

당신은 창문이 dll 파일을 찾기 위해 사용하는 DLL 검색 경로에이 위치를 추가 할 필요가 비표준 위치에 관리되지 않는 라이브러리로 PInvoke를하려는 경우.

는 C/C++ 라이브러리 파일이고 사용자가 프로그램을 말할 수 있다면 그들은 그것을 선택하면, 당신은 수동으로로드 할 수 있습니다.

public class UnsafeNativeMethods { 
    [DllImport("kernel32.dll", SetLastError = true)] 
    public static extern bool SetDllDirectory(string lpPathName); 

    [DllImport("kernel32.dll", SetLastError = true)] 
    public static extern int GetDllDirectory(int bufsize, StringBuilder buf); 

    [DllImport("kernel32", CharSet = CharSet.Unicode, SetLastError = true)] 
    public static extern IntPtr LoadLibrary(string librayName); 

    [DllImport("mylibrary")] 
    public static extern void InitMyLibrary(); 
} 

은 당신과 같이 프리로드 루틴의 일부 형태로 위를 호출 할 수

public void LoadDllFile(string dllfolder, string libname) { 
    var currentpath = new StringBuilder(255); 
    UnsafeNativeMethods.GetDllDirectory(currentpath.Length, currentpath); 

    // use new path 
    UnsafeNativeMethods.SetDllDirectory(dllfolder); 

    UnsafeNativeMethods.LoadLibrary(libname); 

    // restore old path 
    UnsafeNativeMethods.SetDllDirectory(currentpath); 
} 

당신은 다음과 같이 호출 될 수 있습니다

LoadDllFile("c:\whatever", "mylibrary.dll"); 
+0

Norton에게 감사드립니다. 그러나 최종 사용자에게는 DLL에 대한 지식이 없습니다. 이 접근 방식이이 시나리오에서 작동합니까? –

+1

게시 한 코드의 양은 * 길어야 필요 이상입니다. 필요한 것은'SetDllDirectory'뿐입니다. P/Invoke 마샬 러가 나머지 작업을 수행하게하십시오. 자세한 내용과 샘플 코드는 [my answer here] (http://stackoverflow.com/a/8861895/366904)를 참조하십시오. –

+0

@Deepak 최종 사용자가 DLL의 위치를 ​​모르는 경우 어떻게 찾습니까? 당신은 파일 시스템을 검색 한 다음 이것을 사용합니다. – IanNorton