2009-10-19 4 views
3

J'essaie d'appeler une action personnalisée dans mon projet de déploiement d'installation & pour mettre à jour certains éléments dans le app.config de mon application. J'ai enveloppé la section de configuration personnalisée de la manière habituelle, par exemple .:FileNotFoundException dans le programme d'installation et de déploiement Visual Studio lors de la tentative de chargement de la configuration personnalisée

[ConfigurationProperty("serviceProvider", IsRequired = true)] 
public string ServiceProvider 
{ 
    get { return (string)base["serviceProvider"]; } 
    set { base["dataProviderFactory"] = value; } 
} 

J'ai mis l'action personnalisée à appeler au cours de la section d'installation juste après l'installation base.Install (stateSaver). Le code est:

string exePath = string.Format("{0} MyApp.exe", Context.Parameters["DP_TargetDir"]); 
SysConfig.Configuration config = ConfigurationManager.OpenExeConfiguration(exePath); 
Configuration. MyApp section = Configuration.MyApp)config.GetSection("MyApp"); 

Quand je cours, j'obtiens cette erreur:

System.Configuration.ConfigurationErrorsException: An error occurred creating the configuration section handler for MyApp: Could not load file or assembly 'MyCompany. MyApp.Configuration' or one of its dependencies. The system cannot find the file specified. (C:\Program Files\MyCompany\MyApp\MyApp.exe.config line 5) ---> System.IO.FileNotFoundException: Could not load file or assembly 'MyCompany.MyApp.Configuration' or one of its dependencies. The system cannot find the file specified.

ligne 5 dans la configuration est:

<section name="MyApp" 
    type="MyCompany.MyApp.Configuration.MyApp, MyCompany.MyApp.Configuration" 
    requirePermission="false" /> 

La bibliothèque de classe avec le code d'installation (étant la seule classe dans cette bibliothèque) a une référence à l'ensemble de configuration.

Y at-il quelque chose de vraiment évident que je manque ici? Je ne peux pas comprendre pourquoi le ref de la config n'est pas trouvé.

Toute aide ou suggestion serait grandement appréciée.

+0

essai juste et il semble que le code est exécuté dans C: \ WINDOWS \ system32 donc cela pourrait être la raison pour laquelle il ne peut pas l'amende la configuration personnalisée Assemblée. –

Répondre

7

J'ai réussi à trouver du code sur MSDN qui fournit un moyen de travailler (quoique piraté) pour ce faire. Le lien est ici: ConfigurationManager, custom config, and installutil/path searching problem.

Je ne l'aurais pas trouvé si ce n'est pour pouvoir déboguer avec l'aide de suggestions, donc merci à vous deux pour cela.

Pour référence, mon code final d'installation est:

public override void Install(IDictionary stateSaver) 
{ 
    base.Install(stateSaver); 

    string targetDirectory = Context.Parameters["DP_TargetDir"]; 
    stateSaver.Add("TargetDir", targetDirectory); 

    string exePath = Path.Combine(targetDirectory, "MyApp.exe"); 

    System.Diagnostics.Debugger.Break(); 

    ResolveEventHandler tempResolveEventHandler = 
     (sender, args) => 
      { 
       string simpleName = new AssemblyName(args.Name).Name; 
       string path = Path.Combine(targetDirectory, simpleName + ".dll"); 
       return File.Exists(path) 
        ? Assembly.LoadFrom(path) 
        : null; 
      }; 

    try 
    { 
     // hook up asm resolve handler 
     AppDomain.CurrentDomain.AssemblyResolve += tempResolveEventHandler; 

     System.Configuration.Configuration config = ConfigurationManager.OpenExeConfiguration(exePath); 
     Configuration.MyApp section = (Configuration.MyApp) config.Sections["MyApp"]; 

     if (section != null) 
     { 
      // "ApplicationSettings.DefaultDatabasePath" is the custom config value I'm updating 
      section.ApplicationSettings.DefaultDatabasePath = Environment.GetFolderPath(Environment.SpecialFolder.CommonApplicationData); 
      config.Save(); 
     } 
    } 
    finally 
    { 
     // remove asm resolve handler. 
     AppDomain.CurrentDomain.AssemblyResolve -= tempResolveEventHandler; 
    } 

} 
+0

