C#: 如何知道DllImport中使用的DLL的完整路径?

5
我已经在我的代码中导入了dll,方法如下:
[DllImport("dll.dll", CharSet = CharSet.Ansi)]
    private static extern int function(String pars, StringBuilder err);

我曾经惊讶于函数能够运行,但它既不在项目内,也不在Debug或Release文件夹中。也就是说,“dll.dll”应该不可用,因为它不在当前项目文件夹中,但实际上它是可用的。现在我想知道运行时使用的dll的确切完整路径,但不知道如何获取。


3
这可能会有用:动态链接库搜索顺序。我认为在使用P/Invoke时同样适用。然而,它并未说明如何确定已加载的dll文件名;-) - user166390
1
@pst:您应该将其发布为答案,因为...那就是答案。 - Ed S.
3个回答

8

您需要使用win32 API。

首先使用GetModuleHandle,将"dll.dll"传递给它。然后将该句柄传递给GetModuleFileName

string GetDllPath()
{
      const int MAX_PATH = 260;
      StringBuilder builder = new StringBuilder(MAX_PATH);
      IntPtr hModule = GetModuleHandle("dll.dll");  // might return IntPtr.Zero until 
                                                    // you call a method in  
                                                    // dll.dll causing it to be 
                                                    // loaded by LoadLibrary

      Debug.Assert(hModule != IntPtr.Zero);
      uint size = GetModuleFileName(hModule, builder, builder.Capacity);
      Debug.Assert(size > 0);
      return builder.ToString();   // might need to truncate nulls
}

    [DllImport("kernel32.dll", CharSet=CharSet.Auto)]
    public static extern IntPtr GetModuleHandle(string lpModuleName);

    [DllImport("kernel32.dll", SetLastError=true)]
    [PreserveSig]
    public static extern uint GetModuleFileName
    (
        [In] IntPtr hModule,        
        [Out] StringBuilder lpFilename,        
        [In][MarshalAs(UnmanagedType.U4)] int nSize
    );

4
请参阅动态链接库搜索顺序 -- 对于P/Invoke来说应该是正确的,但是行为可能会因加载方法而稍有不同。不过它没有说明如何确定已加载DLL的文件名;-)

这是一种完全未经测试、可能不明智的解决方案,用于在运行时查找DLL路径。这假设P/Invoke和LoadLibrary使用相同的解析方式(例如,P/Invoke不使用带有LOAD_WITH_ALTERED_SEARCH_PATH的LoadLibraryEx),并且此方法没有可怕的冲突。

  1. 使用LoadLibraryLoadLibaryEx加载DLL。

  2. 使用步骤#1中获取的句柄,使用GetModuleFileName查找模块的文件名。

  3. 使用FreeLibrary卸载模块。P/Invoke应该保持模块引用计数> 0,但同样未经测试;-)

以上解决方案的正确性和有效性不能得到保证。欢迎提出建议、警告和/或更正。结果因人而异。

编程愉快。


1

如果你真的想找出来,使用dependency-walker

它甚至可以在运行时“监视”你的应用程序并检测动态加载,以便没有任何东西被隐藏。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接