如何在machine.config?</runtime>中读取/更新<runtime>元素

时间:2013-11-15 17:30:28

标签: c# .net c#-4.0

根据this issue我试图创建一个方法来检查machine.config文件的当前状态(以查看是否存在运行时更改),如果没有,则更新或删除它们。我的current solution正在使用XmlDocument来编写,但是我在下次运行时检查现有元素的尝试总是返回null或false:

XmlDocument doc = new XmlDocument();
doc.Load(file);
Console.WriteLine(null == doc.SelectSingleNode("/configuration"))); //true
Console.WriteLine(null == 
    doc.SelectSingleNode("/configuration/runtime"))); //true
Console.WriteLine(null == 
    doc.SelectSingleNode("/configuration/runtime/assemblyBinding"))); //false

我的第二次尝试是使用Linq to XML来查找数据,但不知道它是如何工作的,我无法得到任何结果:

XDocument doc = XDocument.Load(RuntimeEnvironment.SystemConfigurationFile);
var data = from item in root.Descendants("assemblyIdentity") select el;

var foo = doc.Descendants("assemblyIdentity")
    .Attributes("publicKeyToken")
    .Where(x => x.Value == @"b03f5f7f11d50a3a")
    .ToList();

Console.WriteLine(foo.Count); //shows 0

我的第三次尝试是使用ConfigurationManager class来读取文件,但是我能够打开文件并阅读它,我只能抓住运行时元素,而不是任何包含的信息。我最多能够检查原始xml数据:

Configuration machineConfig =
    ConfigurationManager.OpenMachineConfiguration();

ConfigurationFileMap configFile =
    new ConfigurationFileMap(machineConfig.FilePath);

Configuration config =
    ConfigurationManager.OpenMappedMachineConfiguration(
        configFile);

ConfigurationSectionCollection sections =
    config.Sections;

ConfigurationSection runtime = config.GetSection("runtime");

Console.WriteLine(runtime.SectionInformation.GetRawXml()
    .Contains("System.Runtime")); //true

由于我没有看到对运行时元素的任何内置支持(就像AppSettings那样)我尝试创建custom configuration sectionview that code here),但一直无法用它做任何事情:

RuntimeSection runtimeSection = (RuntimeSection)config.GetSection("runtime");
Console.WriteLine(runtimeSection.SectionInformation.GetRawXml()); //nothing

那么,话虽如此,我如何检查machine.config文件以确保元素更改尚未到位?

1 个答案:

答案 0 :(得分:0)

在与同事交谈后,我们能够找到解决方案。为了访问现有元素,我们必须设置命名空间管理器:

XmlNamespaceManager nsmgr = new XmlNamespaceManager(doc.NameTable);
nsmgr.AddNamespace("bind", "urn:schemas-microsoft-com:asm.v1");

从那里开始使用XPath抓取元素非常简单,你只需要包含命名空间:

doc.SelectSingleNode("//bind:assemblyBinding", nsmgr);

如果您希望一次性添加元素,则子元素不需要附加名称空间(因为它显然知道它们都在同一名称空间下)。但是,如果您要添加到已经部分存在的文件中,最好明确包含命名空间;否则它会看到一个名称空间存在并假设您缺少名称空间是有意的,添加一个额外的空白名称空间属性,可能导致事情不起作用()。

请记住,创建元素需要命名空间为字符串:

ParentElement.AppendChild(xmlDoc.CreateElement("subElement",
  nsmgr.LookupNamespace("bind"))

我的最终目标是在安装过程中使用它来更新machine.config文件(如果有必要)(以避免重复)。如需完整解决方案,请随意look here