开发者

Adding a directory temporarily to Windows 7's DLL search paths

开发者 https://www.devze.com 2023-01-02 12:53 出处:网络
I want to temporarily add a directory to the DLL search paths - is there a correct way to do this under Windows 7?

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 runnin开发者_Python百科g 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.


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?


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...


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 modified PATH.

It looks like this:

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

I wish I could find a better solution!

0

精彩评论

暂无评论...
验证码 换一张
取 消