2010-06-08 8 views
7

Quiero temporalmente agregar un directorio a las rutas de búsqueda de DLL - ¿hay una forma correcta de hacerlo en Windows 7?Agregando un directorio temporalmente a las rutas de búsqueda de DLL de Windows 7

Escenario

Tengo una aplicación C#, vamos a llamarlo WonderApp.

WonderApp necesita llamar a C++ DLL, que se encuentra en C:\MyPath. Por lo tanto, como parte de WonderApp de Program.Main(), añadí el siguiente comando:

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

Según this article, la adición de un directorio a la PATH también debe agregarlo a la búsqueda de directorios de archivos DLL.

La solución funciona bien en Windows XP: si agrego el directorio al PATH, la DLL se carga y el programa funciona bien. Si no agrego el directorio, la DLL no se carga, pero falla con un error "no encontrado".

Sin embargo, esto no funciona para Windows 7.

Así que pensé, vamos a probar usando SetDllDirectory(). De esta manera:

[System.Runtime.InteropServices.DllImport("kernel32.dll", SetLastError = true)] 
private static extern bool SetDllDirectory(string lpPathName); 

Y, más adelante:

bool success = SetDllDirectory(Util.Paths.GetApplicationDataDir()); 

El valor de success es true, pero la DLL todavía no se puede cargar.

Finalmente, si configuro el PATH para incluir PATH manualmente, antes de ejecutar la aplicación, ¡todo funciona! La DLL se carga y funciona perfectamente.

lo tanto, para reiterar:

¿Hay una manera correcta de temporalmente añadir un directorio para las rutas de búsqueda de DLL en Windows 7?

ACTUALIZACIÓN: Utilizando Process Explorer, verifiqué el entorno de ejecución de la aplicación, y "C: \ MyPath" estaba realmente en el PATH! Además, vi que Helper.dll estaba en la lista de identificadores abiertos (como un archivo DLL, no solo como un archivo) y aún así afirmó no encontrarlo.

+0

¿Es esta la versión de 64 bits de Windows? ¿Cuál es el verdadero nombre de ruta? –

+0

Esto es Windows 7 Home de 32 bits. Y la ruta completa a la DLL es C: \ MyPath \ Helper.dll – scraimer

+0

tal vez falten otros dlls intente cargando helper.dll en el programa "depends.exe" y verifique las dependencias de otros dlls. – OlimilOops

Respuesta

0

Mi solución es simple, pero me siento ridícula recurrir a ella.

He escrito otro ensamblaje, "Shell", que modifica el entorno, ejecuta WonderApp y sale.

Al modificar PATH antes de ejecutar la aplicación principal (WonderApp), la ruta de búsqueda de la DLL de la aplicación principal incluye los directorios agregados al PATH modificado.

Parece que este:

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

Me gustaría poder encontrar una mejor solución!

1

Estoy pensando que tiene que ver con los problemas de permisos.

Intenta apagar el UAC y ejecuta tu código nuevamente. Verifique si la actualización de la ruta funcionó.

Si lo hiciera, al menos sabes por dónde empezar ...

+0

No, apagar el UAC no funcionó. Gracias por la idea, sin embargo. – scraimer

2

Puede agregar una lógica de carga DLL personalizada a una aplicación C# utilizando el evento 'AssemblyResolve'.

Esta página tiene un buen resumen, con ejemplos de código: http://support.microsoft.com/kb/837908

Al igual que hizo, he encontrado que el cambio de la variable de entorno PATH de un C# aplicación en ejecución no afecta el comportamiento de búsqueda de DLL. ¿Quizás AppDomain almacena en caché el valor PATH al inicio? Puede usar el evento AssemblyResolve para solucionar este problema.

Ver también How to add folder to assembly search path at runtime in .NET?

+0

Eso es * increíble * !!! ¡Muchas gracias por avisarme! Parece que funcionaría en cualquier ensamblado .NET, pero también necesito probar esto para archivos DLL que no sean .NET. – scraimer

+1

OK, malas noticias: Funciona solo para ensamblados .NET. Lo cual tiene perfecto sentido, teniendo en cuenta su nombre. Es una solución maravillosa, pero no puedo usarla, ya que las DLL que necesito cargar no son ensamblados .NET. (Y para empeorar las cosas, esas DLL también necesitan cargar otras DLL, que están ubicadas en el mismo directorio con ellas, así que necesitaría encontrar una manera de hacer que busquen allí también). – scraimer

Cuestiones relacionadas