在 .NET 中指定 DllImport 的搜索路径

Posted

技术标签:

【中文标题】在 .NET 中指定 DllImport 的搜索路径【英文标题】:Specify the search path for DllImport in .NET 【发布时间】:2011-02-21 07:44:00 【问题描述】:

有没有办法为使用 DllImport 导入的给定程序集指定要搜索的路径?

[DllImport("MyDll.dll")]
static extern void Func();

这将在应用程序目录和 PATH 环境变量中搜索 dll。但有时 dll 会放在其他地方。是否可以在 app.config 或 manifest 文件中指定此信息以避免动态加载和动态调用?

【问题讨论】:

【参考方案1】:

在您第一次调用导入的函数之前,使用您的附加 DLL 路径调用 SetDllDirectory

P/Invoke 签名:

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

要设置多个额外的 DLL 搜索路径,请修改 PATH 环境变量,例如:

static void AddEnvironmentPaths(string[] paths)

    string path = Environment.GetEnvironmentVariable("PATH") ?? string.Empty;
    path += ";" + string.Join(";", paths);

    Environment.SetEnvironmentVariable("PATH", path);

有更多关于 DLL 搜索顺序的信息here on MSDN。


更新 2013/07/30:

以上使用Path.PathSeparator的更新版本:

static void AddEnvironmentPaths(IEnumerable<string> paths)

    var path = new[]  Environment.GetEnvironmentVariable("PATH") ?? string.Empty ;

    string newPath = string.Join(Path.PathSeparator.ToString(), path.Concat(paths));

    Environment.SetEnvironmentVariable("PATH", newPath);

【讨论】:

谢谢,从静态构造函数调用 SetDllDirectory 后效果很好。 AFAIK,不幸的是这并不能解决多个额外搜索目录的问题。 @Stefan,请参阅我修改后的添加多个目录的答案。 谢谢。我认为这是我们能得到的最好的。 你最好使用Path.PathSeparator 【参考方案2】:

在第一次调用导入的函数之前,尝试使用您的附加 DLL 路径调用 AddDllDirectory

如果您的 Windows 版本低于 8,您将需要安装 this patch,它使用 Windows 7、2008 R2、2008 和 Vista 缺少的 AddDllDirectory 函数扩展了 API(虽然没有针对 XP 的补丁)。

【讨论】:

听起来不错,但 DllImport 应该是什么样子? 这是一个更好的解决方案,因为与公认的答案不同,当应用程序作为 Microsoft Store 应用程序(UWP 或打包的 Win32 应用程序作为 UWP)运行时,此 API 也能正常工作。 Microsoft Store 应用程序接受的答案将失败,因为操作系统将当前环境列表阻止到 UWP 应用程序。所以 DllImport 将无法看到带有 dll 的路径。要在 C# 中使用它,您可以通过以下方式复制导入此 API:[DllImport("kernel32.dll", CharSet = CharSet.Auto, SetLastError = true)] public static extern int AddDllDirectory(string lpPathName);【参考方案3】:

这可能有用DefaultDllImportSearchPathsAttribute Class 例如

[assembly: DefaultDllImportSearchPaths(DllImportSearchPath.UserDirectories)]

还请注意,您也可以使用AddDllDirectory,这样您就不会搞砸已经存在的任何东西:

[DllImport("kernel32.dll", SetLastError = true)]
static extern bool AddDllDirectory(string path);

【讨论】:

你能说明在哪里放置 [assembly:... 属性吗? 我相信它可以在任何地方。它无论如何都适用于程序集(全局适用于 .dll)。约定是将其放在.\Properties\AssemblyInfo.cs 文件中,其中. 是项目目录。它可能必须在任何 namespace 声明之外,或者这就是我遇到它或自己编写它时一直存在的地方。

以上是关于在 .NET 中指定 DllImport 的搜索路径的主要内容,如果未能解决你的问题,请参考以下文章

如何在 RSACryptoServiceProvider .NET 类中指定公钥

亚马逊:是不是可以在亚马逊搜索结果的 URL 中指定邮政编码?

如何在 devenv 任务中指定多个构建类型,CruiseControl.net

如何在 .NET 中指定控制台应用程序的退出代码?

如何在 ASP.NET 用户控件中指定 *.css 文件?

如何使用 protobuf-net 反序列化 .asmx webservice 中指定的对象