Временное добавление каталога в пути поиска Windows 7 DLL - PullRequest
7 голосов
/ 08 июня 2010

Я хочу временно добавить каталог в пути поиска DLL - есть ли правильный способ сделать это в Windows 7?

Сценарий

У меня есть приложение на C #, назовем его WonderApp.

WonderApp необходимо вызвать DLL C ++, расположенную в C:\MyPath.Поэтому, как часть Program.Main() WonderApp, я добавил следующую команду:

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

Согласно этой статье , добавление каталога в PATH также должно добавить его в каталогипоиск DLL.

Решение отлично работает в Windows XP: если я добавлю каталог в PATH, DLL загрузится, и программа будет работать нормально.Если я не добавлю каталог, DLL не загрузится, что приведет к ошибке «not found».

Однако, это не работает для 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 загружается и работает очень хорошо.

Итак, еще раз:

Есть ли правильный способ временно добавить каталог в пути поиска DLL вWindows 7?

ОБНОВЛЕНИЕ: Используя Process Explorer, я проверил среду выполнения приложения, и "C: \ MyPath" действительно был в PATH!Кроме того, я увидел, что Helper.dll был в списке открытых дескрипторов (как DLL, а не просто файл) - и он все еще утверждал, что не нашел его.

Ответы [ 3 ]

2 голосов
/ 22 августа 2011

Вы можете добавить пользовательскую логику загрузки DLL в приложение C #, используя событие AssemblyResolve.

На этой странице есть хорошее резюме с примерами кода: http://support.microsoft.com/kb/837908

Как и вы, я обнаружил, что изменение переменной среды PATH работающего приложения C # не влияет на поведение поиска DLL. Возможно, AppDomain кэширует значение PATH при запуске? Вы можете использовать событие AssemblyResolve, чтобы обойти это.

См. Также Как добавить папку в путь поиска сборки во время выполнения в .NET?

1 голос
/ 08 июня 2010

Я думаю, что это связано с проблемами с разрешениями.

Попробуйте выключить UAC и снова запустить свой код. Проверьте, работает ли обновление пути.

Если это так, по крайней мере, вы знаете, с чего начать ...

0 голосов
/ 09 июня 2010

Мое решение простое, но я чувствую себя нелепо, прибегая к нему.

Я написал другую сборку, "Shell", которая изменяет среду, запускает WonderApp и завершает работу.

Изменяя PATH перед запуском основного приложения (WonderApp), путь поиска 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));
      }
   }
}

Хотелось бы найти лучшее решение!

...