在 .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 中指定邮政编码?