Alterar la ruta de búsqueda de DLL para DLL estática

He buscado sugerencias sobre cómo puedo hacer esto, pero todo lo que encontré fue cómo redirigir una DLL SxS a la carpeta de la aplicación local. Esto es lo que quiero lograr: el (C ++) Application.exe está vinculado a un archivo DLL, Plugin.DLL (proyecto dependiente). Esta DLL no se coloca dentro del directorio de la aplicación, sino en una subcarpeta llamada “complementos”. Como el archivo DLL está vinculado de forma estática, la aplicación intentará cargarlo desde la carpeta de la aplicación.

¿Hay alguna manera de cómo puedo cambiar la ruta de búsqueda de esta DLL en particular? ¿A través de manifiestos o configuraciones de enlazador VS2008?

Lo primero que pensé es que si estás enlazando estáticamente un dll, no es un complemento. Simplemente coloque el dll en la carpeta EXE y termine con él. Esa es la configuración de implementación admitida por Windows para las DLL cargadas estáticamente.

Dicho esto, hay formas de lograr lo que quieres. Pero son en su mayoría estúpidos o complicados sin una buena razón: Sus opciones son:

  • No enlazar estáticamente. Use LoadLibrary (“plugins / Plugin.dll”) y GetProcAddress para acceder al contenido del complemento.
  • Agregue “la ruta a su carpeta de complementos” a la variable de entorno PATH del sistema.
  • Utilice el mecanismo de carga de retraso para retrasar el acceso a la funcionalidad de los complementos, establezca una función de ayuda personalizada que pueda cargar los dll (s) utilizando una ruta proporcionada.
  • Convierta la carpeta de complementos en un ensamblaje (creando un archivo .manifest en él que enumere plugin.dll). Agregue “complementos” como un ensamblaje dependiente a su aplicación. Ahora se verá en la carpeta de complementos.
  • Divida su aplicación en un stub exe y una parte cargada dinámicamente. En el stub exe, llame a SetDllDirectory para que apunte a la carpeta del complemento, luego llame a LoadLibrary pasando la ruta completa a “appstub.dll”.

Para convertir una carpeta, con uno o más dll en un “ensamblaje”, simplemente agregue un archivo a la carpeta con las carpetas name.manifest.

Entonces, plugins.manifest: –

    

Es una MUY buena idea asegurarse de que la carpeta y el nombre del dll sean diferentes, como si el nombre dll fuera el nombre del ensamblado. Windows comienza a mirar su archivo de manifiesto incrustado para obtener información sobre el ensamblado.

Suponiendo que está utilizando Visual Studio 7 o posterior, la siguiente directiva agregada a un archivo .c / .cpp o .h en el proyecto hará que su aplicación intente cargar dlls desde el ensamblado en lugar de solo el directorio local:

 #pragma comment(linker, "/manifestdependency:\"name='Plugins' "\ "processorArchitecture='*' version='1.0.0.0' "\ "type='win32'\"") 

Expandiendo y detallando la propuesta de Chris de un subdirectorio de “ensamblaje”:


Nota al margen: Chris también tiene dos excelentes escritos de más detalles:

  • Responda a la redirección de DLL usando manifiestos
  • Respuesta a Una forma de cargar DLL desde el repository central

    Esto también explica cómo puede aprovechar probing privatePath en los archivos de configuración de la aplicación para colocar los archivos DLL fuera de una subcarpeta.


MS documentos

En realidad, esto se llama una “Asamblea privada” y los documentos de MS lo explican de esta manera:

Los ensamblajes privados se instalan en una carpeta de la estructura de directorios de la aplicación. Normalmente, esta es la carpeta que contiene el archivo ejecutable de la aplicación. Los ensamblados privados se pueden implementar en la misma carpeta que la aplicación, en una carpeta con el mismo nombre que el ensamblado o en una subcarpeta específica del idioma con el mismo nombre que el ensamblado.

Por ejemplo (…)

Appdir\Microsoft.Tools.Pop\Microsoft.Tools.Pop.MANIFEST : el manifiesto se implementa como un archivo separado en una subcarpeta que tiene el nombre del ensamblado.

(…)

Los ensamblados privados se pueden instalar mediante cualquier método de instalación que pueda copiar el archivo del ensamblado en esta carpeta, como el comando xcopy .

El ejemplo

Tienes que eres un viejo ejecutable confiable en tu carpeta de progtwig C:\Test\Program\app.exe y quieres – en Load-Time – cargar tu archivo DLL desde la subcarpeta Plugins , es decir, C:\Test\Program\plugins\tool1.dll sin jugar con PATH o cualquier otra cosa.

Necesitas:

  • Compile app.exe con:

     #pragma comment(linker, "/manifestdependency:\"name='Plugins' version='1.0.0.0' type='win32'\"") // name, type and version seems to be the minimum info to get away with 

    Nota: En mi sistema de prueba es necesario comstackr / vincular esto, en lugar de usar un manifiesto externo ( app.exe.manifest ), aún no he descubierto por qué. (*un)

    Sin embargo, lo que también funciona es integrar / fusionar el archivo de manifiesto listado debajo en el ejecutable con la herramienta mt , en lugar de con el pragma enlazador. ( Configuration > Manifest Tool > Additional Manifest Files )

  • poner tool1.dll introducción a la subcarpeta de plugins

  • agregue un archivo plugins.manifest en la subcarpeta de complementos, es decir, C:\Test\Program\plugins\plugins.manifest y ese se verá así:

plugins.manifest:

      

Eso es. Al iniciar app.exe, se buscará automáticamente el dll en la subcarpeta en Load-Time.


(* a): La fusión de este archivo de manifiesto funciona, pero no puede usarlo como el único archivo de manifiesto externo, y sospecho que es porque le falta toda la información de manifiesto que el sistema de comstackción ya coloca en su ejecutable.