Merci beaucoup pour cette solution. J'ai une application qui configure les sections de configuration, mais à travers un système de plug-in, c'est-à-dire qu'elles ne sont pas référencées par l'application pendant la construction. Je suis tombé sur cette exception fichue FileNotFound en les accédant à la configuration, mais grâce à votre solution, je peux maintenant les résoudre correctement, et tout réussit! – Alex

1

Vérifiez que 'MyCompany.MyApp.Configuration' est marqué avec copy local = true.

Vérifiez également que votre projet fait également référence aux dll dont dépendent MyCompany.MyApp.Configuration.

+0

Copy local est défini sur true et toutes les références requises ont été référencées autant que je peux voir. Si j'exécute le code en dehors de la classe de l'installateur (via une application de console), cela fonctionne correctement. –

1

Le projet d'installation appelle toutes les classes d'installation trouvées dans les fichiers d'assembly de projet.

Je dois admettre que j'ai tendance à remplacer la méthode Install dans la classe Installer.

est ici une coupe directe et coller à partir du code que j'ai ici:

public override void Install(System.Collections.IDictionary stateSaver) 
{ 
    base.Install(stateSaver); 

    // System.Diagnostics.Debugger.Break(); 
    string targetDirectory = Context.Parameters["targetdir"]; 

    string param1 = Context.Parameters["Param1"]; 
    string param2 = Context.Parameters["Param2"]; 
    string param3 = Context.Parameters["Param3"]; 
    string param4 = Context.Parameters["Param4"]; 

    string exePath = string.Format("{0}AlarmMonitor.exe", "[SystemFolder]"); 

    PHPCCTVClassLibrary.CctvSite site = new PHPCCTVClassLibrary.CctvSite(); 
    site.Name = param1; 
    site.EndPoint = string.Format(@"tcp://{0}:5005", param2); 
    site.Password = param4; 
    site.Username = param3; 
    site.AutoReconnect = true; 
    site.AlarmHandling = new PHPCCTVClassLibrary.CctvSiteAlarmHandling(); 
    site.AlarmHandling.Audio = new PHPCCTVClassLibrary.AudioSetup(); 
    site.AlarmHandling.Audio.AlarmAddedFile = "alarmadded.wav"; 
    site.AlarmHandling.Audio.AlarmDeletedFile = "alarmdeleted.wav"; 
    site.AlarmHandling.Audio.AlarmUpdatedFile = "alarmupdated.wav"; 

    PHPCCTVClassLibrary.CctvSites sites = new PHPCCTVClassLibrary.CctvSites(); 
    sites.Site = new PHPCCTVClassLibrary.CctvSite[] { site }; 
    System.Xml.Serialization.XmlSerializer serializer = new System.Xml.Serialization.XmlSerializer(typeof(PHPCCTVClassLibrary.CctvSites)); 
    //System.Diagnostics.Debugger.Break(); 

    System.IO.TextWriter tw = new System.IO.StreamWriter(@"CCTVAlarmConfig.xml", false); 
    serializer.Serialize(tw, sites); 
    tw.Close(); 

} 

Il crée un fichier de configuration XML, être appelé par une action personnalisée qui fonctionne à l'installation et a la CustomActionData suivante:/Param1 = "[EDITA1]"/Param2 = "[EDITA2]"/Param3 = "[EDITA3]"/Param4 = "[EDITA4]"/targetdir = "[TARGETDIR]"

EDITA1 etc proviennent d'une interface utilisateur avec 4 zones de texte. J'ai délibérément inclus un espace après [TARGETDIR] car sans lui vous obtiendrez un comportement assez étrange car il ne peut pas alors trouver le répertoire d'installation.

Le commentaire System.Diagnostics.Debugger.Break() vous permet de déboguer à partir de ce point si la ligne n'est pas commentée.

+0

Salut, merci pour l'exemple de code. Je pense que le problème est plus à faire avec la lecture du fichier XML de configuration existant dans le type d'objet. L'indice sur le débogueur devrait être une aide massive, merci. –

Questions connexes