Question

J'ai écrit un petit utilitaire qui me permet de changer d'un simple AppSetting pour le fichier App.config d'une autre application, puis enregistrez les modifications:

 //save a backup copy first.
 var cfg = ConfigurationManager.OpenExeConfiguration(pathToExeFile);
 cfg.SaveAs(cfg.FilePath + "." + DateTime.Now.ToFileTime() + ".bak"); 

 //reopen the original config again and update it.
 cfg = ConfigurationManager.OpenExeConfiguration(pathToExeFile);
 var setting = cfg.AppSettings.Settings[keyName];
 setting.Value = newValue;

 //save the changed configuration.
 cfg.Save(ConfigurationSaveMode.Full); 

Cela fonctionne bien, sauf pour un effet secondaire. Le fichier .config nouvellement enregistré perd tous les commentaires XML d'origine, mais seulement dans la zone AppSettings. Est-il possible de conserver des commentaires XML de la zone AppSettings de fichier de configuration d'origine?

Voici un pastebin de la source complète si vous souhaitez compiler rapidement et l'exécuter.

Était-ce utile?

La solution

Je sautais dans Reflector.Net et regardé à la source décompilé pour cette classe. La réponse courte est non, il ne conservera pas les commentaires. La façon dont Microsoft a écrit la classe est de générer un document XML à partir des propriétés sur la classe de configuration. Étant donné que les commentaires ne se présentent pas dans la classe de configuration, ils ne font pas de nouveau dans le XML.

Et ce qui ne fait qu'empirer est que Microsoft scellé toutes ces classes afin que vous ne pouvez pas obtenir une nouvelle classe et insérez votre propre implémentation. Votre seule option est de déplacer les commentaires en dehors de la section AppSettings ou utiliser des classes XmlDocument ou XDocument pour analyser les fichiers de configuration à la place.

Désolé. Ceci est un cas limite que Microsoft n'a tout simplement pas prévu pour.

Autres conseils

Voici un exemple de fonction que vous pouvez utiliser pour enregistrer les commentaires. Il vous permet d'éditer une paire clé / valeur à la fois. J'ai aussi ajouté quelques trucs pour mettre en forme le fichier bien basé sur la façon dont je l'utilise souvent les fichiers (Vous pouvez facilement supprimer que si vous voulez). J'espère que cela pourrait aider quelqu'un d'autre à l'avenir.

public static bool setConfigValue(Configuration config, string key, string val, out string errorMsg) {
    try {
        errorMsg = null;
        string filename = config.FilePath;

        //Load the config file as an XDocument
        XDocument document = XDocument.Load(filename, LoadOptions.PreserveWhitespace);
        if(document.Root == null) {
            errorMsg = "Document was null for XDocument load.";
            return false;
        }
        XElement appSettings = document.Root.Element("appSettings");
        if(appSettings == null) {
            appSettings = new XElement("appSettings");
            document.Root.Add(appSettings);
        }
        XElement appSetting = appSettings.Elements("add").FirstOrDefault(x => x.Attribute("key").Value == key);
        if (appSetting == null) {
            //Create the new appSetting
            appSettings.Add(new XElement("add", new XAttribute("key", key), new XAttribute("value", val)));
        }
        else {
            //Update the current appSetting
            appSetting.Attribute("value").Value = val;
        }


        //Format the appSetting section
        XNode lastElement = null;
        foreach(var elm in appSettings.DescendantNodes()) {
            if(elm.NodeType == System.Xml.XmlNodeType.Text) {
                if(lastElement?.NodeType == System.Xml.XmlNodeType.Element && elm.NextNode?.NodeType == System.Xml.XmlNodeType.Comment) {
                    //Any time the last node was an element and the next is a comment add two new lines.
                    ((XText)elm).Value = "\n\n\t\t";
                }
                else {
                    ((XText)elm).Value = "\n\t\t";
                }
            }
            lastElement = elm;
        }

        //Make sure the end tag for appSettings is on a new line.
        var lastNode = appSettings.DescendantNodes().Last();
        if (lastNode.NodeType == System.Xml.XmlNodeType.Text) {
            ((XText)lastNode).Value = "\n\t";
        }
        else {
            appSettings.Add(new XText("\n\t"));
        }

        //Save the changes to the config file.
        document.Save(filename, SaveOptions.DisableFormatting);
        return true;
    }
    catch (Exception ex) {
        errorMsg = "There was an exception while trying to update the config value for '" + key + "' with value '" + val + "' : " + ex.ToString();
        return false;
    }
}

Si les commentaires sont critiques, il pourrait juste être que votre seule option est de lire et enregistrer le fichier manuellement (via XmlDocument ou la nouvelle API liées LINQ). Si toutefois ces commentaires ne sont pas critiques, je les laisse partir soit ou peut-être envisager de les intégrer comme (quoique redondante) éléments de données.

Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top