简体   繁体   中英

How to read/update <runtime> element in machine.config?

As per this issue I am attempting to make a method that will check the current state of the machine.config file (to see if the runtime alterations exist) and if not, to update or remove them. My current solution is using XmlDocument to write, but my attempts at checking for existing elements on the next run always returns null or 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

My second attempt was to use Linq to XML to look for the data, but not knowing how that really works I couldn't get any results:

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

My third attempt was to use the ConfigurationManager class to read the file, but whereas I was able to open the file and read it I could only get my hands on the runtime element, but not any of the contained information. At best I have been able to check the raw xml data:

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

Since I didn't see any built-in support for the runtime element (like it does for AppSettings ) I tried to create a custom configuration section ( view that code here ) but have been unable to do anything with it:

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

SO, that being said, how can I check the machine.config file to make sure the element changes are not already in place?

After speaking with a colleague, we were able to work out a solution. In order to access the existing elements we have to set up a namespace manager:

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

From there it's very straight forward to grabbing the elements using XPath, you just have to include the namespace:

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

If you're looking to add elements all at once, the sub elements do not need to have the namespace appended (since it apparently knows that it's all under the same namespace). However, if you're looking to add to a file that is already partially there, it's best to explicitly include the namespace; otherwise it will see that a namespace exists and assume your lack of namespace was intentional, adding an extra blank namespace attribute that can cause things to not work ().

Keep in mind creating elements requires the namespace to be a string:

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

My ultimate goal was to use this to update the machine.config file during an installation only if it was necessary (to avoid duplicates). For the full solution please feel free to look here .

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM