| File: AppConfig\AppConfig.cs | Web Access |
| Project: src\msbuild\src\Tasks\Microsoft.Build.Tasks.csproj (Microsoft.Build.Tasks.Core) |
// Licensed to the .NET Foundation under one or more agreements. // The .NET Foundation licenses this file to you under the MIT license. using System; using System.IO; using System.Xml; using Microsoft.Build.Framework; #nullable disable namespace Microsoft.Build.Tasks { /// <summary> /// Read information from application .config files. /// </summary> internal sealed class AppConfig { /// <summary> /// Read the .config from a file. /// </summary> /// <param name="appConfigFilePath"></param> internal void Load(string appConfigFilePath) { XmlReader reader = null; try { var readerSettings = new XmlReaderSettings { DtdProcessing = DtdProcessing.Ignore, CloseInput = true }; // it's important to normalize the path as it may contain two slashes // see https://github.com/dotnet/msbuild/issues/4335 for details. appConfigFilePath = FileUtilities.NormalizePath(appConfigFilePath); // Need a filestream as the XmlReader doesn't support nonstandard unicode characters in path. // No need to dispose - as 'CloseInput' was passed to XmlReaderSettings FileStream fs = File.OpenRead(appConfigFilePath); #pragma warning disable CA2000 // Dispose objects before losing scope is suppressed because the reader is disposed in the finally block reader = XmlReader.Create(fs, readerSettings); #pragma warning restore CA2000 // Dispose objects before losing scope Read(reader); } catch (XmlException e) { int lineNumber = 0; int linePosition = 0; if (reader is IXmlLineInfo info) { lineNumber = info.LineNumber; linePosition = info.LinePosition; } throw new AppConfigException(e.Message, appConfigFilePath, lineNumber, linePosition, e); } catch (Exception e) when (ExceptionHandling.IsIoRelatedException(e)) { int lineNumber = 0; int linePosition = 0; if (reader is IXmlLineInfo info) { lineNumber = info.LineNumber; linePosition = info.LinePosition; } throw new AppConfigException(e.Message, appConfigFilePath, lineNumber, linePosition, e); } finally { reader?.Dispose(); } } /// <summary> /// Read the .config from an XmlReader /// </summary> /// <param name="reader"></param> internal void Read(XmlReader reader) { // Read the app.config XML while (reader.Read()) { // Look for the <runtime> section if (reader.NodeType == XmlNodeType.Element && StringEquals(reader.Name, "runtime")) { Runtime.Read(reader); } } } /// <summary> /// Access the Runtime section of the application .config file. /// </summary> internal RuntimeSection Runtime { get; } = new RuntimeSection(); /// <summary> /// App.config files seem to come with mixed casing for element and attribute names. /// If the fusion loader can handle this then this code should too. /// </summary> /// <param name="a"></param> /// <param name="b"></param> /// <returns></returns> internal static bool StringEquals(string a, string b) { return String.Equals(a, b, StringComparison.OrdinalIgnoreCase); } } }