我想暂时向 DLL 搜索路径添加一个目录 - 在 Windows 7 下是否有正确的方法来执行此操作?
场景
我有一个 C# 应用程序,我们将其称为 WonderApp。
WonderApp 需要调用位于 C:\MyPath
中的 C++ DLL。因此,作为 WonderApp 的 Program.Main()
的一部分,我添加了以下命令:
Environment.SetEnvironmentVariable("PATH",
"C:\\MyPath;" + Environment.GetEnvironmentVariable("PATH"));
根据 本文,将一个目录添加到 PATH
中,也应该将其添加到 DLL 搜索目录中。
该解决方案在 Windows XP 中运行良好:如果我将目录添加到 PATH
中,DLL 就会加载并且程序运行正常。如果我不添加目录,DLL 将不会加载,并会出现“未找到”错误。
但是,这不适用于 Windows 7。
所以我想,让我们尝试使用 SetDllDirectory()
。像这样:
[System.Runtime.InteropServices.DllImport("kernel32.dll", SetLastError = true)]
private static extern bool SetDllDirectory(string lpPathName);
然后,稍后:
bool success = SetDllDirectory(Util.Paths.GetApplicationDataDir());
success
的值为 true
,但 DLL 仍然无法加载。
最后,如果我在运行应用程序之前手动将 PATH
设置为包含 C:\MyPath
- 一切正常! DLL 加载并运行得很好。
那么,重申一下:
在 Windows 7 下,有没有正确的方法可以临时将目录添加到 DLL 搜索路径中?
更新:使用 Process Explorer,我检查了应用程序的运行时环境,“C:\MyPath”确实位于 PATH
中!此外,我看到 Helper.dll
位于打开句柄列表中(作为 DLL,而不仅仅是文件) - 但它仍然声称找不到它。
I want to temporarily add a directory to the DLL search paths - is there a correct way to do this under Windows 7?
Scenario
I've got a C# application, let's call it WonderApp.
WonderApp needs to call a C++ DLL, located in C:\MyPath
. So as part of WonderApp's Program.Main()
, I added the following command:
Environment.SetEnvironmentVariable("PATH",
"C:\\MyPath;" + Environment.GetEnvironmentVariable("PATH"));
According to this article, adding a directory to the PATH
should also add it to the directories search for DLLs.
The solution works fine in Windows XP: if I add the directory to the PATH
, the DLL loads and the program works just fine. If I don't add the directory, the DLL doesn't load, failing with a "not found" error.
However, this doesn't work for Windows 7.
So I figured, let's try using SetDllDirectory()
. Like this:
[System.Runtime.InteropServices.DllImport("kernel32.dll", SetLastError = true)]
private static extern bool SetDllDirectory(string lpPathName);
And, later on:
bool success = SetDllDirectory(Util.Paths.GetApplicationDataDir());
The value of success
is true
, but the DLL still fails to load.
Finally, if I set the PATH
to include C:\MyPath
manually, before running the application - it all works! The DLL loads, and runs just fine.
So, to re-iterate:
Is there a correct way to temporarily add a directory to the DLL search paths under Windows 7?
UPDATE: Using Process Explorer, I checked the application's run-time Environment, and "C:\MyPath" was indeed in the PATH
! Furthermore, I saw that Helper.dll
was in the list of open handles (as a DLL, not just a file) - and it still claimed not to find it.
发布评论
评论(3)
您可以使用“AssemblyResolve”事件将自定义 DLL 加载逻辑添加到 C# 应用程序。
此页面有一个很好的摘要,其中包含代码示例: http://support.microsoft.com/kb/837908
正如您所做的那样,我发现更改正在运行的 C# 应用程序的 PATH 环境变量不会影响 DLL 搜索行为。也许 AppDomain 在启动时缓存了 PATH 值?您可以使用 AssemblyResolve 事件来解决此问题。
另请参阅如何在 .NET 运行时将文件夹添加到程序集搜索路径?
You can add custom DLL loading logic to a C# app using the 'AssemblyResolve' event.
This page has a good summary, with code samples: http://support.microsoft.com/kb/837908
Just as you did, I have found that changing the PATH environment variable of a running C# app does not affect the DLL search behaviour. Perhaps the AppDomain caches the PATH value at startup? You can use the AssemblyResolve event to work around this.
See also How to add folder to assembly search path at runtime in .NET?
我认为这与权限问题有关。
尝试关闭 UAC 并再次运行您的代码。检查更新路径是否有效。
如果确实如此,至少您知道从哪里开始......
I am thinking it has to do with permission problems.
Try turning off UAC and running your code again. Check to see if updating the path worked.
If it did, at least you know where to start...
我的解决方案很简单,但我觉得诉诸它很荒谬。
我编写了另一个程序集“Shell”,它修改环境、运行 WonderApp,然后退出。
通过在运行主应用程序 (WonderApp) 之前修改
PATH
,主应用程序的 DLL 搜索路径包括添加到修改后的PATH
的目录。看起来像这样:
我希望我能找到更好的解决方案!
My solution is simple, but I feel ridiculous resorting to it.
I've written another assembly, "Shell", that modifies the Environment, runs WonderApp, and exits.
By modifying the
PATH
before running the main application (WonderApp), the main application's DLL search-path includes the directories added to the modifiedPATH
.It looks like this:
I wish I could find a better solution!