5

J'ai un code de bibliothèque qui est utilisé à partir de mon application et qui est également utilisé par une action personnalisée .NET dans un projet d'installation Visual Studio. Le code de bibliothèque utilise à son tour le bloc de journalisation de la bibliothèque d'entreprise pour effectuer sa consignation. Comment puis-je obtenir des informations de configuration sur la bibliothèque d'entreprise dans le contexte de mon action personnalisée exécutée dans msiexec? Est-il possible d'amorcer le mécanisme de configuration dans le code avant de faire des appels à EntLib?Comment utiliser la journalisation de bibliothèque d'entreprise dans une action personnalisée .NET

Mise à jour: J'ai produit un hack qui semble que cela va fonctionner, mais repose sur la définition d'un champ statique non-publique en utilisant la réflexion. Il est dommage que EntLib soit si étroitement couplé au .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"); 

Mise à jour 2: Bien que bidouille fonctionne dans un banc d'essai, lorsqu'il est exécuté dans le contexte de msiexec, le chargeur de montage ne trouve pas les ensembles référencés dans le fichier de configuration. Fuslogvw indique que AppBase est le répertoire Windows system32, ce qui est logique. Ce que je ne comprends pas c'est pourquoi les dépendances manifestes de l'assembly d'actions personnalisées (qui se trouvent dans le répertoire [TargetDir] à côté de l'assembly d'actions personnalisées) sont trouvées, mais pas les assemblys chargés dynamiquement appelés dans le fichier de configuration. Je ne vois pas comment.

Répondre

0

Je ne sais pas si cela aide, mais vous pouvez écrire dans le journal msi à partir d'une action personnalisée. (VBScript exemple ci-dessous :)

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 

Plus d'informations à partir de MSDN: http://msdn.microsoft.com/en-us/library/aa371672.aspx

+0

Ouais, merci mais pas vraiment ce que je cherche. J'utilise le code de bibliothèque qui utilise la bibliothèque d'entreprise. Je n'ai pas vraiment besoin de me connecter, c'est simplement que le code profondément imbriqué utilisant l'entlib essaie de s'initialiser à partir de config. – jlew

0

J'ai eu un problème similaire avec msiexec ne pas être en mesure de charger une action personnalisés dépendances actuellement ma solution est de copier les assemblages dépendants dans la répertoire système. C'est une solution terrible, mais cela fonctionne.

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

Une autre option consisterait à installer les assemblys de bibliothèque d'entreprise dans le GAC. Si vous faites cela, vous devrez éditer le msi en utilisant quelque chose comme Orca pour que le programme d'installation soit installé dans le GAC avant d'exécuter les actions personnalisées par défaut, les actions personnalisées étant exécutées en premier.

Je cherche toujours une solution vraiment bien à ce sujet et je mettrai à jour cette réponse quand je trouve.

1

Il n'y a aucun moyen d'utiliser la méthode standard app.config parce que app.config est le msiexec.config vous devez modifier avant d'exécuter votre MSI. Ma recommandation serait d'avoir votre propre méthode de chargement de configuration qui lit à partir d'un XML personnalisé ou des valeurs dans le MSI.

+0

Ne semble pas possible avec la bibliothèque d'entreprise. – jlew

1

Je crois que le problème est que votre assembly d'actions personnalisées est chargé dans le LoadFrom context, de sorte que ses dépendances manifestes sont résolues par rapport à sa base de code.

Vous pourriez être en mesure de résoudre ce problème en créant une nouvelle AppDomain. Cela vous donnera l'occasion de réinitialiser votre répertoire de base, charger un nouveau fichier App.config, et ainsi de suite. Utilisez AppDomain.CreateDomain(String, Evidence, AppDomainSetup) pour créer le nouvel AppDomain, en renseignant le AppDomainSetup properties pour ApplicationBase, ConfigurationFile, etc.

0

Cela peut aider les personnes qui ont encore des problèmes avec les programmes d'installation VS: il est possible d'utiliser des assemblys chargés dynamiquement à partir d'une action personnalisée, il suffit d'aider l'exécution à localiser les assemblages.

La façon dont vous le faire est de traiter l'événement AppDomain.AssemblyResolve.Je l'ai fait sur la méthode Install de ma classe d'installation, comme ceci:

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... 
    } 
} 

Je recommande la lecture de la MS Docs page on implementing the handler ainsi.

Questions connexes