2009-12-28 15 views
8

Tenemos muchos productos y hay algunos DLL comunes en la aplicación de cada producto. Ahora copiamos cada DLL común en el directorio bin de cada producto y los tratamos como un ensamblado privado. Esto aumenta innecesariamente el tamaño de msi de cada producto y cuando ocurre un problema en una DLL, tenemos que compilar el msi de cada producto que comprende la DLL y desplegarlo.Una forma de cargar DLL desde el repositorio central

¿Hay alguna forma de indicar a la aplicación del producto que use un directorio privado común para ser utilizado para cargar archivos DLL [utilizando el esquema de manifiesto ...]? [Nota: La adición del directorio privado de env PATH no proporcionará una solución como si hay una DLL con el mismo nombre existe en el directorio SYSTEM, que llevaría el privilegio sobre nuestro directorio privado]

-Kartlee

Respuesta

1

Si usted está hablando de .NET, puede:

  • carga el archivo DLL directamente desde una base de datos mediante el uso de Assembly.Load(byte[])
  • mediante el uso de Assembly.TypeResolve caso
  • por utilizando TypeProvider clase
  • Al definir un directorio sonda en su archivo de configuración

igual:

<configuration> 
    <runtime> 
     <assemblyBinding xmlns="urn:schemas-microsoft-com:asm.v1"> 
      <probing privatePath="bin"/> 
     </assemblyBinding> 
    </runtime> 
</configuration> 
+0

Gracias por su respuesta. Lamentablemente, estoy buscando una aplicación C/C++ que no utilice ningún método de vinculación dinámica en tiempo de ejecución (como Loadlibrary (..)) por ejemplo. ¿Hay alguna forma de instruir a través de manifiestos como funciona el concepto de "sondeo"? – Kartlee

+0

@Kartlee, lo siento, no sé sobre C/C++; pero he editado su pregunta para reflejar las palabras clave –

0

no estoy seguro si esto es lo que estás buscando, pero donde trabajo ahora nos use una ruta UNC común para todas nuestras DLL.

Tenemos algo parecido a ...

\\ server01 \ productionLibrary para la producción de leer archivos DLL, cada uno en su propio directorio.

y

\\ server01 \ developmentLibrary que refleja la biblioteca de la producción y esto es lo que usan los desarrolladores a medida que desarrollan.

Cuando fusionamos el código después de completar la prueba, lo implementamos en la biblioteca de producción. Todos los proyectos hacen referencia a la biblioteca de producción cuando están integrados en archivos MSI para su implementación. Nuestro sistema automatizado construye los proyectos en MSI y verifica que todos los archivos DLL apuntan a la biblioteca de producción, por lo que no hay posibilidad de que use una copia de desarrollo accidentalmente.

Espero que esto ayude.

0

no estoy seguro de entender la pregunta correctamente, pero si estás en .Net, hay una caché de ensamblados global (GAC): http://en.wikipedia.org/wiki/Global_Assembly_Cache

Este almacena en caché los montajes y permite la reutilización de los mismos por las aplicaciones (como con el framework .net). Simplemente deberá registrar el ensamblaje en GAC en la instalación, por ejemplo, proporcionar una "instalación de su marco" con todos los ensamblajes comunes, y esto puede implementarse solo una vez.

+0

Gracias por su respuesta. Por favor, mira mi comentario a 'Rubens Farias'. – Kartlee

7

No especifica si su entorno es .NET o Win32 directo.

Supongo que es Win32 porque si su .NET las tecnologías para hacer esto están mucho más cerca en términos de cosas como Global Assembly Cache.

En términos de Win32 es posible cargar Dlls desde una ubicación compartida en una de dos maneras:

  • Uso LoadLibrary con rutas completas explícitos. Esto significa que no puede usar enlaces estáticos: todas las funciones dll utilizadas en todos los productos deberán accederse a través de GetProcAddress. No puede importar clases de C++ desde dll's cargadas a través de LoadLibrary; deben estar vinculadas estáticamente para funcionar, por lo que este enfoque puede o no ser viable. No es muy difícil escribir archivos de encabezado shim que se enmascaran como la interfaz del dll y hacer una carga justo a tiempo y GetProcAddress según sea necesario para cada llamada.

  • La otra opción es convertir los dll en lo que se denominan "ensambles uno al lado del otro" e instalarlos en la tienda WinSxS. No tengas miedo por el gran nombre. "conjunto lado a lado" significa "Un archivo Dll más archivo de manifiesto con información de versión". Cada una de las diversas aplicaciones pondría 'nombre seguro', que incluye información de la versión, en su manifiesto de aplicación para cada dll que use, y el cargador Dll Win32 usará esto para elegir la instancia correcta del dll común de la tienda WinSxS . El proceso básico se describe en el artículo de MSDN Guidelines for Creating Side-by-side Assemblies


En las versiones de Windows 6.1 y arriba (Windows Server 2008 y los 7 Windows irónicamente llamada) archivos de configuración de aplicaciones hacer ahora soportan el elemento de sondeo en Application Configuration Files

Esto significa que debe poder proporcionar una ruta de acceso (en relación con su aplicación) a una carpeta que contiene los ensamblados dll que desea cargar.


Ok, he hecho algunas pruebas en Windows 7, y esto funciona:

Asumiendo que tiene un APP1.EXE aplicación instalada en \ Archivos de programa \ App1, que depende de alguna thedll DLL común". DLL"

En la carpeta de aplicación (\ archivos de programa \ App1) crear un archivo App1.exe.config y darle el siguiente contenido: -

<configuration> 
    <windows> 
    <assemblyBinding xmlns="urn:schemas-microsoft-com:asm.v1"> 
     <probing privatePath="..\AcmeCommon"/> 
    </assemblyBinding> 
    </windows> 
</configuration> 

Ahora, cree una carpeta llamada \ Program F iles \ AcmeCommon, y en él una carpeta acme.thedll, y copie thedll.dll en \ Program Files \ AcmeCommon \ acme.thedll

Cree también un archivo en AcmeCommon \ acme.thedll llamado acme.thedll.manifest - this será el manifiesto de ensamblado que describe el montaje llamado 'acme.thedll'

el contenido de acme.thedll.manifest habrá: -

<assembly xmlns="urn:schemas-microsoft-com:asm.v1" manifestVersion="1.0"> 
    <assemblyIdentity name="acme.thedll" version="1.2.3.4" processorArchitecture="x86" type="win32"/> 
    <file name="thedll.dll"/> 
</assembly> 

Ahora tenemos la DLL común, en un lugar común, una asamblea sxs nativa. Tenemos la aplicación, con un archivo de configuración que, en el servidor de Windows 7 y 2008 (y superior) le indicará que busque ensambles en la ubicación común. Pero la aplicación todavía está tratando de vincular a la DLL como dll, en lugar de a través de un ensamblado.

Para que la aplicación cargue el ensamblaje, debemos agregar un archivo de manifiesto a la aplicación. Si está utilizando Visual Studio, sus aplicaciones probablemente ya estén configuradas para crear e incrustar manifiestos a través del enlazador y la configuración del proyecto de herramienta de manifiesto.En cuyo caso la forma más fácil de decir la aplicación de la asamblea es para reconstruirlo después de añadir el siguiente código a por lo menos un archivo de cabecera o C/CPP en el proyecto: -

#pragma comment(linker,"/manifestdependency:\"type='win32' name='acme.thedll' version='1.2.3.4' processorArchitecture='x86' language='*'\"") 

Si está utilizando una más antigua construir entorno donde los manifiestos son hechas a mano que se necesita para fusionar el siguiente código XML con app1.exe.manifest en la carpeta App1:

<dependency> 
    <dependentassembly> 
    <assemblyidentity type="win32" name="acme.thedll" version="1.2.3.4" processorArchitecture="x86" language="*"/> 
    </dependentassembly> 
</dependency> 

Esto debería cerrar el círculo: Cuando la aplicación carga el cargador de Win32 cargará el manifiesto de aplicación (app1.exe.manifest o incrustado como un recurso RT_MANIFEST) y aprenda sobre el ensamblado "acme.thedll". También cargará el archivo de configuración de la aplicación (app1.exe.config) y conocerá la ruta privada para buscar ensamblajes. Y luego cargará y agregará "acme.thedll.manifest" al "contexto de activación" de las aplicaciones. Luego, cuando el cargador intente cargar "thedll.dll" buscará el contexto de activación db, encontrará que está en el ensamblado acme.thedll y lo cargará desde la ubicación de los ensamblajes.

+0

Gracias por su comentario. Creo que respondí en mi publicación anterior que el enlace DLL de tiempo de ejecución no es una solución que estoy buscando. Al lado del concepto assmebly está bien, pero eso requiere uno para poner nuestras DLL personalizadas en el directorio de WinSXS y requiere privilegio de administrador. ¿Hay alguna manera de mantener la tienda privada en la instalación local y pedirle a toda mi aplicación de producto que la use en la tienda? ¿Hay alguna manera de especificar un directorio para ser utilizado de esta manera en el archivo de manifiesto? -Kartlee – Kartlee

+0

Desafortunadamente no. Las instalaciones privadas de montaje lado a lado son * solo * buscadas en la carpeta del exe. Traté de poner una ruta relativa a la dll en el nodo de archivo del manifiesto de ensamblaje, pero luego no se pudo cargar. Los archivos de configuración de Windows no son compatibles con el elemento de prueba de los archivos de configuración de estilo .NET. –

+0

En realidad, siempre que su sistema operativo de elección sea Windows 7 o Sever 2008, puede hacerlo. Ver la sección ammeded en mi respuesta. –

0

Esto puede no ayudarlo, pero ... PUEDE cargar dlls desde directorios arbitrarios Y aún confiar en un enlace dinámico normal a ellos, siempre y cuando pueda controlar cuándo los dlls se cargan mediante enlaces dinámicos y asegurarse de que tiene Ya cargó el dll explícitamente usando una ruta completa antes de que se cargue dinámicamente.

Esto solo puede ser útil si está escribiendo un sistema de complemento donde sus complementos están dinámicamente vinculados a archivos DLL que desea conservar en un directorio no estándar. Si sabe todo sobre las dlls a las que están vinculadas, puede cargar estas dlls directamente usando su ruta de acceso completa antes de cargar los dlls (complementos) que dependen de ellos dinámicamente. Como el dll ya está en la memoria cuando su plugin necesita localizarlo, usará la versión en la memoria. Puede descargar la carga explícita que hizo antes de cargar el complemento y está listo para comenzar.

Desafortunadamente esto no funcionará si su exe principal necesita cargar dlls de lugares arbitrarios ya que no puede entrar antes del proceso normal de carga dll.

1

Siguiendo la respuesta de Chris. Asegúrese de que la caja sea correcta en los manifiestos y las configuraciones. De lo contrario, fallarán. Pude conseguir cargar el ensamblado, pero no se eligió el archivo DLL. En mi caso, se elige una DLL de Windows en system32 en lugar de la mía con el mismo nombre. En Dependency Walker, mi archivo DLL está cargado, pero en el tiempo de ejecución, con Process Explorer, se carga la copia de Windows. ¿Algunas ideas?

Cuestiones relacionadas