代码之家  ›  专栏  ›  技术社区  ›  Shalom Craimer

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

  •  7
  • Shalom Craimer  · 技术社区  · 14 年前

    我想 暂时地 将目录添加到dll搜索路径-在Windows 7下是否有正确的方法执行此操作?

    脚本

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

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

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

    根据 this article ,将目录添加到 PATH 还应将其添加到查找dll的目录中。

    该解决方案在Windows XP中工作正常:如果我将目录添加到 路径 动态链接库加载,程序运行正常。如果不添加目录,则不会加载DLL,因为“未找到”错误而失败。

    但是,这不适用于Windows7。

    所以我想,我们试着用 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仍然无法加载。

    最后,如果我设置 路径 包括 c:\MyPATH 手动,在运行应用程序之前-一切正常!DLL加载,运行正常。

    因此,要重新迭代:

    有没有正确的方法 暂时地 在Windows7下的dll搜索路径中添加目录?

    更新: 使用ProcessExplorer,我检查了应用程序的运行时环境,并且“c:\mypath”确实在 路径 !而且,我看到了 Helper.dll 在打开的句柄列表中(作为一个dll,而不仅仅是一个文件),它仍然声称没有找到它。

    3 回复  |  直到 13 年前
        1
  •  2
  •   Community Ian Goodfellow    7 年前

    可以使用“assemblyresolve”事件将自定义dll加载逻辑添加到C_app。

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

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

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

        2
  •  1
  •   MQS    14 年前

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

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

    如果有,至少你知道从哪里开始…

        3
  •  0
  •   Shalom Craimer    14 年前

    我的解决办法很简单,但我觉得求助于它很荒谬。

    我已经编写了另一个程序集“shell”,它修改了环境,运行WonderApp,然后退出。

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

    看起来是这样的:

    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));
          }
       }
    }
    

    我希望我能找到更好的解决办法!