临时将目录添加到Windows 7的DLL搜索路径

时间:2010-06-08 14:41:12

标签: c# windows-7 dllimport

我想暂时将目录添加到DLL搜索路径 - 在Windows 7下有正确的方法吗?

方案

我有一个C#应用程序,我们称之为WonderApp。

WonderApp需要调用位于C:\MyPath的C ++ DLL。因此,作为WonderApp的Program.Main()的一部分,我添加了以下命令:

Environment.SetEnvironmentVariable("PATH",
   "C:\\MyPath;" + Environment.GetEnvironmentVariable("PATH"));

根据this article,向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搜索路径中?

UPDATE:使用Process Explorer,我检查了应用程序的运行时环境,“C:\ MyPath”确实在PATH中!此外,我看到Helper.dll位于打开句柄列表中(作为DLL,而不仅仅是文件) - 它仍声称不会找到它。

3 个答案:

答案 0 :(得分:2)

您可以使用“AssemblyResolve”事件将自定义DLL加载逻辑添加到C#应用程序。

此页面有一个很好的摘要,代码示例为:http://support.microsoft.com/kb/837908

正如您所做的那样,我发现更改正在运行的C#应用​​程序的PATH环境变量不会影响DLL搜索行为。也许AppDomain在启动时缓存PATH值?您可以使用AssemblyResolve事件解决此问题。

另见How to add folder to assembly search path at runtime in .NET?

答案 1 :(得分:1)

我认为这与许可问题有关。

尝试关闭UAC并再次运行代码。检查更新路径是否有效。

如果确实如此,至少你知道从哪里开始...

答案 2 :(得分:0)

我的解决方案很简单,但我觉得这很荒谬。

我写了另一个程序集“Shell”,它修改了Environment,运行了WonderApp,然后退出。

通过在运行主应用程序(WonderApp)之前修改PATH,主应用程序的DLL搜索路径包括添加到修改后的PATH的目录。

看起来像这样:

namespace shell
{
   static class program
   {
      [dllimport("kernel32.dll", charset = charset.auto, setlasterror = true)]
      public static extern bool setenvironmentvariable(string lpname, string lpvalue);

      private static string joinargstosinglestring(string[] args)
      {
         string s = string.empty;
         for (int i = 0; i < args.length; ++i)
         {
            if (!string.isnullorempty(s))
            {
               s += " ";
            }
            s += "\"" + args[i] + "\"";
         }
         return s;
      }

      [stathread]
      static void main(string[] args)
      {    
         string pathbefore = environment.getenvironmentvariable("path");
         string wewant = util.paths.getapplicationdatadir() + ";" + pathbefore;
         setenvironmentvariable("path", wewant);

         Process process = Process.Start(".\\WonderApp.exe", joinArgsToSingleString(args));
      }
   }
}

我希望我能找到更好的解决方案!