5

Tengo un código de biblioteca que se utiliza desde mi aplicación y también es utilizado por una acción personalizada de .NET en un proyecto de instalador de Visual Studio. El código de la biblioteca a su vez usa el bloque de registro Enterprise Library para hacer su registro. ¿Cómo puedo obtener información de configuración para Enterprise Library en el contexto de mi acción personalizada ejecutándose dentro de msiexec? ¿Es posible arrancar el mecanismo de configuración en el código antes de realizar cualquier llamada al EntLib?Cómo usar el registro de la biblioteca de la empresa en una acción personalizada de .NET

Actualización: He producido un truco que parece funcionar, pero se basa en establecer un campo estático no público mediante la reflexión. Es una pena que EntLib esté tan estrechamente vinculado al .NET ConfigurationManager.

var factory = new LogWriterFactory(new FakeConfigSource("foo.config")); 
var field = typeof (Logger).GetField("factory", BindingFlags.Static | BindingFlags.NonPublic); 
field.SetValue(null, factory); 
Logger.Write("Test"); 

Actualización 2: A pesar de que el truco funciona en un banco de pruebas, cuando se ejecuta en el contexto de msiexec, el cargador de montaje no encuentra los ensamblados de referencia en el archivo de configuración. Fuslogvw indica que AppBase es el directorio de windows system32, lo que tiene sentido. Lo que no entiendo es por qué se encuentran las dependencias de manifiesto del ensamblado de acción personalizado (que están en el directorio [TargetDir] junto con el ensamblaje de acción personalizado), pero los ensamblados cargados dinámicamente llamados en el archivo de configuración no lo son. No puedo ver ninguna forma de evitar esto.

Respuesta

0

No estoy seguro si esto ayuda, pero puede escribir en el registro msi desde una acción personalizada. a continuación (VBScript Muestra :)

Const msiMessageTypeInfo = &H04000000 
Const msiMessageTypeFatalExit = &H00000000 
Const msiMessageTypeError = &H01000000 
Const msiMessageTypeWarning = &H02000000 
Const msiMessageTypeUser = &H03000000 

Dim rec : Set rec = Session.Installer.CreateRecord(1) 
rec.StringData(1) = "Your log message." 

Session.Message msiMessageTypeInfo, rec 

Más información de MSDN: http://msdn.microsoft.com/en-us/library/aa371672.aspx

+0

Sí, gracias, pero no es realmente lo que estoy buscando. Estoy usando un código de biblioteca que usa la biblioteca de la empresa. En realidad, no necesito iniciar sesión en ninguna parte, es simplemente que el código profundamente anidado que usa entlib está intentando inicializarse desde la configuración. – jlew

0

He tenido un problema similar con msiexec no ser capaz de cargar un dependencias acciones personalizadas actualmente mi solución es copiar los ensamblados dependientes en el directorio del sistema Esta es una solución horrible pero funciona.

string installDir = System.IO.Path.GetDirectoryName(
       System.Reflection.Assembly.GetExecutingAssembly().Location); 
System.IO.File.Copy(
       System.IO.Path.Combine(installDir, "<Insert Assembly Name>.dll"), 
       System.IO.Path.Combine(Environment.SystemDirectory, "<Insert Assembly Name>.dll"), 
       true); 

Otra opción sería instalar los ensamblajes de la biblioteca de la empresa en la GAC. Si hace esto, tendrá que editar el msi usando algo como Orca para hacer que el instalador se instale en el GAC antes de que se ejecuten las acciones personalizadas, ya que las acciones personalizadas predeterminadas se ejecutan primero.

Todavía estoy buscando una solución muy buena para esto y actualizaré esta respuesta cuando la encuentre.

1

No hay forma de utilizar el método estándar app.config porque ese app.config es el msiexec.config que necesitaría editar antes de ejecutar su MSI. Mi recomendación sería tener su propio método de carga de configuración que lea desde un XML personalizado o valores en el MSI.

+0

No parece posible con la biblioteca de empresa. – jlew

1

Creo que el problema es que su conjunto de acción personalizada se está cargando en el LoadFrom context, por lo que sus dependencias de manifiesto se resuelven en relación con su base de código.

Puede resolver este problema creando un nuevo AppDomain. Esto le dará la oportunidad de restablecer su directorio base, cargar un nuevo archivo App.config, y así sucesivamente. Use AppDomain.CreateDomain(String, Evidence, AppDomainSetup) para crear el nuevo dominio de la aplicación, llenando el AppDomainSetup properties para ApplicationBase, ConfigurationFile, y así sucesivamente.

0

Esto podría ayudar a las personas que todavía se ocupan de los instaladores de VS: es posible usar ensamblajes cargados dinámicamente a partir de una acción personalizada, simplemente necesita ayudar al tiempo de ejecución a localizar los ensamblajes.

La forma de hacerlo es manejando el evento AppDomain.AssemblyResolve.Hice esto en el método Install de mi clase de instalación, así:

internal class MyInstaller : Installer 
{ 
    public override void Install(IDictionary stateSaver) 
    { 
     base.Install(stateSaver); 

     AppDomain.CurrentDomain.AssemblyResolve += (sender, args) => 
     { 
      // Resolve assemblies here, e.g.: 
      return 
       args.Name == "My.Assembly" 
       ? Assembly.LoadFrom(this.Context.Parameters["TARGETDIR"] + "\\My.Assembly.dll") 
       : null; 
     }; 

     // Continue install... 
    } 
} 

Yo recomendaría leer el MS Docs page on implementing the handler también.

Cuestiones relacionadas