diff --git a/src/libraries/System.Configuration.ConfigurationManager/System.Configuration.ConfigurationManager.sln b/src/libraries/System.Configuration.ConfigurationManager/System.Configuration.ConfigurationManager.sln index 88ac5e88510295..1e57b6f6cba176 100644 --- a/src/libraries/System.Configuration.ConfigurationManager/System.Configuration.ConfigurationManager.sln +++ b/src/libraries/System.Configuration.ConfigurationManager/System.Configuration.ConfigurationManager.sln @@ -1,4 +1,8 @@ -Microsoft Visual Studio Solution File, Format Version 12.00 + +Microsoft Visual Studio Solution File, Format Version 12.00 +# Visual Studio Version 17 +VisualStudioVersion = 17.2.32317.152 +MinimumVisualStudioVersion = 10.0.40219.1 Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "TestUtilities", "..\Common\tests\TestUtilities\TestUtilities.csproj", "{15012FB4-9C7C-4DE0-AB44-83A64654D738}" EndProject Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Microsoft.Win32.SystemEvents", "..\Microsoft.Win32.SystemEvents\ref\Microsoft.Win32.SystemEvents.csproj", "{C7D1410B-8CF0-48DB-A0DF-C8E3A341FD12}" @@ -39,6 +43,10 @@ Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "src", "src", "{A3B7282E-7D6 EndProject Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "gen", "gen", "{BFBE3E0E-4E75-4665-A373-132D283D366D}" EndProject +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "System.Diagnostics.EventLog", "..\System.Diagnostics.EventLog\ref\System.Diagnostics.EventLog.csproj", "{C70C30E4-56DC-44FA-B621-9BB4C4E365D0}" +EndProject +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "System.Diagnostics.EventLog", "..\System.Diagnostics.EventLog\src\System.Diagnostics.EventLog.csproj", "{808D1F6A-2605-4BEB-A64B-0D09CDE558C8}" +EndProject Global GlobalSection(SolutionConfigurationPlatforms) = preSolution Debug|Any CPU = Debug|Any CPU @@ -109,27 +117,37 @@ Global {E34EBFC8-D1BC-4ED7-8335-C183A5994EE1}.Debug|Any CPU.Build.0 = Debug|Any CPU {E34EBFC8-D1BC-4ED7-8335-C183A5994EE1}.Release|Any CPU.ActiveCfg = Release|Any CPU {E34EBFC8-D1BC-4ED7-8335-C183A5994EE1}.Release|Any CPU.Build.0 = Release|Any CPU + {C70C30E4-56DC-44FA-B621-9BB4C4E365D0}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {C70C30E4-56DC-44FA-B621-9BB4C4E365D0}.Debug|Any CPU.Build.0 = Debug|Any CPU + {C70C30E4-56DC-44FA-B621-9BB4C4E365D0}.Release|Any CPU.ActiveCfg = Release|Any CPU + {C70C30E4-56DC-44FA-B621-9BB4C4E365D0}.Release|Any CPU.Build.0 = Release|Any CPU + {808D1F6A-2605-4BEB-A64B-0D09CDE558C8}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {808D1F6A-2605-4BEB-A64B-0D09CDE558C8}.Debug|Any CPU.Build.0 = Debug|Any CPU + {808D1F6A-2605-4BEB-A64B-0D09CDE558C8}.Release|Any CPU.ActiveCfg = Release|Any CPU + {808D1F6A-2605-4BEB-A64B-0D09CDE558C8}.Release|Any CPU.Build.0 = Release|Any CPU EndGlobalSection GlobalSection(SolutionProperties) = preSolution HideSolutionNode = FALSE EndGlobalSection GlobalSection(NestedProjects) = preSolution {15012FB4-9C7C-4DE0-AB44-83A64654D738} = {3393D976-CAF0-47D0-850E-7A44DF892122} - {9476F50F-E44C-4420-96AB-448259A47C4F} = {3393D976-CAF0-47D0-850E-7A44DF892122} {C7D1410B-8CF0-48DB-A0DF-C8E3A341FD12} = {751DA007-D916-4F22-AF16-85F343C2992C} - {6F662E39-BB56-4BCF-B053-B4A1782A33E1} = {751DA007-D916-4F22-AF16-85F343C2992C} - {6B586A50-5DFE-4FBE-A65B-9152B992C2E1} = {751DA007-D916-4F22-AF16-85F343C2992C} - {1C48B652-BA62-4D46-9CDD-24A1670EE3E3} = {751DA007-D916-4F22-AF16-85F343C2992C} - {CFF7519C-4D41-4713-991D-27777DA2DB21} = {751DA007-D916-4F22-AF16-85F343C2992C} - {3278A0F9-8E0A-42E1-8FE3-1A01851A6248} = {751DA007-D916-4F22-AF16-85F343C2992C} {D54AFFF7-9BEE-42C8-89C3-96E7228A23FA} = {A3B7282E-7D62-48ED-B5FC-E6AB32DA6F0A} + {6F662E39-BB56-4BCF-B053-B4A1782A33E1} = {751DA007-D916-4F22-AF16-85F343C2992C} {7C9D7BE4-BF9C-486C-8ADF-53DE282E018A} = {A3B7282E-7D62-48ED-B5FC-E6AB32DA6F0A} + {9476F50F-E44C-4420-96AB-448259A47C4F} = {3393D976-CAF0-47D0-850E-7A44DF892122} + {6B586A50-5DFE-4FBE-A65B-9152B992C2E1} = {751DA007-D916-4F22-AF16-85F343C2992C} {E49D2841-A288-4B5F-89FC-857CCE0401F0} = {A3B7282E-7D62-48ED-B5FC-E6AB32DA6F0A} + {355B775A-BFE1-4384-BC83-C6B5D1FB77BB} = {BFBE3E0E-4E75-4665-A373-132D283D366D} + {66EC63BC-99DC-40CA-B53B-B4D8BF6D1630} = {BFBE3E0E-4E75-4665-A373-132D283D366D} + {1C48B652-BA62-4D46-9CDD-24A1670EE3E3} = {751DA007-D916-4F22-AF16-85F343C2992C} {7B2CA04A-9DFB-471E-B4CB-1937D0049B96} = {A3B7282E-7D62-48ED-B5FC-E6AB32DA6F0A} + {CFF7519C-4D41-4713-991D-27777DA2DB21} = {751DA007-D916-4F22-AF16-85F343C2992C} {2BE20C4A-C20B-4A0C-8E4A-31B681B6967D} = {A3B7282E-7D62-48ED-B5FC-E6AB32DA6F0A} + {3278A0F9-8E0A-42E1-8FE3-1A01851A6248} = {751DA007-D916-4F22-AF16-85F343C2992C} {E34EBFC8-D1BC-4ED7-8335-C183A5994EE1} = {A3B7282E-7D62-48ED-B5FC-E6AB32DA6F0A} - {355B775A-BFE1-4384-BC83-C6B5D1FB77BB} = {BFBE3E0E-4E75-4665-A373-132D283D366D} - {66EC63BC-99DC-40CA-B53B-B4D8BF6D1630} = {BFBE3E0E-4E75-4665-A373-132D283D366D} + {C70C30E4-56DC-44FA-B621-9BB4C4E365D0} = {751DA007-D916-4F22-AF16-85F343C2992C} + {808D1F6A-2605-4BEB-A64B-0D09CDE558C8} = {A3B7282E-7D62-48ED-B5FC-E6AB32DA6F0A} EndGlobalSection GlobalSection(ExtensibilityGlobals) = postSolution SolutionGuid = {942CAD8E-C19B-4B9A-BEDE-09B43F45F535} diff --git a/src/libraries/System.Configuration.ConfigurationManager/ref/System.Configuration.ConfigurationManager.csproj b/src/libraries/System.Configuration.ConfigurationManager/ref/System.Configuration.ConfigurationManager.csproj index 58e634cc9634ee..82439a81b78185 100644 --- a/src/libraries/System.Configuration.ConfigurationManager/ref/System.Configuration.ConfigurationManager.csproj +++ b/src/libraries/System.Configuration.ConfigurationManager/ref/System.Configuration.ConfigurationManager.csproj @@ -8,6 +8,7 @@ + diff --git a/src/libraries/System.Configuration.ConfigurationManager/ref/System.Configuration.ConfigurationManager.netcoreapp.cs b/src/libraries/System.Configuration.ConfigurationManager/ref/System.Configuration.ConfigurationManager.netcoreapp.cs new file mode 100644 index 00000000000000..3fffb8cd3951d8 --- /dev/null +++ b/src/libraries/System.Configuration.ConfigurationManager/ref/System.Configuration.ConfigurationManager.netcoreapp.cs @@ -0,0 +1,13 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. +// ------------------------------------------------------------------------------ +// Changes to this file must follow the https://aka.ms/api-review process. +// ------------------------------------------------------------------------------ + +namespace System.Diagnostics +{ + public static partial class TraceConfiguration + { + public static void Register() { } + } +} diff --git a/src/libraries/System.Configuration.ConfigurationManager/src/Resources/Strings.resx b/src/libraries/System.Configuration.ConfigurationManager/src/Resources/Strings.resx index 29f880277d1335..de9cd14cb77b88 100644 --- a/src/libraries/System.Configuration.ConfigurationManager/src/Resources/Strings.resx +++ b/src/libraries/System.Configuration.ConfigurationManager/src/Resources/Strings.resx @@ -664,4 +664,34 @@ The file name '{0}' was already in the collection. + + Could not create listener '{0}'. + + + Could not create {0}. + + + Could not find type for class {0}. + + + Could not find constructor for class {0}. + + + switchType needs to be a valid class name. It can't be empty. + + + The specified type, '{0}' is not derived from the appropriate base type, '{1}'. + + + 'switchValue' and 'switchName' cannot both be specified on source '{0}'. + + + A listener with no type name specified references the sharedListeners section and cannot have any attributes other than 'Name'. Listener: '{0}'. + + + Listener '{0}' does not exist in the sharedListeners section. + + + initializeData needs to be valid for this TraceListener. + diff --git a/src/libraries/System.Configuration.ConfigurationManager/src/System.Configuration.ConfigurationManager.csproj b/src/libraries/System.Configuration.ConfigurationManager/src/System.Configuration.ConfigurationManager.csproj index 74dcf5f95c4532..2badd2c37adec6 100644 --- a/src/libraries/System.Configuration.ConfigurationManager/src/System.Configuration.ConfigurationManager.csproj +++ b/src/libraries/System.Configuration.ConfigurationManager/src/System.Configuration.ConfigurationManager.csproj @@ -252,18 +252,28 @@ System.Configuration.ConfigurationManager - + - + - + + + + + + + + + + + + + + @@ -271,6 +281,10 @@ System.Configuration.ConfigurationManager + + + + diff --git a/src/libraries/System.Configuration.ConfigurationManager/src/System/Configuration/ImplicitMachineConfigHost.cs b/src/libraries/System.Configuration.ConfigurationManager/src/System/Configuration/ImplicitMachineConfigHost.cs index 36e4cd1786f3b3..665ef24e47c262 100644 --- a/src/libraries/System.Configuration.ConfigurationManager/src/System/Configuration/ImplicitMachineConfigHost.cs +++ b/src/libraries/System.Configuration.ConfigurationManager/src/System/Configuration/ImplicitMachineConfigHost.cs @@ -81,6 +81,7 @@ public override Stream OpenStreamForRead(string streamName)
+
diff --git a/src/libraries/System.Configuration.ConfigurationManager/src/System/Diagnostics/DiagnosticsConfiguration.cs b/src/libraries/System.Configuration.ConfigurationManager/src/System/Diagnostics/DiagnosticsConfiguration.cs new file mode 100644 index 00000000000000..868298fa7f7476 --- /dev/null +++ b/src/libraries/System.Configuration.ConfigurationManager/src/System/Diagnostics/DiagnosticsConfiguration.cs @@ -0,0 +1,213 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. + +using System.Configuration; +using System.Runtime.Versioning; + +namespace System.Diagnostics +{ + internal static class DiagnosticsConfiguration + { + private static volatile SystemDiagnosticsSection s_configSection; + private static volatile InitState s_initState = InitState.NotInitialized; + + // Setting for Switch.switchSetting + internal static SwitchElementsCollection SwitchSettings + { + get + { + Initialize(); + SystemDiagnosticsSection configSectionSav = s_configSection; + return configSectionSav?.Switches; + } + } + + internal static string ConfigFilePath + { + [ResourceExposure(ResourceScope.Machine)] + [ResourceConsumption(ResourceScope.Machine)] + get + { + Initialize(); + SystemDiagnosticsSection configSectionSav = s_configSection; + if (configSectionSav != null) + { + return configSectionSav.ElementInformation.Source; + } + + return string.Empty; // the default + } + } + + // Setting for TraceInternal.AutoFlush + internal static bool AutoFlush + { + get + { + Initialize(); + SystemDiagnosticsSection configSectionSav = s_configSection; + if (configSectionSav != null && configSectionSav.Trace != null) + { + return configSectionSav.Trace.AutoFlush; + } + + return false; // the default + } + } + + // Setting for TraceInternal.UseGlobalLock + internal static bool UseGlobalLock + { + get + { + Initialize(); + SystemDiagnosticsSection configSectionSav = s_configSection; + if (configSectionSav != null && configSectionSav.Trace != null) + { + return configSectionSav.Trace.UseGlobalLock; + } + + return true; // the default + } + } + + // Setting for TraceInternal.IndentSize + internal static int IndentSize + { + get + { + Initialize(); + SystemDiagnosticsSection configSectionSav = s_configSection; + if (configSectionSav != null && configSectionSav.Trace != null) + { + return configSectionSav.Trace.IndentSize; + } + + return 4; // the default + } + } + + internal static ListenerElementsCollection SharedListeners + { + get + { + Initialize(); + SystemDiagnosticsSection configSectionSav = s_configSection; + return configSectionSav?.SharedListeners; + } + } + + internal static SourceElementsCollection Sources + { + get + { + Initialize(); + SystemDiagnosticsSection configSectionSav = s_configSection; + return configSectionSav?.Sources; + } + } + + internal static SystemDiagnosticsSection SystemDiagnosticsSection + { + get + { + Initialize(); + return s_configSection; + } + } + + private static SystemDiagnosticsSection GetConfigSection() + { + return s_configSection ??= (SystemDiagnosticsSection)PrivilegedConfigurationManager.GetSection("system.diagnostics"); + } + + internal static bool IsInitializing() => s_initState == InitState.Initializing; + internal static bool IsInitialized() => s_initState == InitState.Initialized; + + internal static bool CanInitialize() => (s_initState != InitState.Initializing) && + !ConfigurationManagerInternalFactory.Instance.SetConfigurationSystemInProgress; + + internal static void Initialize() + { + // Ported from https://referencesource.microsoft.com/#System/compmod/system/diagnostics/DiagnosticsConfiguration.cs,188 + // This port removed the lock on TraceInternal.critSec since that is now in a separate assembly and TraceInternal + // is internal and because GetConfigSection() is not locked elsewhere such as for connection strings. + + // Because some of the code used to load config also uses diagnostics + // we can't block them while we initialize from config. Therefore we just + // return immediately and they just use the default values. + if (s_initState != InitState.NotInitialized || + ConfigurationManagerInternalFactory.Instance.SetConfigurationSystemInProgress) + { + return; + } + + s_initState = InitState.Initializing; // used for preventing recursion + try + { + s_configSection = GetConfigSection(); + } + finally + { + s_initState = InitState.Initialized; + } + } + + internal static void Refresh() + { + ConfigurationManager.RefreshSection("system.diagnostics"); + + // There might still be some persistant state left behind for + // ConfigPropertyCollection (for ex, swtichelements), probably for perf. + // We need to explicitly cleanup any unrecognized attributes that we + // have added during last deserialization, so that they are re-added + // during the next Config.GetSection properly and we get a chance to + // populate the Attributes collection for re-deserialization. + // Another alternative could be to expose the properties collection + // directly as Attributes collection (currently we keep a local + // hashtable which we explicitly need to keep in sycn and hence the + // cleanup logic below) but the down side of that would be we need to + // explicitly compute what is recognized Vs unrecognized from that + // collection when we expose the unrecognized Attributes publically + SystemDiagnosticsSection configSectionSav = s_configSection; + if (configSectionSav != null) + { + if (configSectionSav.Switches != null) + { + foreach (SwitchElement swelem in configSectionSav.Switches) + { + swelem.ResetProperties(); + } + } + + if (configSectionSav.SharedListeners != null) + { + foreach (ListenerElement lnelem in configSectionSav.SharedListeners) + { + lnelem.ResetProperties(); + } + } + + if (configSectionSav.Sources != null) + { + foreach (SourceElement srelem in configSectionSav.Sources) + { + srelem.ResetProperties(); + } + } + } + + s_configSection = null; + + s_initState = InitState.NotInitialized; + Initialize(); + } + + private enum InitState + { + NotInitialized, + Initializing, + Initialized + } + } +} diff --git a/src/libraries/System.Configuration.ConfigurationManager/src/System/Diagnostics/FilterElement.cs b/src/libraries/System.Configuration.ConfigurationManager/src/System/Diagnostics/FilterElement.cs new file mode 100644 index 00000000000000..6067c06dc5a6e2 --- /dev/null +++ b/src/libraries/System.Configuration.ConfigurationManager/src/System/Diagnostics/FilterElement.cs @@ -0,0 +1,37 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. + +using System.Runtime.CompilerServices; + +namespace System.Diagnostics +{ + internal sealed class FilterElement : TypedElement + { + private static ConditionalWeakTable s_initData = new(); + + public FilterElement() : base(typeof(TraceFilter)) { } + + public TraceFilter GetRuntimeObject() + { + TraceFilter newFilter = (TraceFilter)BaseGetRuntimeObject(); + s_initData.AddOrUpdate(newFilter, InitData); + return newFilter; + } + + internal TraceFilter RefreshRuntimeObject(TraceFilter filter) + { + if (Type.GetType(TypeName) != filter.GetType() || InitDataChanged(filter)) + { + // Type or initdata changed. + _runtimeObject = null; + return GetRuntimeObject(); + } + else + { + return filter; + } + } + + private bool InitDataChanged(TraceFilter filter) => !s_initData.TryGetValue(filter, out string previousInitData) || InitData != previousInitData; + } +} diff --git a/src/libraries/System.Configuration.ConfigurationManager/src/System/Diagnostics/ListenerElementsCollection.cs b/src/libraries/System.Configuration.ConfigurationManager/src/System/Diagnostics/ListenerElementsCollection.cs new file mode 100644 index 00000000000000..04a54960bcc91d --- /dev/null +++ b/src/libraries/System.Configuration.ConfigurationManager/src/System/Diagnostics/ListenerElementsCollection.cs @@ -0,0 +1,372 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. + +using System.Collections; +using System.Collections.Generic; +using System.Collections.Specialized; +using System.Configuration; +using System.Reflection; +using System.Runtime.CompilerServices; +using System.Xml; + +namespace System.Diagnostics +{ + [ConfigurationCollection(typeof(ListenerElement))] + internal class ListenerElementsCollection : ConfigurationElementCollection + { + public new ListenerElement this[string name] => (ListenerElement)BaseGet(name); + + public override ConfigurationElementCollectionType CollectionType => ConfigurationElementCollectionType.AddRemoveClearMap; + + protected override ConfigurationElement CreateNewElement() => new ListenerElement(true); + + protected override object GetElementKey(ConfigurationElement element) => ((ListenerElement)element).Name; + + public IEnumerable GetRuntimeObject() + { + List listeners = new(); + + foreach (ListenerElement element in this) + { + // At some point, we need to pull out adding/removing the 'default' DefaultTraceListener + // code from here in favor of adding/not-adding after we load the config (in TraceSource + // and in static Trace). + + listeners.Add(element.GetRuntimeObject()); + } + + return listeners; + } + + protected internal override void InitializeDefault() => InitializeDefaultInternal(); + + internal void InitializeDefaultInternal() + { + ListenerElement defaultListener = new ListenerElement(false); + defaultListener.Name = "Default"; + defaultListener.TypeName = typeof(DefaultTraceListener).FullName; + defaultListener._isAddedByDefault = true; + + BaseAdd(defaultListener); + } + + protected override void BaseAdd(ConfigurationElement element) + { + ListenerElement listenerElement = element as ListenerElement; + + Debug.Assert((listenerElement != null), "adding elements other than ListenerElement to ListenerElementsCollection?"); + + if (listenerElement.Name.Equals("Default") && listenerElement.TypeName.Equals(typeof(DefaultTraceListener).FullName)) + BaseAdd(listenerElement, false); + else + BaseAdd(listenerElement, ThrowOnDuplicate); + } + } + + // This is the collection used by the sharedListener section. It is only slightly different from ListenerElementsCollection. + // The differences are that it does not allow remove and clear, and that the ListenerElements it creates do not allow + // references. + [ConfigurationCollection(typeof(ListenerElement), + AddItemName = "add", + CollectionType = ConfigurationElementCollectionType.BasicMap)] + internal sealed class SharedListenerElementsCollection : ListenerElementsCollection + { + public override ConfigurationElementCollectionType CollectionType => ConfigurationElementCollectionType.BasicMap; + protected override ConfigurationElement CreateNewElement() => new ListenerElement(false); + protected override string ElementName => "add"; + } + + internal sealed class ListenerElement : TypedElement + { + private static readonly ConfigurationProperty s_propFilter = new("filter", typeof(FilterElement), null, ConfigurationPropertyOptions.None); + private static readonly ConfigurationProperty s_propName = new("name", typeof(string), null, ConfigurationPropertyOptions.IsRequired | ConfigurationPropertyOptions.IsKey); + private static readonly ConfigurationProperty s_propOutputOpts = new("traceOutputOptions", typeof(TraceOptions), TraceOptions.None, ConfigurationPropertyOptions.None); + + private ConfigurationProperty _propListenerTypeName; + private bool _allowReferences; + private StringDictionary _attributes; + internal bool _isAddedByDefault; + + private static ConditionalWeakTable s_initData = new(); + + public ListenerElement(bool allowReferences) : base(typeof(TraceListener)) + { + _allowReferences = allowReferences; + + ConfigurationPropertyOptions flags = ConfigurationPropertyOptions.None; + if (!_allowReferences) + flags |= ConfigurationPropertyOptions.IsRequired; + + _propListenerTypeName = new ConfigurationProperty("type", typeof(string), null, flags); + + _properties.Remove("type"); + _properties.Add(_propListenerTypeName); + _properties.Add(s_propFilter); + _properties.Add(s_propName); + _properties.Add(s_propOutputOpts); + } + + public StringDictionary Attributes => _attributes ?? new StringDictionary(); + + [ConfigurationProperty("filter")] + public FilterElement Filter => (FilterElement)this[s_propFilter]; + + [ConfigurationProperty("name", IsRequired = true, IsKey = true)] + public string Name + { + get + { + return (string)this[s_propName]; + } + set + { + this[s_propName] = value; + } + } + + [ConfigurationProperty("traceOutputOptions", DefaultValue = (TraceOptions)TraceOptions.None)] + public TraceOptions TraceOutputOptions + { + get + { + return (TraceOptions)this[s_propOutputOpts]; + } + // This is useful when the OM becomes public. In the meantime, this can be utilized via reflection. + set + { + this[s_propOutputOpts] = value; + } + + } + + [ConfigurationProperty("type")] + public override string TypeName + { + get + { + return (string)this[_propListenerTypeName]; + } + set + { + this[_propListenerTypeName] = value; + } + } + + public override bool Equals(object compareTo) + { + if (Name.Equals("Default") && TypeName.Equals(typeof(DefaultTraceListener).FullName)) + { + // This is a workaround to treat all DefaultTraceListener named 'Default' the same. + // This is needed for the Config.Save to work properly as otherwise config base layers + // above us would run into duplicate 'Default' listener element and perceive it as + // error. + ListenerElement compareToElem = compareTo as ListenerElement; + return (compareToElem != null) && compareToElem.Name.Equals("Default") + && compareToElem.TypeName.Equals(typeof(DefaultTraceListener).FullName); + } + + return base.Equals(compareTo); + } + + public override int GetHashCode() => base.GetHashCode(); + + public TraceListener GetRuntimeObject() + { + if (_runtimeObject != null) + return (TraceListener)_runtimeObject; + + try + { + string className = TypeName; + if (string.IsNullOrEmpty(className)) + { + // Look it up in SharedListeners. + Debug.Assert(_allowReferences, "_allowReferences must be true if type name is null"); + + if (_attributes != null || ElementInformation.Properties[s_propFilter.Name].ValueOrigin == PropertyValueOrigin.SetHere || TraceOutputOptions != TraceOptions.None || !string.IsNullOrEmpty(InitData)) + { + throw new ConfigurationErrorsException(SR.Format(SR.Reference_listener_cant_have_properties, Name)); + } + + if (DiagnosticsConfiguration.SharedListeners == null) + { + throw new ConfigurationErrorsException(SR.Format(SR.Reference_to_nonexistent_listener, Name)); + } + + ListenerElement sharedListener = DiagnosticsConfiguration.SharedListeners[Name]; + if (sharedListener == null) + { + throw new ConfigurationErrorsException(SR.Format(SR.Reference_to_nonexistent_listener, Name)); + } + + _runtimeObject = sharedListener.GetRuntimeObject(); + return (TraceListener)_runtimeObject; + } + else + { + // Create a new one. + TraceListener newListener = (TraceListener)BaseGetRuntimeObject(); + s_initData.AddOrUpdate(newListener, InitData); + newListener.Name = Name; + TraceUtils.CopyStringDictionary(Attributes, newListener.Attributes); + newListener.TraceOutputOptions = TraceOutputOptions; + + if (Filter != null && !string.IsNullOrEmpty(Filter.TypeName)) + { + newListener.Filter = Filter.GetRuntimeObject(); + } + + _runtimeObject = newListener; + return newListener; + } + } + catch (ArgumentException e) + { + throw new ConfigurationErrorsException(SR.Format(SR.Could_not_create_listener, Name), e); + } + } + + // Our optional attributes implementation is little convoluted as there is + // no such first class mechanism from the config system. We basically cache + // any "unrecognized" attribute here and serialize it out later. + protected override bool OnDeserializeUnrecognizedAttribute(string name, string value) + { + Attributes.Add(name, value); + return true; + } + + // We need to serialize optional attributes here, a better place would have + // been inside SerializeElement but the base class implementation from + // ConfigurationElement doesn't take into account for derived class doing + // extended serialization, it basically writes out child element that + // forces the element closing syntax, so any attribute serialization needs + // to happen before normal element serialization from ConfigurationElement. + // This means we would write out custom attributes ahead of normal ones. + // The other alternative would be to re-implement the entire routine here + // which is an overkill and a maintenance issue. + protected override void PreSerialize(XmlWriter writer) + { + if (_attributes != null) + { + IDictionaryEnumerator e = (IDictionaryEnumerator)_attributes.GetEnumerator(); + while (e.MoveNext()) + { + string xmlValue = (string)e.Value; + string xmlName = (string)e.Key; + + if ((xmlValue != null) && (writer != null)) + { + writer.WriteAttributeString(xmlName, xmlValue); + } + } + } + } + + // Account for optional attributes from custom listeners. + protected internal override bool SerializeElement(XmlWriter writer, bool serializeCollectionKey) + { + bool DataToWrite = base.SerializeElement(writer, serializeCollectionKey); + DataToWrite = DataToWrite || ((_attributes != null) && (_attributes.Count > 0)); + return DataToWrite; + } + + protected internal override void Unmerge(ConfigurationElement sourceElement, + ConfigurationElement parentElement, + ConfigurationSaveMode saveMode) + { + base.Unmerge(sourceElement, parentElement, saveMode); + + // Unmerge the optional attributes cache as well + ListenerElement le = sourceElement as ListenerElement; + if ((le != null) && (le._attributes != null)) + { + _attributes = le._attributes; + } + } + + internal void ResetProperties() + { + // Blow away any UnrecognizedAttributes that we have deserialized earlier. + if (_attributes != null) + { + _attributes.Clear(); + _properties.Clear(); + _properties.Add(_propListenerTypeName); + _properties.Add(s_propFilter); + _properties.Add(s_propName); + _properties.Add(s_propOutputOpts); + } + } + + internal TraceListener RefreshRuntimeObject(TraceListener listener) + { + _runtimeObject = null; + try + { + string className = TypeName; + if (string.IsNullOrEmpty(className)) + { + // Look it up in SharedListeners and ask the sharedListener to refresh. + Debug.Assert(_allowReferences, "_allowReferences must be true if type name is null"); + + if (_attributes != null || ElementInformation.Properties[s_propFilter.Name].ValueOrigin == PropertyValueOrigin.SetHere || TraceOutputOptions != TraceOptions.None || !string.IsNullOrEmpty(InitData)) + { + throw new ConfigurationErrorsException(SR.Format(SR.Reference_listener_cant_have_properties, Name)); + } + + if (DiagnosticsConfiguration.SharedListeners == null) + { + throw new ConfigurationErrorsException(SR.Format(SR.Reference_to_nonexistent_listener, Name)); + } + + ListenerElement sharedListener = DiagnosticsConfiguration.SharedListeners[Name]; + if (sharedListener == null) + { + throw new ConfigurationErrorsException(SR.Format(SR.Reference_to_nonexistent_listener, Name)); + } + + _runtimeObject = sharedListener.RefreshRuntimeObject(listener); + return (TraceListener)_runtimeObject; + } + else + { + // We're the element with the type and initializeData info. First see if those two are the same as they were. + // If not, create a whole new object, otherwise, just update the other properties. + if (Type.GetType(className) != listener.GetType() || InitDataChanged(listener)) + { + // Type or initdata changed. + return GetRuntimeObject(); + } + else + { + TraceUtils.CopyStringDictionary(Attributes, listener.Attributes); + listener.TraceOutputOptions = TraceOutputOptions; + + if (listener.Filter != null) + { + if (ElementInformation.Properties[s_propFilter.Name].ValueOrigin == PropertyValueOrigin.SetHere || + ElementInformation.Properties[s_propFilter.Name].ValueOrigin == PropertyValueOrigin.Inherited) + { + listener.Filter = Filter.RefreshRuntimeObject(listener.Filter); + } + else + { + listener.Filter = null; + } + } + + _runtimeObject = listener; + return listener; + } + } + } + catch (ArgumentException e) + { + throw new ConfigurationErrorsException(SR.Format(SR.Could_not_create_listener, Name), e); + } + } + + private bool InitDataChanged(TraceListener listener) => !s_initData.TryGetValue(listener, out string previousInitData) + || InitData != previousInitData; + } +} diff --git a/src/libraries/System.Configuration.ConfigurationManager/src/System/Diagnostics/SourceElementsCollection.cs b/src/libraries/System.Configuration.ConfigurationManager/src/System/Diagnostics/SourceElementsCollection.cs new file mode 100644 index 00000000000000..b4d0434445f9ab --- /dev/null +++ b/src/libraries/System.Configuration.ConfigurationManager/src/System/Diagnostics/SourceElementsCollection.cs @@ -0,0 +1,151 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. + +using System.Configuration; +using System.Collections; +using System.Collections.Specialized; +using System.Xml; + +namespace System.Diagnostics +{ + [ConfigurationCollection(typeof(SourceElement), + AddItemName = "source", + CollectionType = ConfigurationElementCollectionType.BasicMap)] + internal sealed class SourceElementsCollection : ConfigurationElementCollection + { + public new SourceElement this[string name] => (SourceElement)BaseGet(name); + + protected override string ElementName => "source"; + + public override ConfigurationElementCollectionType CollectionType => ConfigurationElementCollectionType.BasicMap; + + protected override ConfigurationElement CreateNewElement() + { + SourceElement se = new SourceElement(); + se.Listeners.InitializeDefaultInternal(); + return se; + } + + protected override object GetElementKey(ConfigurationElement element) => ((SourceElement)element).Name; + } + + + internal sealed class SourceElement : ConfigurationElement + { + private static readonly ConfigurationPropertyCollection _properties = new(); + private static readonly ConfigurationProperty _propName = new("name", typeof(string), "", ConfigurationPropertyOptions.IsRequired); + private static readonly ConfigurationProperty _propSwitchName = new("switchName", typeof(string), null, ConfigurationPropertyOptions.None); + private static readonly ConfigurationProperty _propSwitchValue = new("switchValue", typeof(string), null, ConfigurationPropertyOptions.None); + private static readonly ConfigurationProperty _propSwitchType = new("switchType", typeof(string), null, ConfigurationPropertyOptions.None); + private static readonly ConfigurationProperty _propListeners = new("listeners", typeof(ListenerElementsCollection), new ListenerElementsCollection(), ConfigurationPropertyOptions.None); + + private StringDictionary _attributes; + + static SourceElement() + { + _properties.Add(_propName); + _properties.Add(_propSwitchName); + _properties.Add(_propSwitchValue); + _properties.Add(_propSwitchType); + _properties.Add(_propListeners); + } + + public StringDictionary Attributes => _attributes ??= new StringDictionary(); + + [ConfigurationProperty("listeners")] + public ListenerElementsCollection Listeners => (ListenerElementsCollection)this[_propListeners]; + + [ConfigurationProperty("name", IsRequired = true, DefaultValue = "")] + public string Name => (string)this[_propName]; + + protected internal override ConfigurationPropertyCollection Properties => _properties; + + [ConfigurationProperty("switchName")] + public string SwitchName => (string)this[_propSwitchName]; + + [ConfigurationProperty("switchValue")] + public string SwitchValue => (string)this[_propSwitchValue]; + + [ConfigurationProperty("switchType")] + public string SwitchType => (string)this[_propSwitchType]; + + protected internal override void DeserializeElement(XmlReader reader, bool serializeCollectionKey) + { + base.DeserializeElement(reader, serializeCollectionKey); + + if (!string.IsNullOrEmpty(SwitchName) && !string.IsNullOrEmpty(SwitchValue)) + throw new ConfigurationErrorsException(SR.Format(SR.Only_specify_one, Name)); + } + + // Our optional attributes implementation is little convoluted as there is + // no such first class mechanism from the config system. We basically cache + // any "unrecognized" attribute here and serialize it out later. + protected override bool OnDeserializeUnrecognizedAttribute(string name, string value) + { + Attributes.Add(name, value); + return true; + } + + // We need to serialize optional attributes here, a better place would have + // been inside SerializeElement but the base class implementation from + // ConfigurationElement doesn't take into account for derived class doing + // extended serialization, it basically writes out child element that + // forces the element closing syntax, so any attribute serialization needs + // to happen before normal element serialization from ConfigurationElement. + // This means we would write out custom attributes ahead of normal ones. + // The other alternative would be to re-implement the entire routine here + // which is an overkill and a maintenance issue. + protected override void PreSerialize(XmlWriter writer) + { + if (_attributes != null) + { + IDictionaryEnumerator e = (IDictionaryEnumerator)_attributes.GetEnumerator(); + while (e.MoveNext()) + { + string xmlValue = (string)e.Value; + string xmlName = (string)e.Key; + + if ((xmlValue != null) && (writer != null)) + { + writer.WriteAttributeString(xmlName, xmlValue); + } + } + } + } + + // Account for optional attributes from custom listeners. + protected internal override bool SerializeElement(XmlWriter writer, bool serializeCollectionKey) + { + bool DataToWrite = base.SerializeElement(writer, serializeCollectionKey); + DataToWrite = DataToWrite || ((_attributes != null) && (_attributes.Count > 0)); + return DataToWrite; + } + + protected internal override void Unmerge(ConfigurationElement sourceElement, + ConfigurationElement parentElement, + ConfigurationSaveMode saveMode) + { + base.Unmerge(sourceElement, parentElement, saveMode); + + // Unmerge the optional attributes cache as well + SourceElement le = sourceElement as SourceElement; + if ((le != null) && (le._attributes != null)) + this._attributes = le._attributes; + } + + internal void ResetProperties() + { + // Blow away any UnrecognizedAttributes that we have deserialized earlier. + if (_attributes != null) + { + _attributes.Clear(); + _properties.Clear(); + _properties.Add(_propName); + _properties.Add(_propSwitchName); + _properties.Add(_propSwitchValue); + _properties.Add(_propSwitchType); + _properties.Add(_propListeners); + } + } + } +} diff --git a/src/libraries/System.Configuration.ConfigurationManager/src/System/Diagnostics/SwitchElementsCollection.cs b/src/libraries/System.Configuration.ConfigurationManager/src/System/Diagnostics/SwitchElementsCollection.cs new file mode 100644 index 00000000000000..7cd92443d111cb --- /dev/null +++ b/src/libraries/System.Configuration.ConfigurationManager/src/System/Diagnostics/SwitchElementsCollection.cs @@ -0,0 +1,112 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. + +using System.Configuration; +using System.Collections; +using System.Collections.Specialized; +using System.Xml; + +namespace System.Diagnostics +{ + [ConfigurationCollection(typeof(SwitchElement))] + internal sealed class SwitchElementsCollection : ConfigurationElementCollection + { + public new SwitchElement this[string name] => (SwitchElement)BaseGet(name); + public override ConfigurationElementCollectionType CollectionType => ConfigurationElementCollectionType.AddRemoveClearMap; + protected override ConfigurationElement CreateNewElement() => new SwitchElement(); + protected override object GetElementKey(ConfigurationElement element) => ((SwitchElement)element).Name; + } + + internal sealed class SwitchElement : ConfigurationElement + { + private static readonly ConfigurationPropertyCollection _properties = new ConfigurationPropertyCollection(); + private static readonly ConfigurationProperty _propName = new("name", typeof(string), "", ConfigurationPropertyOptions.IsRequired | ConfigurationPropertyOptions.IsKey); + private static readonly ConfigurationProperty _propValue = new("value", typeof(string), null, ConfigurationPropertyOptions.IsRequired); + + private StringDictionary _attributes; + + static SwitchElement() + { + _properties.Add(_propName); + _properties.Add(_propValue); + } + + public StringDictionary Attributes => _attributes ??= new StringDictionary(); + + [ConfigurationProperty("name", DefaultValue = "", IsRequired = true, IsKey = true)] + public string Name => (string)this[_propName]; + + protected internal override ConfigurationPropertyCollection Properties => _properties; + + [ConfigurationProperty("value", IsRequired = true)] + public string Value => (string)this[_propValue]; + + // Our optional attributes implementation is little convoluted as there is + // no such first class mechanism from the config system. We basically cache + // any "unrecognized" attribute here and serialize it out later. + protected override bool OnDeserializeUnrecognizedAttribute(string name, string value) + { + Attributes.Add(name, value); + return true; + } + + // We need to serialize optional attributes here, a better place would have + // been inside SerializeElement but the base class implementation from + // ConfigurationElement doesn't take into account for derived class doing + // extended serialization, it basically writes out child element that + // forces the element closing syntax, so any attribute serialization needs + // to happen before normal element serialization from ConfigurationElement. + // This means we would write out custom attributes ahead of normal ones. + // The other alternative would be to re-implement the entire routine here + // which is an overkill and a maintenance issue. + protected override void PreSerialize(XmlWriter writer) + { + if (_attributes != null) + { + IDictionaryEnumerator e = (IDictionaryEnumerator)_attributes.GetEnumerator(); + while (e.MoveNext()) + { + string xmlValue = (string)e.Value; + string xmlName = (string)e.Key; + + if ((xmlValue != null) && (writer != null)) + { + writer.WriteAttributeString(xmlName, xmlValue); + } + } + } + } + + // Account for optional attributes from custom listeners. + protected internal override bool SerializeElement(XmlWriter writer, bool serializeCollectionKey) + { + bool DataToWrite = base.SerializeElement(writer, serializeCollectionKey); + DataToWrite = DataToWrite || ((_attributes != null) && (_attributes.Count > 0)); + return DataToWrite; + } + + protected internal override void Unmerge(ConfigurationElement sourceElement, + ConfigurationElement parentElement, + ConfigurationSaveMode saveMode) + { + base.Unmerge(sourceElement, parentElement, saveMode); + + // Unmerge the optional attributes cache as well + SwitchElement le = sourceElement as SwitchElement; + if ((le != null) && (le._attributes != null)) + this._attributes = le._attributes; + } + + internal void ResetProperties() + { + // Blow away any UnrecognizedAttributes that we have deserialized earlier. + if (_attributes != null) + { + _attributes.Clear(); + _properties.Clear(); + _properties.Add(_propName); + _properties.Add(_propValue); + } + } + } +} diff --git a/src/libraries/System.Configuration.ConfigurationManager/src/System/Diagnostics/SystemDiagnosticsSection.cs b/src/libraries/System.Configuration.ConfigurationManager/src/System/Diagnostics/SystemDiagnosticsSection.cs new file mode 100644 index 00000000000000..e4b5af069fe35b --- /dev/null +++ b/src/libraries/System.Configuration.ConfigurationManager/src/System/Diagnostics/SystemDiagnosticsSection.cs @@ -0,0 +1,43 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. + +using System.Configuration; + +namespace System.Diagnostics +{ + internal sealed class SystemDiagnosticsSection : ConfigurationSection + { + private static readonly ConfigurationPropertyCollection s_properties = new(); + private static readonly ConfigurationProperty s_propSources = new("sources", typeof(SourceElementsCollection), new SourceElementsCollection(), ConfigurationPropertyOptions.None); + private static readonly ConfigurationProperty s_propSharedListeners = new("sharedListeners", typeof(SharedListenerElementsCollection), new SharedListenerElementsCollection(), ConfigurationPropertyOptions.None); + private static readonly ConfigurationProperty s_propSwitches = new("switches", typeof(SwitchElementsCollection), new SwitchElementsCollection(), ConfigurationPropertyOptions.None); + private static readonly ConfigurationProperty s_propTrace = new("trace", typeof(TraceSection), new TraceSection(), ConfigurationPropertyOptions.None); + + static SystemDiagnosticsSection() + { + s_properties.Add(s_propSources); + s_properties.Add(s_propSharedListeners); + s_properties.Add(s_propSwitches); + s_properties.Add(s_propTrace); + } + + protected internal override ConfigurationPropertyCollection Properties => s_properties; + + [ConfigurationProperty("sources")] + public SourceElementsCollection Sources => (SourceElementsCollection)base[s_propSources]; + + [ConfigurationProperty("sharedListeners")] + public ListenerElementsCollection SharedListeners => (ListenerElementsCollection)base[s_propSharedListeners]; + + [ConfigurationProperty("switches")] + public SwitchElementsCollection Switches => (SwitchElementsCollection)base[s_propSwitches]; + + [ConfigurationProperty("trace")] + public TraceSection Trace => (TraceSection)base[s_propTrace]; + + protected internal override void InitializeDefault() + { + Trace.Listeners?.InitializeDefaultInternal(); + } + } +} diff --git a/src/libraries/System.Configuration.ConfigurationManager/src/System/Diagnostics/TraceConfiguration.cs b/src/libraries/System.Configuration.ConfigurationManager/src/System/Diagnostics/TraceConfiguration.cs new file mode 100644 index 00000000000000..d02b5a006b3da4 --- /dev/null +++ b/src/libraries/System.Configuration.ConfigurationManager/src/System/Diagnostics/TraceConfiguration.cs @@ -0,0 +1,200 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. + +namespace System.Diagnostics +{ + public static class TraceConfiguration + { + private static volatile bool s_registered; + + /// + /// Register the configuration system to apply settings from configuration files + /// to and related classes. + /// + public static void Register() + { + if (!s_registered) + { + // Registering callbacks more than once is fine, but avoid the overhead common cases without taking a lock. + Trace.Refreshing += RefreshingConfiguration; + Switch.Initializing += InitializingSwitch; + TraceSource.Initializing += InitializingTraceSource; + + ConfigureTraceSettings(); + + s_registered = true; + } + } + + private static void RefreshingConfiguration(object sender, EventArgs e) => DiagnosticsConfiguration.Refresh(); + + private static void InitializingTraceSource(object sender, InitializingTraceSourceEventArgs e) + { + TraceSource traceSource = e.TraceSource; + + // Ported from https://referencesource.microsoft.com/#System/compmod/system/diagnostics/TraceSource.cs,176 + SourceElementsCollection sources = DiagnosticsConfiguration.Sources; + + if (sources != null) + { + SourceElement sourceElement = sources[traceSource.Name]; + if (sourceElement != null) + { + e.WasInitialized = true; + + // First check if the type changed. + if (HasSourceSwitchTypeChanged()) + { + if (!string.IsNullOrEmpty(sourceElement.SwitchName)) + { + CreateSwitch(sourceElement.SwitchType, sourceElement.SwitchName); + } + else + { + CreateSwitch(sourceElement.SwitchType, traceSource.Name); + + if (!string.IsNullOrEmpty(sourceElement.SwitchValue)) + { + traceSource.Switch.Level = (SourceLevels)Enum.Parse(typeof(SourceLevels), sourceElement.SwitchValue); + } + } + } + else if (!string.IsNullOrEmpty(sourceElement.SwitchName)) + { + // Create a new switch if the name changed, otherwise just refresh. + if (sourceElement.SwitchName != traceSource.Switch.DisplayName) + CreateSwitch(sourceElement.SwitchType, sourceElement.SwitchName); + else + { + traceSource.Switch.Refresh(); + } + } + else + { + // The SwitchValue changed; just update our internalSwitch. + if (!string.IsNullOrEmpty(sourceElement.SwitchValue)) + { + traceSource.Switch.Level = (SourceLevels)Enum.Parse(typeof(SourceLevels), sourceElement.SwitchValue); + } + else + { + traceSource.Switch.Level = SourceLevels.Off; + } + } + + TraceListener[] newListenerCollection = new TraceListener[sourceElement.Listeners.Count]; + int listnerOffset = 0; + foreach (ListenerElement listenerElement in sourceElement.Listeners) + { + TraceListener listener = traceSource.Listeners[listenerElement.Name]; + if (listener != null) + { + newListenerCollection[listnerOffset++] = listenerElement.RefreshRuntimeObject(listener); + } + else + { + newListenerCollection[listnerOffset++] = listenerElement.GetRuntimeObject(); + } + } + + TraceUtils.CopyStringDictionary(sourceElement.Attributes, traceSource.Attributes); + + traceSource.Listeners.Clear(); + traceSource.Listeners.AddRange(newListenerCollection); + } + else + { + // There was no config, so clear whatever we have. + traceSource.Switch.Level = traceSource.DefaultLevel; + traceSource.Listeners.Clear(); + traceSource.Attributes.Clear(); + } + + bool HasSourceSwitchTypeChanged() + { + string sourceTypeName = sourceElement.SwitchType; + Type currentType = traceSource.Switch.GetType(); + + if (string.IsNullOrEmpty(sourceTypeName)) + { + // SourceSwitch is the default switch type. + return currentType != typeof(SourceSwitch); + } + + if (sourceTypeName == currentType.FullName) + { + return false; + } + + // Since there can be more than one valid AssemblyQualifiedName for a given Type this + // check can return true for some cases which can cause a minor side effect of a new + // Switch being created instead of just being refreshed. + return sourceElement.SwitchType != currentType.AssemblyQualifiedName; + } + } + + void CreateSwitch(string typeName, string name) + { + if (!string.IsNullOrEmpty(typeName)) + { + traceSource.Switch = (SourceSwitch)TraceUtils.GetRuntimeObject(typeName, typeof(SourceSwitch), name); + } + else + { + traceSource.Switch = new SourceSwitch(name, traceSource.DefaultLevel.ToString()); + } + } + } + + private static void ConfigureTraceSettings() + { + // Ported from https://referencesource.microsoft.com/#System/compmod/system/diagnostics/TraceInternal.cs,06360b4de5e221c2, https://referencesource.microsoft.com/#System/compmod/system/diagnostics/TraceInternal.cs,37 + + TraceSection traceSection = DiagnosticsConfiguration.SystemDiagnosticsSection?.Trace; + + if (traceSection != null) + { + Trace.UseGlobalLock = traceSection.UseGlobalLock; + Trace.AutoFlush = traceSection.AutoFlush; + Trace.IndentSize = traceSection.IndentSize; + + ListenerElementsCollection listeners = DiagnosticsConfiguration.SystemDiagnosticsSection?.Trace.Listeners; + if (listeners != null) + { + // If listeners were configured, replace the defaults with these. + Trace.Listeners.Clear(); + foreach (var listener in listeners.GetRuntimeObject()) + { + Trace.Listeners.Add(listener); + } + } + } + } + + private static void InitializingSwitch(object sender, InitializingSwitchEventArgs e) + { + Switch sw = e.Switch; + + // Ported from https://referencesource.microsoft.com/#System/compmod/system/diagnostics/Switch.cs,173 + SwitchElementsCollection switchSettings = DiagnosticsConfiguration.SwitchSettings; + if (switchSettings != null) + { + SwitchElement mySettings = switchSettings[sw.DisplayName]; + + if (mySettings != null) + { + if (mySettings.Value != null) + { + sw.Value = mySettings.Value; + } + else + { + sw.Value = sw.DefaultValue; + } + + TraceUtils.CopyStringDictionary(sw.Attributes, mySettings.Attributes); + } + } + } + } +} diff --git a/src/libraries/System.Configuration.ConfigurationManager/src/System/Diagnostics/TraceSection.cs b/src/libraries/System.Configuration.ConfigurationManager/src/System/Diagnostics/TraceSection.cs new file mode 100644 index 00000000000000..e5795150549d94 --- /dev/null +++ b/src/libraries/System.Configuration.ConfigurationManager/src/System/Diagnostics/TraceSection.cs @@ -0,0 +1,38 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. + +using System.Configuration; + +namespace System.Diagnostics +{ + internal sealed class TraceSection : ConfigurationElement + { + private static readonly ConfigurationPropertyCollection s_properties = new(); + private static readonly ConfigurationProperty s_propListeners = new("listeners", typeof(ListenerElementsCollection), null, ConfigurationPropertyOptions.None); + private static readonly ConfigurationProperty s_propAutoFlush = new("autoflush", typeof(bool), false, ConfigurationPropertyOptions.None); + private static readonly ConfigurationProperty s_propIndentSize = new("indentsize", typeof(int), 4, ConfigurationPropertyOptions.None); + private static readonly ConfigurationProperty s_propUseGlobalLock = new("useGlobalLock", typeof(bool), true, ConfigurationPropertyOptions.None); + + static TraceSection() + { + s_properties.Add(s_propListeners); + s_properties.Add(s_propAutoFlush); + s_properties.Add(s_propIndentSize); + s_properties.Add(s_propUseGlobalLock); + } + + [ConfigurationProperty("autoflush", DefaultValue = false)] + public bool AutoFlush => (bool)this[s_propAutoFlush]; + + [ConfigurationProperty("indentsize", DefaultValue = 4)] + public int IndentSize => (int)this[s_propIndentSize]; + + [ConfigurationProperty("listeners")] + public ListenerElementsCollection Listeners => (ListenerElementsCollection)this[s_propListeners]; + + [ConfigurationProperty("useGlobalLock", DefaultValue = true)] + public bool UseGlobalLock => (bool)this[s_propUseGlobalLock]; + + protected internal override ConfigurationPropertyCollection Properties => s_properties; + } +} diff --git a/src/libraries/System.Configuration.ConfigurationManager/src/System/Diagnostics/TraceUtils.cs b/src/libraries/System.Configuration.ConfigurationManager/src/System/Diagnostics/TraceUtils.cs new file mode 100644 index 00000000000000..99029ca290ef73 --- /dev/null +++ b/src/libraries/System.Configuration.ConfigurationManager/src/System/Diagnostics/TraceUtils.cs @@ -0,0 +1,214 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. + +using System.Configuration; +using System.IO; +using System.Reflection; +using System.Globalization; +using System.Collections; +using System.Runtime.Versioning; +using System.Collections.Specialized; + +namespace System.Diagnostics +{ + internal static class TraceUtils + { + private const string SystemDiagnostics = "System.Diagnostics."; + + internal static object GetRuntimeObject(string className, Type baseType, string initializeData) + { + object newObject = null; + Type objectType = null; + + if (className.Length == 0) + { + throw new ConfigurationErrorsException(SR.EmptyTypeName_NotAllowed); + } + + if (className.StartsWith(SystemDiagnostics)) + { + // Since the config file likely has just the FullName without the assembly name, + // map the FullName to the built in types. + objectType = MapToBuiltInTypes(className); + } + + if (objectType == null) + { + objectType = Type.GetType(className); + + if (objectType == null) + { + throw new ConfigurationErrorsException(SR.Format(SR.Could_not_find_type, className)); + } + } + + if (!baseType.IsAssignableFrom(objectType)) + throw new ConfigurationErrorsException(SR.Format(SR.Incorrect_base_type, className, baseType.FullName)); + + Exception innerException = null; + try + { + if (string.IsNullOrEmpty(initializeData)) + { + if (IsOwnedTL(objectType)) + throw new ConfigurationErrorsException(SR.TL_InitializeData_NotSpecified); + + // Create an object with parameterless constructor. + ConstructorInfo ctorInfo = objectType.GetConstructor(Array.Empty()); + if (ctorInfo == null) + throw new ConfigurationErrorsException(SR.Format(SR.Could_not_get_constructor, className)); + newObject = ctorInfo.Invoke(Array.Empty()); + } + else + { + // Create an object with a one-string constructor. + // First look for a string constructor. + ConstructorInfo ctorInfo = objectType.GetConstructor(new Type[] { typeof(string) }); + if (ctorInfo != null) + { + // Special case to enable specifying relative path to trace file from config for + // our own TextWriterTraceListener derivatives. We will prepend it with fullpath + // prefix from config file location. + if (IsOwnedTextWriterTL(objectType)) + { + if ((initializeData[0] != Path.DirectorySeparatorChar) && (initializeData[0] != Path.AltDirectorySeparatorChar) && !Path.IsPathRooted(initializeData)) + { + string filePath = DiagnosticsConfiguration.ConfigFilePath; + + if (!string.IsNullOrEmpty(filePath)) + { + string dirPath = Path.GetDirectoryName(filePath); + + if (dirPath != null) + initializeData = Path.Combine(dirPath, initializeData); + } + } + } + newObject = ctorInfo.Invoke(new object[] { initializeData }); + } + else + { + // Now look for another 1 param constructor. + ConstructorInfo[] ctorInfos = objectType.GetConstructors(); + if (ctorInfos == null) + { + throw new ConfigurationErrorsException(SR.Format(SR.Could_not_get_constructor, className)); + } + + for (int i = 0; i < ctorInfos.Length; i++) + { + ParameterInfo[] ctorparams = ctorInfos[i].GetParameters(); + if (ctorparams.Length == 1) + { + Type paramtype = ctorparams[0].ParameterType; + try + { + object convertedInitializeData = ConvertToBaseTypeOrEnum(initializeData, paramtype); + newObject = ctorInfos[i].Invoke(new object[] { convertedInitializeData }); + break; + } + catch (TargetInvocationException tiexc) + { + Debug.Assert(tiexc.InnerException != null, "ill-formed TargetInvocationException!"); + innerException = tiexc.InnerException; + } + catch (Exception e) + { + innerException = e; + // Ignore exceptions for now. If we don't have a newObject at the end, then we'll throw. + } + } + } + } + } + } + catch (TargetInvocationException tiexc) + { + Debug.Assert(tiexc.InnerException != null, "ill-formed TargetInvocationException!"); + innerException = tiexc.InnerException; + } + + if (newObject == null) + { + if (innerException != null) + { + throw new ConfigurationErrorsException(SR.Format(SR.Could_not_create_type_instance, className), innerException); + } + + throw new ConfigurationErrorsException(SR.Format(SR.Could_not_create_type_instance, className)); + } + + return newObject; + } + + private static Type MapToBuiltInTypes(string className) + { + string name = className.Substring(SystemDiagnostics.Length); + switch (name) + { + // Types in System.Diagnostics.TraceSource.dll: + case nameof(DefaultTraceListener): + return typeof(DefaultTraceListener); + case nameof(SourceFilter): + return typeof(SourceFilter); + case nameof(EventTypeFilter): + return typeof(EventTypeFilter); + case nameof(BooleanSwitch): + return typeof(BooleanSwitch); + case nameof(TraceSwitch): + return typeof(TraceSwitch); + case nameof(SourceSwitch): + return typeof(SourceSwitch); + + // Types in System.Diagnostics.TextWriterTraceListener: + case nameof(ConsoleTraceListener): + return typeof(ConsoleTraceListener); + case nameof(DelimitedListTraceListener): + return typeof(DelimitedListTraceListener); + case nameof(XmlWriterTraceListener): + return typeof(XmlWriterTraceListener); + case nameof(TextWriterTraceListener): + return typeof(TextWriterTraceListener); + + // Types in System.Diagnostics.EventLog.dll: + case nameof(EventLogTraceListener): + return typeof(EventLogTraceListener); + + default: + return null; + } + } + + // Our own tracelisteners that needs extra config validation. + internal static bool IsOwnedTL(Type type) + { + return typeof(EventLogTraceListener) == type + || IsOwnedTextWriterTL(type); + } + + internal static bool IsOwnedTextWriterTL(Type type) + { + return (typeof(XmlWriterTraceListener) == type) + || (typeof(DelimitedListTraceListener) == type) + || (typeof(TextWriterTraceListener) == type); + } + + private static object ConvertToBaseTypeOrEnum(string value, Type type) + { + return type.IsEnum ? + Enum.Parse(type, value, false) : + Convert.ChangeType(value, type, CultureInfo.InvariantCulture); + } + + // Copy the StringDictionary to another StringDictionary. + // This is not as efficient as directly setting the property, but it avoids having to expose a public setter on the property. + internal static void CopyStringDictionary(StringDictionary source, StringDictionary dest) + { + dest.Clear(); + foreach (string key in source) + { + dest[key] = source[key]; + } + } + } +} diff --git a/src/libraries/System.Configuration.ConfigurationManager/src/System/Diagnostics/TypedElement.cs b/src/libraries/System.Configuration.ConfigurationManager/src/System/Diagnostics/TypedElement.cs new file mode 100644 index 00000000000000..618911077816c2 --- /dev/null +++ b/src/libraries/System.Configuration.ConfigurationManager/src/System/Diagnostics/TypedElement.cs @@ -0,0 +1,62 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. +using System.Configuration; + +namespace System.Diagnostics +{ + internal class TypedElement : ConfigurationElement + { + protected static readonly ConfigurationProperty s_propTypeName = new("type", typeof(string), string.Empty, ConfigurationPropertyOptions.IsRequired | ConfigurationPropertyOptions.IsTypeStringTransformationRequired); + protected static readonly ConfigurationProperty s_propInitData = new("initializeData", typeof(string), string.Empty, ConfigurationPropertyOptions.None); + + protected ConfigurationPropertyCollection _properties; + protected object _runtimeObject; + private Type _baseType; + + public TypedElement(Type baseType) : base() + { + _properties = new ConfigurationPropertyCollection(); + _properties.Add(s_propTypeName); + _properties.Add(s_propInitData); + + _baseType = baseType; + } + + [ConfigurationProperty("initializeData", DefaultValue = "")] + public string InitData + { + get + { + return (string)this[s_propInitData]; + } + // This is useful when the OM becomes public. In the meantime, this can be utilized via reflection. + set + { + this[s_propInitData] = value; + } + } + + protected internal override ConfigurationPropertyCollection Properties => _properties; + + [ConfigurationProperty("type", IsRequired = true, DefaultValue = "")] + public virtual string TypeName + { + get + { + return (string)this[s_propTypeName]; + } + set + { + this[s_propTypeName] = value; + } + } + + protected object BaseGetRuntimeObject() + { + if (_runtimeObject == null) + _runtimeObject = TraceUtils.GetRuntimeObject(TypeName, _baseType, InitData); + + return _runtimeObject; + } + } +} diff --git a/src/libraries/System.Configuration.ConfigurationManager/tests/System.Configuration.ConfigurationManager.Tests.csproj b/src/libraries/System.Configuration.ConfigurationManager/tests/System.Configuration.ConfigurationManager.Tests.csproj index 733fcd5adf9813..bccb8f7e2fb189 100644 --- a/src/libraries/System.Configuration.ConfigurationManager/tests/System.Configuration.ConfigurationManager.Tests.csproj +++ b/src/libraries/System.Configuration.ConfigurationManager/tests/System.Configuration.ConfigurationManager.Tests.csproj @@ -5,22 +5,14 @@ true - - - - - - - - + + + + + + + + @@ -98,11 +90,16 @@ + + + + + diff --git a/src/libraries/System.Configuration.ConfigurationManager/tests/System/Diagnostics/DiagnosticsTestData.cs b/src/libraries/System.Configuration.ConfigurationManager/tests/System/Diagnostics/DiagnosticsTestData.cs new file mode 100644 index 00000000000000..05bbdbe991140f --- /dev/null +++ b/src/libraries/System.Configuration.ConfigurationManager/tests/System/Diagnostics/DiagnosticsTestData.cs @@ -0,0 +1,37 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. + +namespace System.DiagnosticsTests +{ + public static class DiagnosticsTestData + { + public static string Sample = +@" + + + + + + + + + + + + + + + + + + + + + +"; + } +} diff --git a/src/libraries/System.Configuration.ConfigurationManager/tests/System/Diagnostics/TraceSourceConfigurationTests.cs b/src/libraries/System.Configuration.ConfigurationManager/tests/System/Diagnostics/TraceSourceConfigurationTests.cs new file mode 100644 index 00000000000000..2ea13aeb31983e --- /dev/null +++ b/src/libraries/System.Configuration.ConfigurationManager/tests/System/Diagnostics/TraceSourceConfigurationTests.cs @@ -0,0 +1,78 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. + +using System.Configuration; +using System.Diagnostics; +using System.DiagnosticsTests; +using System.Reflection; +using Xunit; + +namespace System.Diagnostics.Tests +{ + public class DiagnosticConfigurationTests + { + [Fact] + public void ReadConfigSectionsFromFile() + { + using (var temp = new TempConfig(DiagnosticsTestData.Sample)) + { + var config = ConfigurationManager.OpenExeConfiguration(temp.ExePath); + + ConfigurationSection section = config.GetSection("system.diagnostics"); + Assert.NotNull(section); + Assert.Equal("SystemDiagnosticsSection", section.GetType().Name); + + ConfigurationElementCollection collection; + ConfigurationElement[] items; + + // Verify Switches + collection = (ConfigurationElementCollection)GetPropertyValue("Switches"); + Assert.Equal("SwitchElementsCollection", collection.GetType().Name); + Assert.Equal(1, collection.Count); + items = new ConfigurationElement[1]; + collection.CopyTo(items, 0); + Assert.Equal("sourceSwitch", items[0].ElementInformation.Properties["name"].Value.ToString()); + Assert.Equal("Error", items[0].ElementInformation.Properties["value"].Value.ToString()); + + // Verify SharedListeners + collection = (ConfigurationElementCollection)GetPropertyValue("SharedListeners"); + Assert.Equal("SharedListenerElementsCollection", collection.GetType().Name); + Assert.Equal(1, collection.Count); + items = new ConfigurationElement[1]; + collection.CopyTo(items, 0); + Assert.Equal("myListener", items[0].ElementInformation.Properties["name"].Value.ToString()); + Assert.Equal("System.Diagnostics.TextWriterTraceListener", items[0].ElementInformation.Properties["type"].Value.ToString()); + Assert.Equal("myListener.log", items[0].ElementInformation.Properties["initializeData"].Value.ToString()); + + // Verify Sources + collection = (ConfigurationElementCollection)GetPropertyValue("Sources"); + Assert.Equal("SourceElementsCollection", GetPropertyValue("Sources").GetType().Name); + Assert.Equal(1, collection.Count); + items = new ConfigurationElement[1]; + collection.CopyTo(items, 0); + Assert.Equal("TraceSourceApp", items[0].ElementInformation.Properties["name"].Value.ToString()); + Assert.Equal("sourceSwitch", items[0].ElementInformation.Properties["switchName"].Value.ToString()); + Assert.Equal("System.Diagnostics.SourceSwitch", items[0].ElementInformation.Properties["switchType"].Value); + + ConfigurationElementCollection listeners = (ConfigurationElementCollection)items[0].ElementInformation.Properties["listeners"].Value; + Assert.Equal("ListenerElementsCollection", listeners.GetType().Name); + Assert.Equal(2, listeners.Count); + ConfigurationElement[] listenerItems = new ConfigurationElement[2]; + listeners.CopyTo(listenerItems, 0); + Assert.Equal("console", listenerItems[0].ElementInformation.Properties["name"].Value.ToString()); + Assert.Equal("System.Diagnostics.ConsoleTraceListener", listenerItems[0].ElementInformation.Properties["type"].Value.ToString()); + Assert.Equal("myListener", listenerItems[1].ElementInformation.Properties["name"].Value.ToString()); + + ConfigurationElement filter = (ConfigurationElement)listenerItems[0].ElementInformation.Properties["filter"].Value; + Assert.Equal("FilterElement", filter.GetType().Name); + Assert.Equal("System.Diagnostics.EventTypeFilter", filter.ElementInformation.Properties["type"].Value.ToString()); + Assert.Equal("Error", filter.ElementInformation.Properties["initializeData"].Value.ToString()); + + object GetPropertyValue(string propertyName) => section.GetType(). + GetProperty(propertyName, BindingFlags.Public | BindingFlags.Instance). + GetValue(section); + } + } + } +} + diff --git a/src/libraries/System.Diagnostics.PerformanceCounter/src/System.Diagnostics.PerformanceCounter.csproj b/src/libraries/System.Diagnostics.PerformanceCounter/src/System.Diagnostics.PerformanceCounter.csproj index 8a800527bb10bb..a0dbb8e208bd40 100644 --- a/src/libraries/System.Diagnostics.PerformanceCounter/src/System.Diagnostics.PerformanceCounter.csproj +++ b/src/libraries/System.Diagnostics.PerformanceCounter/src/System.Diagnostics.PerformanceCounter.csproj @@ -29,7 +29,6 @@ System.Diagnostics.PerformanceCounter - Component @@ -41,7 +40,6 @@ System.Diagnostics.PerformanceCounter - diff --git a/src/libraries/System.Diagnostics.PerformanceCounter/src/System/Diagnostics/DiagnosticsConfiguration.cs b/src/libraries/System.Diagnostics.PerformanceCounter/src/System/Diagnostics/DiagnosticsConfiguration.cs index ad942e734183d1..8343a152a7cd1f 100644 --- a/src/libraries/System.Diagnostics.PerformanceCounter/src/System/Diagnostics/DiagnosticsConfiguration.cs +++ b/src/libraries/System.Diagnostics.PerformanceCounter/src/System/Diagnostics/DiagnosticsConfiguration.cs @@ -1,103 +1,22 @@ // Licensed to the .NET Foundation under one or more agreements. // The .NET Foundation licenses this file to you under the MIT license. -using System.Reflection; -using System.Configuration; - namespace System.Diagnostics { - internal enum InitState - { - NotInitialized, - Initializing, - Initialized - } - internal static class DiagnosticsConfiguration { - private static volatile SystemDiagnosticsSection s_configSection; - private static volatile InitState s_initState = InitState.NotInitialized; - internal static int PerformanceCountersFileMappingSize { get { - for (int retryCount = 0; !CanInitialize() && retryCount <= 5; ++retryCount) - { - if (retryCount == 5) - return SharedPerformanceCounter.DefaultCountersFileMappingSize; - - System.Threading.Thread.Sleep(200); - } - - Initialize(); - SystemDiagnosticsSection configSectionSav = s_configSection; - if (configSectionSav != null && configSectionSav.PerfCounters != null) - { - int size = configSectionSav.PerfCounters.FileMappingSize; - if (size < SharedPerformanceCounter.MinCountersFileMappingSize) - size = SharedPerformanceCounter.MinCountersFileMappingSize; - - if (size > SharedPerformanceCounter.MaxCountersFileMappingSize) - size = SharedPerformanceCounter.MaxCountersFileMappingSize; - - return size; - } - else - return SharedPerformanceCounter.DefaultCountersFileMappingSize; - } - } - - internal static string ConfigFilePath - { - get - { - Initialize(); - SystemDiagnosticsSection configSectionSav = s_configSection; - return configSectionSav?.ElementInformation?.Source ?? string.Empty; - } - } - - private static SystemDiagnosticsSection GetConfigSection() - { - SystemDiagnosticsSection configSection = (SystemDiagnosticsSection)ConfigurationManager.GetSection("system.diagnostics"); - return configSection; - } - - internal static bool CanInitialize() - { - bool setConfigurationSystemInProgress = (bool)(typeof(ConfigurationManager).GetProperty("SetConfigurationSystemInProgress", BindingFlags.NonPublic | BindingFlags.Static).GetValue(null)); - return (s_initState != InitState.Initializing) && !setConfigurationSystemInProgress; - } - - internal static void Initialize() - { - // Initialize() is also called by other components outside of Trace (such as PerformanceCounter) - // as a result using one lock for this critical section and another for Trace API critical sections - // (such as Trace.WriteLine) could potentially lead to deadlock between 2 threads that are - // executing these critical sections (and consequently obtaining the 2 locks) in the reverse order. - // Using the same lock for DiagnosticsConfiguration as well as TraceInternal avoids this issue. - // Sequential locks on TraceInternal.critSec by the same thread is a non issue for this critical section. - lock (TraceInternal.critSec) - { - // because some of the code used to load config also uses diagnostics - // we can't block them while we initialize from config. Therefore we just - // return immediately and they just use the default values. - bool setConfigurationSystemInProgress = (bool)(typeof(ConfigurationManager).GetProperty("SetConfigurationSystemInProgress", BindingFlags.NonPublic | BindingFlags.Static).GetValue(null)); - if (s_initState != InitState.NotInitialized || setConfigurationSystemInProgress) - { - return; - } - - s_initState = InitState.Initializing; // used for preventing recursion - try - { - s_configSection = GetConfigSection(); - } - finally - { - s_initState = InitState.Initialized; - } + // This is supposed to read the filemappingsize value from the System.Diagnostics section in the app config file, but it was + // discovered it was broken so the code was removed. + // Removing the code was necessary to support TraceSource-based config entries which also need to read the System.Diagnostics + // section. The code as also removed to support using performance counters in general (without even using the filemappingsize entry) + // since just the presence of a System.Diagnostics section itself caused the removed code to throw so many performance counter + // scenarios would throw when having any TraceSource-related entries in the System.Diagnostics section. + // See https://github.com/dotnet/runtime/issues/73706. + return SharedPerformanceCounter.DefaultCountersFileMappingSize; } } } diff --git a/src/libraries/System.Diagnostics.PerformanceCounter/src/System/Diagnostics/PerfCounterSection.cs b/src/libraries/System.Diagnostics.PerformanceCounter/src/System/Diagnostics/PerfCounterSection.cs deleted file mode 100644 index 7169e201f65e33..00000000000000 --- a/src/libraries/System.Diagnostics.PerformanceCounter/src/System/Diagnostics/PerfCounterSection.cs +++ /dev/null @@ -1,18 +0,0 @@ -// Licensed to the .NET Foundation under one or more agreements. -// The .NET Foundation licenses this file to you under the MIT license. - -using System.Configuration; - -namespace System.Diagnostics -{ - internal sealed class PerfCounterSection : ConfigurationElement - { - private static readonly ConfigurationProperty s_propFileMappingSize = new ConfigurationProperty("filemappingsize", typeof(int), 524288, ConfigurationPropertyOptions.None); - private static readonly ConfigurationPropertyCollection s_properties = new ConfigurationPropertyCollection { s_propFileMappingSize }; - - [ConfigurationProperty("filemappingsize", DefaultValue = 524288)] - public int FileMappingSize => (int)this[s_propFileMappingSize]; - - protected override ConfigurationPropertyCollection Properties => s_properties; - } -} diff --git a/src/libraries/System.Diagnostics.PerformanceCounter/src/System/Diagnostics/SystemDiagnosticsSection.cs b/src/libraries/System.Diagnostics.PerformanceCounter/src/System/Diagnostics/SystemDiagnosticsSection.cs deleted file mode 100644 index aa40d83aed03ae..00000000000000 --- a/src/libraries/System.Diagnostics.PerformanceCounter/src/System/Diagnostics/SystemDiagnosticsSection.cs +++ /dev/null @@ -1,18 +0,0 @@ -// Licensed to the .NET Foundation under one or more agreements. -// The .NET Foundation licenses this file to you under the MIT license. - -using System.Configuration; - -namespace System.Diagnostics -{ - internal sealed class SystemDiagnosticsSection : ConfigurationSection - { - private static readonly ConfigurationProperty s_propPerfCounters = new ConfigurationProperty("performanceCounters", typeof(PerfCounterSection), new PerfCounterSection(), ConfigurationPropertyOptions.None); - private static readonly ConfigurationPropertyCollection s_properties = new ConfigurationPropertyCollection { s_propPerfCounters }; - - [ConfigurationProperty("performanceCounters")] - public PerfCounterSection PerfCounters => (PerfCounterSection)base[s_propPerfCounters]; - - protected override ConfigurationPropertyCollection Properties => s_properties; - } -} diff --git a/src/libraries/System.Diagnostics.TraceSource/System.Diagnostics.TraceSource.sln b/src/libraries/System.Diagnostics.TraceSource/System.Diagnostics.TraceSource.sln index 897ad3f4f502c6..0de933741901b4 100644 --- a/src/libraries/System.Diagnostics.TraceSource/System.Diagnostics.TraceSource.sln +++ b/src/libraries/System.Diagnostics.TraceSource/System.Diagnostics.TraceSource.sln @@ -1,4 +1,8 @@ -Microsoft Visual Studio Solution File, Format Version 12.00 + +Microsoft Visual Studio Solution File, Format Version 12.00 +# Visual Studio Version 17 +VisualStudioVersion = 17.3.32714.290 +MinimumVisualStudioVersion = 10.0.40219.1 Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "System.Private.CoreLib", "..\..\coreclr\System.Private.CoreLib\System.Private.CoreLib.csproj", "{89B01AF7-F0CE-4168-8C4A-33FCDCF33B73}" EndProject Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "TestUtilities", "..\Common\tests\TestUtilities\TestUtilities.csproj", "{F6BCA6EF-777E-408B-B49B-B055B5A0BA19}" @@ -25,7 +29,7 @@ Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "System.Diagnostics.TraceSou EndProject Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "System.Diagnostics.TraceSource", "src\System.Diagnostics.TraceSource.csproj", "{48CC1460-B1E7-4DE9-A4E7-2206F7FD54CF}" EndProject -Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "System.Diagnostics.TraceSource.Tests", "tests\System.Diagnostics.TraceSource.Tests.csproj", "{0C126AE9-C858-4AC8-9DB1-B8E228BD2DB0}" +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "System.Diagnostics.TraceSource.Tests", "tests\System.Diagnostics.TraceSource.Tests\System.Diagnostics.TraceSource.Tests.csproj", "{0C126AE9-C858-4AC8-9DB1-B8E228BD2DB0}" EndProject Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "System.ObjectModel", "..\System.ObjectModel\ref\System.ObjectModel.csproj", "{535A9671-08A0-46DD-8191-DC9B995DF425}" EndProject @@ -53,19 +57,27 @@ Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "ref", "ref", "{1826CD8D-A5E EndProject Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "gen", "gen", "{BDABB39C-A9FF-4A9B-8BA2-EF873C5EEB16}" EndProject +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "System.Diagnostics.TraceSource.Config.Tests", "tests\System.Diagnostics.TraceSource.Config.Tests\System.Diagnostics.TraceSource.Config.Tests.csproj", "{422C9340-E720-4554-B6AC-560A19FE16B1}" +EndProject Global GlobalSection(SolutionConfigurationPlatforms) = preSolution + Checked|Any CPU = Checked|Any CPU + Checked|x64 = Checked|x64 + Checked|x86 = Checked|x86 Debug|Any CPU = Debug|Any CPU Debug|x64 = Debug|x64 Debug|x86 = Debug|x86 Release|Any CPU = Release|Any CPU Release|x64 = Release|x64 Release|x86 = Release|x86 - Checked|Any CPU = Checked|Any CPU - Checked|x64 = Checked|x64 - Checked|x86 = Checked|x86 EndGlobalSection GlobalSection(ProjectConfigurationPlatforms) = postSolution + {89B01AF7-F0CE-4168-8C4A-33FCDCF33B73}.Checked|Any CPU.ActiveCfg = Checked|x64 + {89B01AF7-F0CE-4168-8C4A-33FCDCF33B73}.Checked|Any CPU.Build.0 = Checked|x64 + {89B01AF7-F0CE-4168-8C4A-33FCDCF33B73}.Checked|x64.ActiveCfg = Checked|x64 + {89B01AF7-F0CE-4168-8C4A-33FCDCF33B73}.Checked|x64.Build.0 = Checked|x64 + {89B01AF7-F0CE-4168-8C4A-33FCDCF33B73}.Checked|x86.ActiveCfg = Checked|x86 + {89B01AF7-F0CE-4168-8C4A-33FCDCF33B73}.Checked|x86.Build.0 = Checked|x86 {89B01AF7-F0CE-4168-8C4A-33FCDCF33B73}.Debug|Any CPU.ActiveCfg = Debug|x64 {89B01AF7-F0CE-4168-8C4A-33FCDCF33B73}.Debug|Any CPU.Build.0 = Debug|x64 {89B01AF7-F0CE-4168-8C4A-33FCDCF33B73}.Debug|x64.ActiveCfg = Debug|x64 @@ -78,12 +90,12 @@ Global {89B01AF7-F0CE-4168-8C4A-33FCDCF33B73}.Release|x64.Build.0 = Release|x64 {89B01AF7-F0CE-4168-8C4A-33FCDCF33B73}.Release|x86.ActiveCfg = Release|x86 {89B01AF7-F0CE-4168-8C4A-33FCDCF33B73}.Release|x86.Build.0 = Release|x86 - {89B01AF7-F0CE-4168-8C4A-33FCDCF33B73}.Checked|Any CPU.ActiveCfg = Checked|x64 - {89B01AF7-F0CE-4168-8C4A-33FCDCF33B73}.Checked|Any CPU.Build.0 = Checked|x64 - {89B01AF7-F0CE-4168-8C4A-33FCDCF33B73}.Checked|x64.ActiveCfg = Checked|x64 - {89B01AF7-F0CE-4168-8C4A-33FCDCF33B73}.Checked|x64.Build.0 = Checked|x64 - {89B01AF7-F0CE-4168-8C4A-33FCDCF33B73}.Checked|x86.ActiveCfg = Checked|x86 - {89B01AF7-F0CE-4168-8C4A-33FCDCF33B73}.Checked|x86.Build.0 = Checked|x86 + {F6BCA6EF-777E-408B-B49B-B055B5A0BA19}.Checked|Any CPU.ActiveCfg = Debug|Any CPU + {F6BCA6EF-777E-408B-B49B-B055B5A0BA19}.Checked|Any CPU.Build.0 = Debug|Any CPU + {F6BCA6EF-777E-408B-B49B-B055B5A0BA19}.Checked|x64.ActiveCfg = Debug|Any CPU + {F6BCA6EF-777E-408B-B49B-B055B5A0BA19}.Checked|x64.Build.0 = Debug|Any CPU + {F6BCA6EF-777E-408B-B49B-B055B5A0BA19}.Checked|x86.ActiveCfg = Debug|Any CPU + {F6BCA6EF-777E-408B-B49B-B055B5A0BA19}.Checked|x86.Build.0 = Debug|Any CPU {F6BCA6EF-777E-408B-B49B-B055B5A0BA19}.Debug|Any CPU.ActiveCfg = Debug|Any CPU {F6BCA6EF-777E-408B-B49B-B055B5A0BA19}.Debug|Any CPU.Build.0 = Debug|Any CPU {F6BCA6EF-777E-408B-B49B-B055B5A0BA19}.Debug|x64.ActiveCfg = Debug|Any CPU @@ -96,12 +108,12 @@ Global {F6BCA6EF-777E-408B-B49B-B055B5A0BA19}.Release|x64.Build.0 = Release|Any CPU {F6BCA6EF-777E-408B-B49B-B055B5A0BA19}.Release|x86.ActiveCfg = Release|Any CPU {F6BCA6EF-777E-408B-B49B-B055B5A0BA19}.Release|x86.Build.0 = Release|Any CPU - {F6BCA6EF-777E-408B-B49B-B055B5A0BA19}.Checked|Any CPU.ActiveCfg = Debug|Any CPU - {F6BCA6EF-777E-408B-B49B-B055B5A0BA19}.Checked|Any CPU.Build.0 = Debug|Any CPU - {F6BCA6EF-777E-408B-B49B-B055B5A0BA19}.Checked|x64.ActiveCfg = Debug|Any CPU - {F6BCA6EF-777E-408B-B49B-B055B5A0BA19}.Checked|x64.Build.0 = Debug|Any CPU - {F6BCA6EF-777E-408B-B49B-B055B5A0BA19}.Checked|x86.ActiveCfg = Debug|Any CPU - {F6BCA6EF-777E-408B-B49B-B055B5A0BA19}.Checked|x86.Build.0 = Debug|Any CPU + {A26E9B9C-AFE7-4740-AC73-626D9823E515}.Checked|Any CPU.ActiveCfg = Debug|Any CPU + {A26E9B9C-AFE7-4740-AC73-626D9823E515}.Checked|Any CPU.Build.0 = Debug|Any CPU + {A26E9B9C-AFE7-4740-AC73-626D9823E515}.Checked|x64.ActiveCfg = Debug|Any CPU + {A26E9B9C-AFE7-4740-AC73-626D9823E515}.Checked|x64.Build.0 = Debug|Any CPU + {A26E9B9C-AFE7-4740-AC73-626D9823E515}.Checked|x86.ActiveCfg = Debug|Any CPU + {A26E9B9C-AFE7-4740-AC73-626D9823E515}.Checked|x86.Build.0 = Debug|Any CPU {A26E9B9C-AFE7-4740-AC73-626D9823E515}.Debug|Any CPU.ActiveCfg = Debug|Any CPU {A26E9B9C-AFE7-4740-AC73-626D9823E515}.Debug|Any CPU.Build.0 = Debug|Any CPU {A26E9B9C-AFE7-4740-AC73-626D9823E515}.Debug|x64.ActiveCfg = Debug|Any CPU @@ -114,12 +126,12 @@ Global {A26E9B9C-AFE7-4740-AC73-626D9823E515}.Release|x64.Build.0 = Release|Any CPU {A26E9B9C-AFE7-4740-AC73-626D9823E515}.Release|x86.ActiveCfg = Release|Any CPU {A26E9B9C-AFE7-4740-AC73-626D9823E515}.Release|x86.Build.0 = Release|Any CPU - {A26E9B9C-AFE7-4740-AC73-626D9823E515}.Checked|Any CPU.ActiveCfg = Debug|Any CPU - {A26E9B9C-AFE7-4740-AC73-626D9823E515}.Checked|Any CPU.Build.0 = Debug|Any CPU - {A26E9B9C-AFE7-4740-AC73-626D9823E515}.Checked|x64.ActiveCfg = Debug|Any CPU - {A26E9B9C-AFE7-4740-AC73-626D9823E515}.Checked|x64.Build.0 = Debug|Any CPU - {A26E9B9C-AFE7-4740-AC73-626D9823E515}.Checked|x86.ActiveCfg = Debug|Any CPU - {A26E9B9C-AFE7-4740-AC73-626D9823E515}.Checked|x86.Build.0 = Debug|Any CPU + {89C01491-2BE8-438C-8F1D-24DE9AFD7A86}.Checked|Any CPU.ActiveCfg = Debug|Any CPU + {89C01491-2BE8-438C-8F1D-24DE9AFD7A86}.Checked|Any CPU.Build.0 = Debug|Any CPU + {89C01491-2BE8-438C-8F1D-24DE9AFD7A86}.Checked|x64.ActiveCfg = Debug|Any CPU + {89C01491-2BE8-438C-8F1D-24DE9AFD7A86}.Checked|x64.Build.0 = Debug|Any CPU + {89C01491-2BE8-438C-8F1D-24DE9AFD7A86}.Checked|x86.ActiveCfg = Debug|Any CPU + {89C01491-2BE8-438C-8F1D-24DE9AFD7A86}.Checked|x86.Build.0 = Debug|Any CPU {89C01491-2BE8-438C-8F1D-24DE9AFD7A86}.Debug|Any CPU.ActiveCfg = Debug|Any CPU {89C01491-2BE8-438C-8F1D-24DE9AFD7A86}.Debug|Any CPU.Build.0 = Debug|Any CPU {89C01491-2BE8-438C-8F1D-24DE9AFD7A86}.Debug|x64.ActiveCfg = Debug|Any CPU @@ -132,12 +144,12 @@ Global {89C01491-2BE8-438C-8F1D-24DE9AFD7A86}.Release|x64.Build.0 = Release|Any CPU {89C01491-2BE8-438C-8F1D-24DE9AFD7A86}.Release|x86.ActiveCfg = Release|Any CPU {89C01491-2BE8-438C-8F1D-24DE9AFD7A86}.Release|x86.Build.0 = Release|Any CPU - {89C01491-2BE8-438C-8F1D-24DE9AFD7A86}.Checked|Any CPU.ActiveCfg = Debug|Any CPU - {89C01491-2BE8-438C-8F1D-24DE9AFD7A86}.Checked|Any CPU.Build.0 = Debug|Any CPU - {89C01491-2BE8-438C-8F1D-24DE9AFD7A86}.Checked|x64.ActiveCfg = Debug|Any CPU - {89C01491-2BE8-438C-8F1D-24DE9AFD7A86}.Checked|x64.Build.0 = Debug|Any CPU - {89C01491-2BE8-438C-8F1D-24DE9AFD7A86}.Checked|x86.ActiveCfg = Debug|Any CPU - {89C01491-2BE8-438C-8F1D-24DE9AFD7A86}.Checked|x86.Build.0 = Debug|Any CPU + {51AEBD0E-0A93-4532-A010-CAAF8E320D6C}.Checked|Any CPU.ActiveCfg = Debug|Any CPU + {51AEBD0E-0A93-4532-A010-CAAF8E320D6C}.Checked|Any CPU.Build.0 = Debug|Any CPU + {51AEBD0E-0A93-4532-A010-CAAF8E320D6C}.Checked|x64.ActiveCfg = Debug|Any CPU + {51AEBD0E-0A93-4532-A010-CAAF8E320D6C}.Checked|x64.Build.0 = Debug|Any CPU + {51AEBD0E-0A93-4532-A010-CAAF8E320D6C}.Checked|x86.ActiveCfg = Debug|Any CPU + {51AEBD0E-0A93-4532-A010-CAAF8E320D6C}.Checked|x86.Build.0 = Debug|Any CPU {51AEBD0E-0A93-4532-A010-CAAF8E320D6C}.Debug|Any CPU.ActiveCfg = Debug|Any CPU {51AEBD0E-0A93-4532-A010-CAAF8E320D6C}.Debug|Any CPU.Build.0 = Debug|Any CPU {51AEBD0E-0A93-4532-A010-CAAF8E320D6C}.Debug|x64.ActiveCfg = Debug|Any CPU @@ -150,12 +162,12 @@ Global {51AEBD0E-0A93-4532-A010-CAAF8E320D6C}.Release|x64.Build.0 = Release|Any CPU {51AEBD0E-0A93-4532-A010-CAAF8E320D6C}.Release|x86.ActiveCfg = Release|Any CPU {51AEBD0E-0A93-4532-A010-CAAF8E320D6C}.Release|x86.Build.0 = Release|Any CPU - {51AEBD0E-0A93-4532-A010-CAAF8E320D6C}.Checked|Any CPU.ActiveCfg = Debug|Any CPU - {51AEBD0E-0A93-4532-A010-CAAF8E320D6C}.Checked|Any CPU.Build.0 = Debug|Any CPU - {51AEBD0E-0A93-4532-A010-CAAF8E320D6C}.Checked|x64.ActiveCfg = Debug|Any CPU - {51AEBD0E-0A93-4532-A010-CAAF8E320D6C}.Checked|x64.Build.0 = Debug|Any CPU - {51AEBD0E-0A93-4532-A010-CAAF8E320D6C}.Checked|x86.ActiveCfg = Debug|Any CPU - {51AEBD0E-0A93-4532-A010-CAAF8E320D6C}.Checked|x86.Build.0 = Debug|Any CPU + {64F83961-AECA-4D5C-B467-A1A94AE6FFB4}.Checked|Any CPU.ActiveCfg = Debug|Any CPU + {64F83961-AECA-4D5C-B467-A1A94AE6FFB4}.Checked|Any CPU.Build.0 = Debug|Any CPU + {64F83961-AECA-4D5C-B467-A1A94AE6FFB4}.Checked|x64.ActiveCfg = Debug|Any CPU + {64F83961-AECA-4D5C-B467-A1A94AE6FFB4}.Checked|x64.Build.0 = Debug|Any CPU + {64F83961-AECA-4D5C-B467-A1A94AE6FFB4}.Checked|x86.ActiveCfg = Debug|Any CPU + {64F83961-AECA-4D5C-B467-A1A94AE6FFB4}.Checked|x86.Build.0 = Debug|Any CPU {64F83961-AECA-4D5C-B467-A1A94AE6FFB4}.Debug|Any CPU.ActiveCfg = Debug|Any CPU {64F83961-AECA-4D5C-B467-A1A94AE6FFB4}.Debug|Any CPU.Build.0 = Debug|Any CPU {64F83961-AECA-4D5C-B467-A1A94AE6FFB4}.Debug|x64.ActiveCfg = Debug|Any CPU @@ -168,12 +180,12 @@ Global {64F83961-AECA-4D5C-B467-A1A94AE6FFB4}.Release|x64.Build.0 = Release|Any CPU {64F83961-AECA-4D5C-B467-A1A94AE6FFB4}.Release|x86.ActiveCfg = Release|Any CPU {64F83961-AECA-4D5C-B467-A1A94AE6FFB4}.Release|x86.Build.0 = Release|Any CPU - {64F83961-AECA-4D5C-B467-A1A94AE6FFB4}.Checked|Any CPU.ActiveCfg = Debug|Any CPU - {64F83961-AECA-4D5C-B467-A1A94AE6FFB4}.Checked|Any CPU.Build.0 = Debug|Any CPU - {64F83961-AECA-4D5C-B467-A1A94AE6FFB4}.Checked|x64.ActiveCfg = Debug|Any CPU - {64F83961-AECA-4D5C-B467-A1A94AE6FFB4}.Checked|x64.Build.0 = Debug|Any CPU - {64F83961-AECA-4D5C-B467-A1A94AE6FFB4}.Checked|x86.ActiveCfg = Debug|Any CPU - {64F83961-AECA-4D5C-B467-A1A94AE6FFB4}.Checked|x86.Build.0 = Debug|Any CPU + {279066F9-4DB9-4897-8CE4-66BC31118323}.Checked|Any CPU.ActiveCfg = Debug|Any CPU + {279066F9-4DB9-4897-8CE4-66BC31118323}.Checked|Any CPU.Build.0 = Debug|Any CPU + {279066F9-4DB9-4897-8CE4-66BC31118323}.Checked|x64.ActiveCfg = Debug|Any CPU + {279066F9-4DB9-4897-8CE4-66BC31118323}.Checked|x64.Build.0 = Debug|Any CPU + {279066F9-4DB9-4897-8CE4-66BC31118323}.Checked|x86.ActiveCfg = Debug|Any CPU + {279066F9-4DB9-4897-8CE4-66BC31118323}.Checked|x86.Build.0 = Debug|Any CPU {279066F9-4DB9-4897-8CE4-66BC31118323}.Debug|Any CPU.ActiveCfg = Debug|Any CPU {279066F9-4DB9-4897-8CE4-66BC31118323}.Debug|Any CPU.Build.0 = Debug|Any CPU {279066F9-4DB9-4897-8CE4-66BC31118323}.Debug|x64.ActiveCfg = Debug|Any CPU @@ -186,12 +198,12 @@ Global {279066F9-4DB9-4897-8CE4-66BC31118323}.Release|x64.Build.0 = Release|Any CPU {279066F9-4DB9-4897-8CE4-66BC31118323}.Release|x86.ActiveCfg = Release|Any CPU {279066F9-4DB9-4897-8CE4-66BC31118323}.Release|x86.Build.0 = Release|Any CPU - {279066F9-4DB9-4897-8CE4-66BC31118323}.Checked|Any CPU.ActiveCfg = Debug|Any CPU - {279066F9-4DB9-4897-8CE4-66BC31118323}.Checked|Any CPU.Build.0 = Debug|Any CPU - {279066F9-4DB9-4897-8CE4-66BC31118323}.Checked|x64.ActiveCfg = Debug|Any CPU - {279066F9-4DB9-4897-8CE4-66BC31118323}.Checked|x64.Build.0 = Debug|Any CPU - {279066F9-4DB9-4897-8CE4-66BC31118323}.Checked|x86.ActiveCfg = Debug|Any CPU - {279066F9-4DB9-4897-8CE4-66BC31118323}.Checked|x86.Build.0 = Debug|Any CPU + {95F843FE-38B4-4ED5-81FF-605DE38155F6}.Checked|Any CPU.ActiveCfg = Debug|Any CPU + {95F843FE-38B4-4ED5-81FF-605DE38155F6}.Checked|Any CPU.Build.0 = Debug|Any CPU + {95F843FE-38B4-4ED5-81FF-605DE38155F6}.Checked|x64.ActiveCfg = Debug|Any CPU + {95F843FE-38B4-4ED5-81FF-605DE38155F6}.Checked|x64.Build.0 = Debug|Any CPU + {95F843FE-38B4-4ED5-81FF-605DE38155F6}.Checked|x86.ActiveCfg = Debug|Any CPU + {95F843FE-38B4-4ED5-81FF-605DE38155F6}.Checked|x86.Build.0 = Debug|Any CPU {95F843FE-38B4-4ED5-81FF-605DE38155F6}.Debug|Any CPU.ActiveCfg = Debug|Any CPU {95F843FE-38B4-4ED5-81FF-605DE38155F6}.Debug|Any CPU.Build.0 = Debug|Any CPU {95F843FE-38B4-4ED5-81FF-605DE38155F6}.Debug|x64.ActiveCfg = Debug|Any CPU @@ -204,12 +216,12 @@ Global {95F843FE-38B4-4ED5-81FF-605DE38155F6}.Release|x64.Build.0 = Release|Any CPU {95F843FE-38B4-4ED5-81FF-605DE38155F6}.Release|x86.ActiveCfg = Release|Any CPU {95F843FE-38B4-4ED5-81FF-605DE38155F6}.Release|x86.Build.0 = Release|Any CPU - {95F843FE-38B4-4ED5-81FF-605DE38155F6}.Checked|Any CPU.ActiveCfg = Debug|Any CPU - {95F843FE-38B4-4ED5-81FF-605DE38155F6}.Checked|Any CPU.Build.0 = Debug|Any CPU - {95F843FE-38B4-4ED5-81FF-605DE38155F6}.Checked|x64.ActiveCfg = Debug|Any CPU - {95F843FE-38B4-4ED5-81FF-605DE38155F6}.Checked|x64.Build.0 = Debug|Any CPU - {95F843FE-38B4-4ED5-81FF-605DE38155F6}.Checked|x86.ActiveCfg = Debug|Any CPU - {95F843FE-38B4-4ED5-81FF-605DE38155F6}.Checked|x86.Build.0 = Debug|Any CPU + {ED544AD5-41C5-4445-BC0F-EFA1553C881A}.Checked|Any CPU.ActiveCfg = Debug|Any CPU + {ED544AD5-41C5-4445-BC0F-EFA1553C881A}.Checked|Any CPU.Build.0 = Debug|Any CPU + {ED544AD5-41C5-4445-BC0F-EFA1553C881A}.Checked|x64.ActiveCfg = Debug|Any CPU + {ED544AD5-41C5-4445-BC0F-EFA1553C881A}.Checked|x64.Build.0 = Debug|Any CPU + {ED544AD5-41C5-4445-BC0F-EFA1553C881A}.Checked|x86.ActiveCfg = Debug|Any CPU + {ED544AD5-41C5-4445-BC0F-EFA1553C881A}.Checked|x86.Build.0 = Debug|Any CPU {ED544AD5-41C5-4445-BC0F-EFA1553C881A}.Debug|Any CPU.ActiveCfg = Debug|Any CPU {ED544AD5-41C5-4445-BC0F-EFA1553C881A}.Debug|Any CPU.Build.0 = Debug|Any CPU {ED544AD5-41C5-4445-BC0F-EFA1553C881A}.Debug|x64.ActiveCfg = Debug|Any CPU @@ -222,12 +234,12 @@ Global {ED544AD5-41C5-4445-BC0F-EFA1553C881A}.Release|x64.Build.0 = Release|Any CPU {ED544AD5-41C5-4445-BC0F-EFA1553C881A}.Release|x86.ActiveCfg = Release|Any CPU {ED544AD5-41C5-4445-BC0F-EFA1553C881A}.Release|x86.Build.0 = Release|Any CPU - {ED544AD5-41C5-4445-BC0F-EFA1553C881A}.Checked|Any CPU.ActiveCfg = Debug|Any CPU - {ED544AD5-41C5-4445-BC0F-EFA1553C881A}.Checked|Any CPU.Build.0 = Debug|Any CPU - {ED544AD5-41C5-4445-BC0F-EFA1553C881A}.Checked|x64.ActiveCfg = Debug|Any CPU - {ED544AD5-41C5-4445-BC0F-EFA1553C881A}.Checked|x64.Build.0 = Debug|Any CPU - {ED544AD5-41C5-4445-BC0F-EFA1553C881A}.Checked|x86.ActiveCfg = Debug|Any CPU - {ED544AD5-41C5-4445-BC0F-EFA1553C881A}.Checked|x86.Build.0 = Debug|Any CPU + {97D756D3-8ECA-45F5-A9F5-DBF659D87BC4}.Checked|Any CPU.ActiveCfg = Debug|Any CPU + {97D756D3-8ECA-45F5-A9F5-DBF659D87BC4}.Checked|Any CPU.Build.0 = Debug|Any CPU + {97D756D3-8ECA-45F5-A9F5-DBF659D87BC4}.Checked|x64.ActiveCfg = Debug|Any CPU + {97D756D3-8ECA-45F5-A9F5-DBF659D87BC4}.Checked|x64.Build.0 = Debug|Any CPU + {97D756D3-8ECA-45F5-A9F5-DBF659D87BC4}.Checked|x86.ActiveCfg = Debug|Any CPU + {97D756D3-8ECA-45F5-A9F5-DBF659D87BC4}.Checked|x86.Build.0 = Debug|Any CPU {97D756D3-8ECA-45F5-A9F5-DBF659D87BC4}.Debug|Any CPU.ActiveCfg = Debug|Any CPU {97D756D3-8ECA-45F5-A9F5-DBF659D87BC4}.Debug|Any CPU.Build.0 = Debug|Any CPU {97D756D3-8ECA-45F5-A9F5-DBF659D87BC4}.Debug|x64.ActiveCfg = Debug|Any CPU @@ -240,12 +252,12 @@ Global {97D756D3-8ECA-45F5-A9F5-DBF659D87BC4}.Release|x64.Build.0 = Release|Any CPU {97D756D3-8ECA-45F5-A9F5-DBF659D87BC4}.Release|x86.ActiveCfg = Release|Any CPU {97D756D3-8ECA-45F5-A9F5-DBF659D87BC4}.Release|x86.Build.0 = Release|Any CPU - {97D756D3-8ECA-45F5-A9F5-DBF659D87BC4}.Checked|Any CPU.ActiveCfg = Debug|Any CPU - {97D756D3-8ECA-45F5-A9F5-DBF659D87BC4}.Checked|Any CPU.Build.0 = Debug|Any CPU - {97D756D3-8ECA-45F5-A9F5-DBF659D87BC4}.Checked|x64.ActiveCfg = Debug|Any CPU - {97D756D3-8ECA-45F5-A9F5-DBF659D87BC4}.Checked|x64.Build.0 = Debug|Any CPU - {97D756D3-8ECA-45F5-A9F5-DBF659D87BC4}.Checked|x86.ActiveCfg = Debug|Any CPU - {97D756D3-8ECA-45F5-A9F5-DBF659D87BC4}.Checked|x86.Build.0 = Debug|Any CPU + {83696A63-CF89-4DE4-8F79-96F5B830A4B6}.Checked|Any CPU.ActiveCfg = Debug|Any CPU + {83696A63-CF89-4DE4-8F79-96F5B830A4B6}.Checked|Any CPU.Build.0 = Debug|Any CPU + {83696A63-CF89-4DE4-8F79-96F5B830A4B6}.Checked|x64.ActiveCfg = Debug|Any CPU + {83696A63-CF89-4DE4-8F79-96F5B830A4B6}.Checked|x64.Build.0 = Debug|Any CPU + {83696A63-CF89-4DE4-8F79-96F5B830A4B6}.Checked|x86.ActiveCfg = Debug|Any CPU + {83696A63-CF89-4DE4-8F79-96F5B830A4B6}.Checked|x86.Build.0 = Debug|Any CPU {83696A63-CF89-4DE4-8F79-96F5B830A4B6}.Debug|Any CPU.ActiveCfg = Debug|Any CPU {83696A63-CF89-4DE4-8F79-96F5B830A4B6}.Debug|Any CPU.Build.0 = Debug|Any CPU {83696A63-CF89-4DE4-8F79-96F5B830A4B6}.Debug|x64.ActiveCfg = Debug|Any CPU @@ -258,12 +270,12 @@ Global {83696A63-CF89-4DE4-8F79-96F5B830A4B6}.Release|x64.Build.0 = Release|Any CPU {83696A63-CF89-4DE4-8F79-96F5B830A4B6}.Release|x86.ActiveCfg = Release|Any CPU {83696A63-CF89-4DE4-8F79-96F5B830A4B6}.Release|x86.Build.0 = Release|Any CPU - {83696A63-CF89-4DE4-8F79-96F5B830A4B6}.Checked|Any CPU.ActiveCfg = Debug|Any CPU - {83696A63-CF89-4DE4-8F79-96F5B830A4B6}.Checked|Any CPU.Build.0 = Debug|Any CPU - {83696A63-CF89-4DE4-8F79-96F5B830A4B6}.Checked|x64.ActiveCfg = Debug|Any CPU - {83696A63-CF89-4DE4-8F79-96F5B830A4B6}.Checked|x64.Build.0 = Debug|Any CPU - {83696A63-CF89-4DE4-8F79-96F5B830A4B6}.Checked|x86.ActiveCfg = Debug|Any CPU - {83696A63-CF89-4DE4-8F79-96F5B830A4B6}.Checked|x86.Build.0 = Debug|Any CPU + {2F00396E-003A-4385-92DC-69FDBEF330D8}.Checked|Any CPU.ActiveCfg = Debug|Any CPU + {2F00396E-003A-4385-92DC-69FDBEF330D8}.Checked|Any CPU.Build.0 = Debug|Any CPU + {2F00396E-003A-4385-92DC-69FDBEF330D8}.Checked|x64.ActiveCfg = Debug|Any CPU + {2F00396E-003A-4385-92DC-69FDBEF330D8}.Checked|x64.Build.0 = Debug|Any CPU + {2F00396E-003A-4385-92DC-69FDBEF330D8}.Checked|x86.ActiveCfg = Debug|Any CPU + {2F00396E-003A-4385-92DC-69FDBEF330D8}.Checked|x86.Build.0 = Debug|Any CPU {2F00396E-003A-4385-92DC-69FDBEF330D8}.Debug|Any CPU.ActiveCfg = Debug|Any CPU {2F00396E-003A-4385-92DC-69FDBEF330D8}.Debug|Any CPU.Build.0 = Debug|Any CPU {2F00396E-003A-4385-92DC-69FDBEF330D8}.Debug|x64.ActiveCfg = Debug|Any CPU @@ -276,12 +288,12 @@ Global {2F00396E-003A-4385-92DC-69FDBEF330D8}.Release|x64.Build.0 = Release|Any CPU {2F00396E-003A-4385-92DC-69FDBEF330D8}.Release|x86.ActiveCfg = Release|Any CPU {2F00396E-003A-4385-92DC-69FDBEF330D8}.Release|x86.Build.0 = Release|Any CPU - {2F00396E-003A-4385-92DC-69FDBEF330D8}.Checked|Any CPU.ActiveCfg = Debug|Any CPU - {2F00396E-003A-4385-92DC-69FDBEF330D8}.Checked|Any CPU.Build.0 = Debug|Any CPU - {2F00396E-003A-4385-92DC-69FDBEF330D8}.Checked|x64.ActiveCfg = Debug|Any CPU - {2F00396E-003A-4385-92DC-69FDBEF330D8}.Checked|x64.Build.0 = Debug|Any CPU - {2F00396E-003A-4385-92DC-69FDBEF330D8}.Checked|x86.ActiveCfg = Debug|Any CPU - {2F00396E-003A-4385-92DC-69FDBEF330D8}.Checked|x86.Build.0 = Debug|Any CPU + {48CC1460-B1E7-4DE9-A4E7-2206F7FD54CF}.Checked|Any CPU.ActiveCfg = Debug|Any CPU + {48CC1460-B1E7-4DE9-A4E7-2206F7FD54CF}.Checked|Any CPU.Build.0 = Debug|Any CPU + {48CC1460-B1E7-4DE9-A4E7-2206F7FD54CF}.Checked|x64.ActiveCfg = Debug|Any CPU + {48CC1460-B1E7-4DE9-A4E7-2206F7FD54CF}.Checked|x64.Build.0 = Debug|Any CPU + {48CC1460-B1E7-4DE9-A4E7-2206F7FD54CF}.Checked|x86.ActiveCfg = Debug|Any CPU + {48CC1460-B1E7-4DE9-A4E7-2206F7FD54CF}.Checked|x86.Build.0 = Debug|Any CPU {48CC1460-B1E7-4DE9-A4E7-2206F7FD54CF}.Debug|Any CPU.ActiveCfg = Debug|Any CPU {48CC1460-B1E7-4DE9-A4E7-2206F7FD54CF}.Debug|Any CPU.Build.0 = Debug|Any CPU {48CC1460-B1E7-4DE9-A4E7-2206F7FD54CF}.Debug|x64.ActiveCfg = Debug|Any CPU @@ -294,12 +306,12 @@ Global {48CC1460-B1E7-4DE9-A4E7-2206F7FD54CF}.Release|x64.Build.0 = Release|Any CPU {48CC1460-B1E7-4DE9-A4E7-2206F7FD54CF}.Release|x86.ActiveCfg = Release|Any CPU {48CC1460-B1E7-4DE9-A4E7-2206F7FD54CF}.Release|x86.Build.0 = Release|Any CPU - {48CC1460-B1E7-4DE9-A4E7-2206F7FD54CF}.Checked|Any CPU.ActiveCfg = Debug|Any CPU - {48CC1460-B1E7-4DE9-A4E7-2206F7FD54CF}.Checked|Any CPU.Build.0 = Debug|Any CPU - {48CC1460-B1E7-4DE9-A4E7-2206F7FD54CF}.Checked|x64.ActiveCfg = Debug|Any CPU - {48CC1460-B1E7-4DE9-A4E7-2206F7FD54CF}.Checked|x64.Build.0 = Debug|Any CPU - {48CC1460-B1E7-4DE9-A4E7-2206F7FD54CF}.Checked|x86.ActiveCfg = Debug|Any CPU - {48CC1460-B1E7-4DE9-A4E7-2206F7FD54CF}.Checked|x86.Build.0 = Debug|Any CPU + {0C126AE9-C858-4AC8-9DB1-B8E228BD2DB0}.Checked|Any CPU.ActiveCfg = Debug|Any CPU + {0C126AE9-C858-4AC8-9DB1-B8E228BD2DB0}.Checked|Any CPU.Build.0 = Debug|Any CPU + {0C126AE9-C858-4AC8-9DB1-B8E228BD2DB0}.Checked|x64.ActiveCfg = Debug|Any CPU + {0C126AE9-C858-4AC8-9DB1-B8E228BD2DB0}.Checked|x64.Build.0 = Debug|Any CPU + {0C126AE9-C858-4AC8-9DB1-B8E228BD2DB0}.Checked|x86.ActiveCfg = Debug|Any CPU + {0C126AE9-C858-4AC8-9DB1-B8E228BD2DB0}.Checked|x86.Build.0 = Debug|Any CPU {0C126AE9-C858-4AC8-9DB1-B8E228BD2DB0}.Debug|Any CPU.ActiveCfg = Debug|Any CPU {0C126AE9-C858-4AC8-9DB1-B8E228BD2DB0}.Debug|Any CPU.Build.0 = Debug|Any CPU {0C126AE9-C858-4AC8-9DB1-B8E228BD2DB0}.Debug|x64.ActiveCfg = Debug|Any CPU @@ -312,12 +324,12 @@ Global {0C126AE9-C858-4AC8-9DB1-B8E228BD2DB0}.Release|x64.Build.0 = Release|Any CPU {0C126AE9-C858-4AC8-9DB1-B8E228BD2DB0}.Release|x86.ActiveCfg = Release|Any CPU {0C126AE9-C858-4AC8-9DB1-B8E228BD2DB0}.Release|x86.Build.0 = Release|Any CPU - {0C126AE9-C858-4AC8-9DB1-B8E228BD2DB0}.Checked|Any CPU.ActiveCfg = Debug|Any CPU - {0C126AE9-C858-4AC8-9DB1-B8E228BD2DB0}.Checked|Any CPU.Build.0 = Debug|Any CPU - {0C126AE9-C858-4AC8-9DB1-B8E228BD2DB0}.Checked|x64.ActiveCfg = Debug|Any CPU - {0C126AE9-C858-4AC8-9DB1-B8E228BD2DB0}.Checked|x64.Build.0 = Debug|Any CPU - {0C126AE9-C858-4AC8-9DB1-B8E228BD2DB0}.Checked|x86.ActiveCfg = Debug|Any CPU - {0C126AE9-C858-4AC8-9DB1-B8E228BD2DB0}.Checked|x86.Build.0 = Debug|Any CPU + {535A9671-08A0-46DD-8191-DC9B995DF425}.Checked|Any CPU.ActiveCfg = Debug|Any CPU + {535A9671-08A0-46DD-8191-DC9B995DF425}.Checked|Any CPU.Build.0 = Debug|Any CPU + {535A9671-08A0-46DD-8191-DC9B995DF425}.Checked|x64.ActiveCfg = Debug|Any CPU + {535A9671-08A0-46DD-8191-DC9B995DF425}.Checked|x64.Build.0 = Debug|Any CPU + {535A9671-08A0-46DD-8191-DC9B995DF425}.Checked|x86.ActiveCfg = Debug|Any CPU + {535A9671-08A0-46DD-8191-DC9B995DF425}.Checked|x86.Build.0 = Debug|Any CPU {535A9671-08A0-46DD-8191-DC9B995DF425}.Debug|Any CPU.ActiveCfg = Debug|Any CPU {535A9671-08A0-46DD-8191-DC9B995DF425}.Debug|Any CPU.Build.0 = Debug|Any CPU {535A9671-08A0-46DD-8191-DC9B995DF425}.Debug|x64.ActiveCfg = Debug|Any CPU @@ -330,12 +342,12 @@ Global {535A9671-08A0-46DD-8191-DC9B995DF425}.Release|x64.Build.0 = Release|Any CPU {535A9671-08A0-46DD-8191-DC9B995DF425}.Release|x86.ActiveCfg = Release|Any CPU {535A9671-08A0-46DD-8191-DC9B995DF425}.Release|x86.Build.0 = Release|Any CPU - {535A9671-08A0-46DD-8191-DC9B995DF425}.Checked|Any CPU.ActiveCfg = Debug|Any CPU - {535A9671-08A0-46DD-8191-DC9B995DF425}.Checked|Any CPU.Build.0 = Debug|Any CPU - {535A9671-08A0-46DD-8191-DC9B995DF425}.Checked|x64.ActiveCfg = Debug|Any CPU - {535A9671-08A0-46DD-8191-DC9B995DF425}.Checked|x64.Build.0 = Debug|Any CPU - {535A9671-08A0-46DD-8191-DC9B995DF425}.Checked|x86.ActiveCfg = Debug|Any CPU - {535A9671-08A0-46DD-8191-DC9B995DF425}.Checked|x86.Build.0 = Debug|Any CPU + {8EAD8906-AF4E-42CA-983E-28CFE2224AEE}.Checked|Any CPU.ActiveCfg = Debug|Any CPU + {8EAD8906-AF4E-42CA-983E-28CFE2224AEE}.Checked|Any CPU.Build.0 = Debug|Any CPU + {8EAD8906-AF4E-42CA-983E-28CFE2224AEE}.Checked|x64.ActiveCfg = Debug|Any CPU + {8EAD8906-AF4E-42CA-983E-28CFE2224AEE}.Checked|x64.Build.0 = Debug|Any CPU + {8EAD8906-AF4E-42CA-983E-28CFE2224AEE}.Checked|x86.ActiveCfg = Debug|Any CPU + {8EAD8906-AF4E-42CA-983E-28CFE2224AEE}.Checked|x86.Build.0 = Debug|Any CPU {8EAD8906-AF4E-42CA-983E-28CFE2224AEE}.Debug|Any CPU.ActiveCfg = Debug|Any CPU {8EAD8906-AF4E-42CA-983E-28CFE2224AEE}.Debug|Any CPU.Build.0 = Debug|Any CPU {8EAD8906-AF4E-42CA-983E-28CFE2224AEE}.Debug|x64.ActiveCfg = Debug|Any CPU @@ -348,12 +360,12 @@ Global {8EAD8906-AF4E-42CA-983E-28CFE2224AEE}.Release|x64.Build.0 = Release|Any CPU {8EAD8906-AF4E-42CA-983E-28CFE2224AEE}.Release|x86.ActiveCfg = Release|Any CPU {8EAD8906-AF4E-42CA-983E-28CFE2224AEE}.Release|x86.Build.0 = Release|Any CPU - {8EAD8906-AF4E-42CA-983E-28CFE2224AEE}.Checked|Any CPU.ActiveCfg = Debug|Any CPU - {8EAD8906-AF4E-42CA-983E-28CFE2224AEE}.Checked|Any CPU.Build.0 = Debug|Any CPU - {8EAD8906-AF4E-42CA-983E-28CFE2224AEE}.Checked|x64.ActiveCfg = Debug|Any CPU - {8EAD8906-AF4E-42CA-983E-28CFE2224AEE}.Checked|x64.Build.0 = Debug|Any CPU - {8EAD8906-AF4E-42CA-983E-28CFE2224AEE}.Checked|x86.ActiveCfg = Debug|Any CPU - {8EAD8906-AF4E-42CA-983E-28CFE2224AEE}.Checked|x86.Build.0 = Debug|Any CPU + {4DAA5CFC-C59D-4C1B-A12A-BC9863F38C0C}.Checked|Any CPU.ActiveCfg = Debug|Any CPU + {4DAA5CFC-C59D-4C1B-A12A-BC9863F38C0C}.Checked|Any CPU.Build.0 = Debug|Any CPU + {4DAA5CFC-C59D-4C1B-A12A-BC9863F38C0C}.Checked|x64.ActiveCfg = Debug|Any CPU + {4DAA5CFC-C59D-4C1B-A12A-BC9863F38C0C}.Checked|x64.Build.0 = Debug|Any CPU + {4DAA5CFC-C59D-4C1B-A12A-BC9863F38C0C}.Checked|x86.ActiveCfg = Debug|Any CPU + {4DAA5CFC-C59D-4C1B-A12A-BC9863F38C0C}.Checked|x86.Build.0 = Debug|Any CPU {4DAA5CFC-C59D-4C1B-A12A-BC9863F38C0C}.Debug|Any CPU.ActiveCfg = Debug|Any CPU {4DAA5CFC-C59D-4C1B-A12A-BC9863F38C0C}.Debug|Any CPU.Build.0 = Debug|Any CPU {4DAA5CFC-C59D-4C1B-A12A-BC9863F38C0C}.Debug|x64.ActiveCfg = Debug|Any CPU @@ -366,12 +378,12 @@ Global {4DAA5CFC-C59D-4C1B-A12A-BC9863F38C0C}.Release|x64.Build.0 = Release|Any CPU {4DAA5CFC-C59D-4C1B-A12A-BC9863F38C0C}.Release|x86.ActiveCfg = Release|Any CPU {4DAA5CFC-C59D-4C1B-A12A-BC9863F38C0C}.Release|x86.Build.0 = Release|Any CPU - {4DAA5CFC-C59D-4C1B-A12A-BC9863F38C0C}.Checked|Any CPU.ActiveCfg = Debug|Any CPU - {4DAA5CFC-C59D-4C1B-A12A-BC9863F38C0C}.Checked|Any CPU.Build.0 = Debug|Any CPU - {4DAA5CFC-C59D-4C1B-A12A-BC9863F38C0C}.Checked|x64.ActiveCfg = Debug|Any CPU - {4DAA5CFC-C59D-4C1B-A12A-BC9863F38C0C}.Checked|x64.Build.0 = Debug|Any CPU - {4DAA5CFC-C59D-4C1B-A12A-BC9863F38C0C}.Checked|x86.ActiveCfg = Debug|Any CPU - {4DAA5CFC-C59D-4C1B-A12A-BC9863F38C0C}.Checked|x86.Build.0 = Debug|Any CPU + {2F5DA438-6CBA-42AA-818A-64C633A56D55}.Checked|Any CPU.ActiveCfg = Debug|Any CPU + {2F5DA438-6CBA-42AA-818A-64C633A56D55}.Checked|Any CPU.Build.0 = Debug|Any CPU + {2F5DA438-6CBA-42AA-818A-64C633A56D55}.Checked|x64.ActiveCfg = Debug|Any CPU + {2F5DA438-6CBA-42AA-818A-64C633A56D55}.Checked|x64.Build.0 = Debug|Any CPU + {2F5DA438-6CBA-42AA-818A-64C633A56D55}.Checked|x86.ActiveCfg = Debug|Any CPU + {2F5DA438-6CBA-42AA-818A-64C633A56D55}.Checked|x86.Build.0 = Debug|Any CPU {2F5DA438-6CBA-42AA-818A-64C633A56D55}.Debug|Any CPU.ActiveCfg = Debug|Any CPU {2F5DA438-6CBA-42AA-818A-64C633A56D55}.Debug|Any CPU.Build.0 = Debug|Any CPU {2F5DA438-6CBA-42AA-818A-64C633A56D55}.Debug|x64.ActiveCfg = Debug|Any CPU @@ -384,12 +396,12 @@ Global {2F5DA438-6CBA-42AA-818A-64C633A56D55}.Release|x64.Build.0 = Release|Any CPU {2F5DA438-6CBA-42AA-818A-64C633A56D55}.Release|x86.ActiveCfg = Release|Any CPU {2F5DA438-6CBA-42AA-818A-64C633A56D55}.Release|x86.Build.0 = Release|Any CPU - {2F5DA438-6CBA-42AA-818A-64C633A56D55}.Checked|Any CPU.ActiveCfg = Debug|Any CPU - {2F5DA438-6CBA-42AA-818A-64C633A56D55}.Checked|Any CPU.Build.0 = Debug|Any CPU - {2F5DA438-6CBA-42AA-818A-64C633A56D55}.Checked|x64.ActiveCfg = Debug|Any CPU - {2F5DA438-6CBA-42AA-818A-64C633A56D55}.Checked|x64.Build.0 = Debug|Any CPU - {2F5DA438-6CBA-42AA-818A-64C633A56D55}.Checked|x86.ActiveCfg = Debug|Any CPU - {2F5DA438-6CBA-42AA-818A-64C633A56D55}.Checked|x86.Build.0 = Debug|Any CPU + {A17B970B-41B2-4C78-BA05-2B954357E46A}.Checked|Any CPU.ActiveCfg = Debug|Any CPU + {A17B970B-41B2-4C78-BA05-2B954357E46A}.Checked|Any CPU.Build.0 = Debug|Any CPU + {A17B970B-41B2-4C78-BA05-2B954357E46A}.Checked|x64.ActiveCfg = Debug|Any CPU + {A17B970B-41B2-4C78-BA05-2B954357E46A}.Checked|x64.Build.0 = Debug|Any CPU + {A17B970B-41B2-4C78-BA05-2B954357E46A}.Checked|x86.ActiveCfg = Debug|Any CPU + {A17B970B-41B2-4C78-BA05-2B954357E46A}.Checked|x86.Build.0 = Debug|Any CPU {A17B970B-41B2-4C78-BA05-2B954357E46A}.Debug|Any CPU.ActiveCfg = Debug|Any CPU {A17B970B-41B2-4C78-BA05-2B954357E46A}.Debug|Any CPU.Build.0 = Debug|Any CPU {A17B970B-41B2-4C78-BA05-2B954357E46A}.Debug|x64.ActiveCfg = Debug|Any CPU @@ -402,12 +414,12 @@ Global {A17B970B-41B2-4C78-BA05-2B954357E46A}.Release|x64.Build.0 = Release|Any CPU {A17B970B-41B2-4C78-BA05-2B954357E46A}.Release|x86.ActiveCfg = Release|Any CPU {A17B970B-41B2-4C78-BA05-2B954357E46A}.Release|x86.Build.0 = Release|Any CPU - {A17B970B-41B2-4C78-BA05-2B954357E46A}.Checked|Any CPU.ActiveCfg = Debug|Any CPU - {A17B970B-41B2-4C78-BA05-2B954357E46A}.Checked|Any CPU.Build.0 = Debug|Any CPU - {A17B970B-41B2-4C78-BA05-2B954357E46A}.Checked|x64.ActiveCfg = Debug|Any CPU - {A17B970B-41B2-4C78-BA05-2B954357E46A}.Checked|x64.Build.0 = Debug|Any CPU - {A17B970B-41B2-4C78-BA05-2B954357E46A}.Checked|x86.ActiveCfg = Debug|Any CPU - {A17B970B-41B2-4C78-BA05-2B954357E46A}.Checked|x86.Build.0 = Debug|Any CPU + {3D4EEB00-D4E0-4581-A144-51EFF8319FFB}.Checked|Any CPU.ActiveCfg = Debug|Any CPU + {3D4EEB00-D4E0-4581-A144-51EFF8319FFB}.Checked|Any CPU.Build.0 = Debug|Any CPU + {3D4EEB00-D4E0-4581-A144-51EFF8319FFB}.Checked|x64.ActiveCfg = Debug|Any CPU + {3D4EEB00-D4E0-4581-A144-51EFF8319FFB}.Checked|x64.Build.0 = Debug|Any CPU + {3D4EEB00-D4E0-4581-A144-51EFF8319FFB}.Checked|x86.ActiveCfg = Debug|Any CPU + {3D4EEB00-D4E0-4581-A144-51EFF8319FFB}.Checked|x86.Build.0 = Debug|Any CPU {3D4EEB00-D4E0-4581-A144-51EFF8319FFB}.Debug|Any CPU.ActiveCfg = Debug|Any CPU {3D4EEB00-D4E0-4581-A144-51EFF8319FFB}.Debug|Any CPU.Build.0 = Debug|Any CPU {3D4EEB00-D4E0-4581-A144-51EFF8319FFB}.Debug|x64.ActiveCfg = Debug|Any CPU @@ -420,12 +432,12 @@ Global {3D4EEB00-D4E0-4581-A144-51EFF8319FFB}.Release|x64.Build.0 = Release|Any CPU {3D4EEB00-D4E0-4581-A144-51EFF8319FFB}.Release|x86.ActiveCfg = Release|Any CPU {3D4EEB00-D4E0-4581-A144-51EFF8319FFB}.Release|x86.Build.0 = Release|Any CPU - {3D4EEB00-D4E0-4581-A144-51EFF8319FFB}.Checked|Any CPU.ActiveCfg = Debug|Any CPU - {3D4EEB00-D4E0-4581-A144-51EFF8319FFB}.Checked|Any CPU.Build.0 = Debug|Any CPU - {3D4EEB00-D4E0-4581-A144-51EFF8319FFB}.Checked|x64.ActiveCfg = Debug|Any CPU - {3D4EEB00-D4E0-4581-A144-51EFF8319FFB}.Checked|x64.Build.0 = Debug|Any CPU - {3D4EEB00-D4E0-4581-A144-51EFF8319FFB}.Checked|x86.ActiveCfg = Debug|Any CPU - {3D4EEB00-D4E0-4581-A144-51EFF8319FFB}.Checked|x86.Build.0 = Debug|Any CPU + {637E7769-42D2-4541-9A63-32301113FA5A}.Checked|Any CPU.ActiveCfg = Debug|Any CPU + {637E7769-42D2-4541-9A63-32301113FA5A}.Checked|Any CPU.Build.0 = Debug|Any CPU + {637E7769-42D2-4541-9A63-32301113FA5A}.Checked|x64.ActiveCfg = Debug|Any CPU + {637E7769-42D2-4541-9A63-32301113FA5A}.Checked|x64.Build.0 = Debug|Any CPU + {637E7769-42D2-4541-9A63-32301113FA5A}.Checked|x86.ActiveCfg = Debug|Any CPU + {637E7769-42D2-4541-9A63-32301113FA5A}.Checked|x86.Build.0 = Debug|Any CPU {637E7769-42D2-4541-9A63-32301113FA5A}.Debug|Any CPU.ActiveCfg = Debug|Any CPU {637E7769-42D2-4541-9A63-32301113FA5A}.Debug|Any CPU.Build.0 = Debug|Any CPU {637E7769-42D2-4541-9A63-32301113FA5A}.Debug|x64.ActiveCfg = Debug|Any CPU @@ -438,12 +450,12 @@ Global {637E7769-42D2-4541-9A63-32301113FA5A}.Release|x64.Build.0 = Release|Any CPU {637E7769-42D2-4541-9A63-32301113FA5A}.Release|x86.ActiveCfg = Release|Any CPU {637E7769-42D2-4541-9A63-32301113FA5A}.Release|x86.Build.0 = Release|Any CPU - {637E7769-42D2-4541-9A63-32301113FA5A}.Checked|Any CPU.ActiveCfg = Debug|Any CPU - {637E7769-42D2-4541-9A63-32301113FA5A}.Checked|Any CPU.Build.0 = Debug|Any CPU - {637E7769-42D2-4541-9A63-32301113FA5A}.Checked|x64.ActiveCfg = Debug|Any CPU - {637E7769-42D2-4541-9A63-32301113FA5A}.Checked|x64.Build.0 = Debug|Any CPU - {637E7769-42D2-4541-9A63-32301113FA5A}.Checked|x86.ActiveCfg = Debug|Any CPU - {637E7769-42D2-4541-9A63-32301113FA5A}.Checked|x86.Build.0 = Debug|Any CPU + {7D404296-72F5-4F99-931F-73791FAB3E14}.Checked|Any CPU.ActiveCfg = Debug|Any CPU + {7D404296-72F5-4F99-931F-73791FAB3E14}.Checked|Any CPU.Build.0 = Debug|Any CPU + {7D404296-72F5-4F99-931F-73791FAB3E14}.Checked|x64.ActiveCfg = Debug|Any CPU + {7D404296-72F5-4F99-931F-73791FAB3E14}.Checked|x64.Build.0 = Debug|Any CPU + {7D404296-72F5-4F99-931F-73791FAB3E14}.Checked|x86.ActiveCfg = Debug|Any CPU + {7D404296-72F5-4F99-931F-73791FAB3E14}.Checked|x86.Build.0 = Debug|Any CPU {7D404296-72F5-4F99-931F-73791FAB3E14}.Debug|Any CPU.ActiveCfg = Debug|Any CPU {7D404296-72F5-4F99-931F-73791FAB3E14}.Debug|Any CPU.Build.0 = Debug|Any CPU {7D404296-72F5-4F99-931F-73791FAB3E14}.Debug|x64.ActiveCfg = Debug|Any CPU @@ -456,12 +468,12 @@ Global {7D404296-72F5-4F99-931F-73791FAB3E14}.Release|x64.Build.0 = Release|Any CPU {7D404296-72F5-4F99-931F-73791FAB3E14}.Release|x86.ActiveCfg = Release|Any CPU {7D404296-72F5-4F99-931F-73791FAB3E14}.Release|x86.Build.0 = Release|Any CPU - {7D404296-72F5-4F99-931F-73791FAB3E14}.Checked|Any CPU.ActiveCfg = Debug|Any CPU - {7D404296-72F5-4F99-931F-73791FAB3E14}.Checked|Any CPU.Build.0 = Debug|Any CPU - {7D404296-72F5-4F99-931F-73791FAB3E14}.Checked|x64.ActiveCfg = Debug|Any CPU - {7D404296-72F5-4F99-931F-73791FAB3E14}.Checked|x64.Build.0 = Debug|Any CPU - {7D404296-72F5-4F99-931F-73791FAB3E14}.Checked|x86.ActiveCfg = Debug|Any CPU - {7D404296-72F5-4F99-931F-73791FAB3E14}.Checked|x86.Build.0 = Debug|Any CPU + {7C0A6923-A9BC-4F10-81E0-C535EEF537BB}.Checked|Any CPU.ActiveCfg = Debug|Any CPU + {7C0A6923-A9BC-4F10-81E0-C535EEF537BB}.Checked|Any CPU.Build.0 = Debug|Any CPU + {7C0A6923-A9BC-4F10-81E0-C535EEF537BB}.Checked|x64.ActiveCfg = Debug|Any CPU + {7C0A6923-A9BC-4F10-81E0-C535EEF537BB}.Checked|x64.Build.0 = Debug|Any CPU + {7C0A6923-A9BC-4F10-81E0-C535EEF537BB}.Checked|x86.ActiveCfg = Debug|Any CPU + {7C0A6923-A9BC-4F10-81E0-C535EEF537BB}.Checked|x86.Build.0 = Debug|Any CPU {7C0A6923-A9BC-4F10-81E0-C535EEF537BB}.Debug|Any CPU.ActiveCfg = Debug|Any CPU {7C0A6923-A9BC-4F10-81E0-C535EEF537BB}.Debug|Any CPU.Build.0 = Debug|Any CPU {7C0A6923-A9BC-4F10-81E0-C535EEF537BB}.Debug|x64.ActiveCfg = Debug|Any CPU @@ -474,42 +486,58 @@ Global {7C0A6923-A9BC-4F10-81E0-C535EEF537BB}.Release|x64.Build.0 = Release|Any CPU {7C0A6923-A9BC-4F10-81E0-C535EEF537BB}.Release|x86.ActiveCfg = Release|Any CPU {7C0A6923-A9BC-4F10-81E0-C535EEF537BB}.Release|x86.Build.0 = Release|Any CPU - {7C0A6923-A9BC-4F10-81E0-C535EEF537BB}.Checked|Any CPU.ActiveCfg = Debug|Any CPU - {7C0A6923-A9BC-4F10-81E0-C535EEF537BB}.Checked|Any CPU.Build.0 = Debug|Any CPU - {7C0A6923-A9BC-4F10-81E0-C535EEF537BB}.Checked|x64.ActiveCfg = Debug|Any CPU - {7C0A6923-A9BC-4F10-81E0-C535EEF537BB}.Checked|x64.Build.0 = Debug|Any CPU - {7C0A6923-A9BC-4F10-81E0-C535EEF537BB}.Checked|x86.ActiveCfg = Debug|Any CPU - {7C0A6923-A9BC-4F10-81E0-C535EEF537BB}.Checked|x86.Build.0 = Debug|Any CPU + {422C9340-E720-4554-B6AC-560A19FE16B1}.Checked|Any CPU.ActiveCfg = Debug|Any CPU + {422C9340-E720-4554-B6AC-560A19FE16B1}.Checked|Any CPU.Build.0 = Debug|Any CPU + {422C9340-E720-4554-B6AC-560A19FE16B1}.Checked|x64.ActiveCfg = Debug|Any CPU + {422C9340-E720-4554-B6AC-560A19FE16B1}.Checked|x64.Build.0 = Debug|Any CPU + {422C9340-E720-4554-B6AC-560A19FE16B1}.Checked|x86.ActiveCfg = Debug|Any CPU + {422C9340-E720-4554-B6AC-560A19FE16B1}.Checked|x86.Build.0 = Debug|Any CPU + {422C9340-E720-4554-B6AC-560A19FE16B1}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {422C9340-E720-4554-B6AC-560A19FE16B1}.Debug|Any CPU.Build.0 = Debug|Any CPU + {422C9340-E720-4554-B6AC-560A19FE16B1}.Debug|x64.ActiveCfg = Debug|Any CPU + {422C9340-E720-4554-B6AC-560A19FE16B1}.Debug|x64.Build.0 = Debug|Any CPU + {422C9340-E720-4554-B6AC-560A19FE16B1}.Debug|x86.ActiveCfg = Debug|Any CPU + {422C9340-E720-4554-B6AC-560A19FE16B1}.Debug|x86.Build.0 = Debug|Any CPU + {422C9340-E720-4554-B6AC-560A19FE16B1}.Release|Any CPU.ActiveCfg = Release|Any CPU + {422C9340-E720-4554-B6AC-560A19FE16B1}.Release|Any CPU.Build.0 = Release|Any CPU + {422C9340-E720-4554-B6AC-560A19FE16B1}.Release|x64.ActiveCfg = Release|Any CPU + {422C9340-E720-4554-B6AC-560A19FE16B1}.Release|x64.Build.0 = Release|Any CPU + {422C9340-E720-4554-B6AC-560A19FE16B1}.Release|x86.ActiveCfg = Release|Any CPU + {422C9340-E720-4554-B6AC-560A19FE16B1}.Release|x86.Build.0 = Release|Any CPU EndGlobalSection GlobalSection(SolutionProperties) = preSolution HideSolutionNode = FALSE EndGlobalSection GlobalSection(NestedProjects) = preSolution {89B01AF7-F0CE-4168-8C4A-33FCDCF33B73} = {315BC231-270B-456C-919A-3E9BB50CDD7A} - {89C01491-2BE8-438C-8F1D-24DE9AFD7A86} = {315BC231-270B-456C-919A-3E9BB50CDD7A} - {64F83961-AECA-4D5C-B467-A1A94AE6FFB4} = {315BC231-270B-456C-919A-3E9BB50CDD7A} - {95F843FE-38B4-4ED5-81FF-605DE38155F6} = {315BC231-270B-456C-919A-3E9BB50CDD7A} - {97D756D3-8ECA-45F5-A9F5-DBF659D87BC4} = {315BC231-270B-456C-919A-3E9BB50CDD7A} - {48CC1460-B1E7-4DE9-A4E7-2206F7FD54CF} = {315BC231-270B-456C-919A-3E9BB50CDD7A} - {4DAA5CFC-C59D-4C1B-A12A-BC9863F38C0C} = {315BC231-270B-456C-919A-3E9BB50CDD7A} - {637E7769-42D2-4541-9A63-32301113FA5A} = {315BC231-270B-456C-919A-3E9BB50CDD7A} - {7C0A6923-A9BC-4F10-81E0-C535EEF537BB} = {315BC231-270B-456C-919A-3E9BB50CDD7A} {F6BCA6EF-777E-408B-B49B-B055B5A0BA19} = {6BA02609-AE23-4E80-8B4B-9C6548AA147A} - {0C126AE9-C858-4AC8-9DB1-B8E228BD2DB0} = {6BA02609-AE23-4E80-8B4B-9C6548AA147A} {A26E9B9C-AFE7-4740-AC73-626D9823E515} = {1826CD8D-A5E3-4C8E-A49A-E746D9682B87} + {89C01491-2BE8-438C-8F1D-24DE9AFD7A86} = {315BC231-270B-456C-919A-3E9BB50CDD7A} {51AEBD0E-0A93-4532-A010-CAAF8E320D6C} = {1826CD8D-A5E3-4C8E-A49A-E746D9682B87} + {64F83961-AECA-4D5C-B467-A1A94AE6FFB4} = {315BC231-270B-456C-919A-3E9BB50CDD7A} {279066F9-4DB9-4897-8CE4-66BC31118323} = {1826CD8D-A5E3-4C8E-A49A-E746D9682B87} + {95F843FE-38B4-4ED5-81FF-605DE38155F6} = {315BC231-270B-456C-919A-3E9BB50CDD7A} {ED544AD5-41C5-4445-BC0F-EFA1553C881A} = {1826CD8D-A5E3-4C8E-A49A-E746D9682B87} + {97D756D3-8ECA-45F5-A9F5-DBF659D87BC4} = {315BC231-270B-456C-919A-3E9BB50CDD7A} {83696A63-CF89-4DE4-8F79-96F5B830A4B6} = {1826CD8D-A5E3-4C8E-A49A-E746D9682B87} {2F00396E-003A-4385-92DC-69FDBEF330D8} = {1826CD8D-A5E3-4C8E-A49A-E746D9682B87} + {48CC1460-B1E7-4DE9-A4E7-2206F7FD54CF} = {315BC231-270B-456C-919A-3E9BB50CDD7A} + {0C126AE9-C858-4AC8-9DB1-B8E228BD2DB0} = {6BA02609-AE23-4E80-8B4B-9C6548AA147A} {535A9671-08A0-46DD-8191-DC9B995DF425} = {1826CD8D-A5E3-4C8E-A49A-E746D9682B87} - {3D4EEB00-D4E0-4581-A144-51EFF8319FFB} = {1826CD8D-A5E3-4C8E-A49A-E746D9682B87} - {7D404296-72F5-4F99-931F-73791FAB3E14} = {1826CD8D-A5E3-4C8E-A49A-E746D9682B87} {8EAD8906-AF4E-42CA-983E-28CFE2224AEE} = {BDABB39C-A9FF-4A9B-8BA2-EF873C5EEB16} + {4DAA5CFC-C59D-4C1B-A12A-BC9863F38C0C} = {315BC231-270B-456C-919A-3E9BB50CDD7A} {2F5DA438-6CBA-42AA-818A-64C633A56D55} = {BDABB39C-A9FF-4A9B-8BA2-EF873C5EEB16} {A17B970B-41B2-4C78-BA05-2B954357E46A} = {BDABB39C-A9FF-4A9B-8BA2-EF873C5EEB16} + {3D4EEB00-D4E0-4581-A144-51EFF8319FFB} = {1826CD8D-A5E3-4C8E-A49A-E746D9682B87} + {637E7769-42D2-4541-9A63-32301113FA5A} = {315BC231-270B-456C-919A-3E9BB50CDD7A} + {7D404296-72F5-4F99-931F-73791FAB3E14} = {1826CD8D-A5E3-4C8E-A49A-E746D9682B87} + {7C0A6923-A9BC-4F10-81E0-C535EEF537BB} = {315BC231-270B-456C-919A-3E9BB50CDD7A} + {422C9340-E720-4554-B6AC-560A19FE16B1} = {6BA02609-AE23-4E80-8B4B-9C6548AA147A} EndGlobalSection GlobalSection(ExtensibilityGlobals) = postSolution SolutionGuid = {52B54BB6-271E-45BD-A7A4-D4CEDC973704} EndGlobalSection + GlobalSection(SharedMSBuildProjectFiles) = preSolution + ..\System.Private.CoreLib\src\System.Private.CoreLib.Shared.projitems*{89b01af7-f0ce-4168-8c4a-33fcdcf33b73}*SharedItemsImports = 5 + EndGlobalSection EndGlobal diff --git a/src/libraries/System.Diagnostics.TraceSource/ref/System.Diagnostics.TraceSource.cs b/src/libraries/System.Diagnostics.TraceSource/ref/System.Diagnostics.TraceSource.cs index 554d40142f6c0f..3831073431a074 100644 --- a/src/libraries/System.Diagnostics.TraceSource/ref/System.Diagnostics.TraceSource.cs +++ b/src/libraries/System.Diagnostics.TraceSource/ref/System.Diagnostics.TraceSource.cs @@ -39,6 +39,17 @@ public EventTypeFilter(System.Diagnostics.SourceLevels level) { } public System.Diagnostics.SourceLevels EventType { get { throw null; } set { } } public override bool ShouldTrace(System.Diagnostics.TraceEventCache? cache, string source, System.Diagnostics.TraceEventType eventType, int id, [System.Diagnostics.CodeAnalysis.StringSyntaxAttribute("CompositeFormat")] string? formatOrMessage, object?[]? args, object? data1, object?[]? data) { throw null; } } + public sealed partial class InitializingSwitchEventArgs : System.EventArgs + { + public InitializingSwitchEventArgs(System.Diagnostics.Switch @switch) { } + public System.Diagnostics.Switch Switch { get { throw null; } } + } + public sealed partial class InitializingTraceSourceEventArgs : System.EventArgs + { + public InitializingTraceSourceEventArgs(System.Diagnostics.TraceSource traceSource) { } + public System.Diagnostics.TraceSource TraceSource { get { throw null; } } + public bool WasInitialized { get { throw null; } set { } } + } public partial class SourceFilter : System.Diagnostics.TraceFilter { public SourceFilter(string source) { } @@ -71,13 +82,16 @@ public abstract partial class Switch protected Switch(string displayName, string? description) { } protected Switch(string displayName, string? description, string defaultSwitchValue) { } public System.Collections.Specialized.StringDictionary Attributes { get { throw null; } } + public string DefaultValue { get { throw null; } } public string Description { get { throw null; } } public string DisplayName { get { throw null; } } + public static event System.EventHandler? Initializing { add { } remove { } } protected int SwitchSetting { get { throw null; } set { } } - protected string Value { get { throw null; } set { } } + public string Value { get { throw null; } set { } } protected virtual string[]? GetSupportedAttributes() { throw null; } protected virtual void OnSwitchSettingChanged() { } protected virtual void OnValueChanged() { } + public void Refresh() { } } [System.AttributeUsageAttribute(System.AttributeTargets.Assembly | System.AttributeTargets.Class | System.AttributeTargets.Constructor | System.AttributeTargets.Event | System.AttributeTargets.Method | System.AttributeTargets.Property)] public sealed partial class SwitchAttribute : System.Attribute @@ -121,6 +135,7 @@ public static void Flush() { } [System.Diagnostics.ConditionalAttribute("TRACE")] public static void Indent() { } public static void Refresh() { } + public static event System.EventHandler? Refreshing { add { } remove { } } [System.Diagnostics.ConditionalAttribute("TRACE")] public static void TraceError(string? message) { } [System.Diagnostics.ConditionalAttribute("TRACE")] @@ -286,6 +301,8 @@ public partial class TraceSource public TraceSource(string name) { } public TraceSource(string name, System.Diagnostics.SourceLevels defaultLevel) { } public System.Collections.Specialized.StringDictionary Attributes { get { throw null; } } + public System.Diagnostics.SourceLevels DefaultLevel { get { throw null; } } + public static event System.EventHandler? Initializing { add { } remove { } } public System.Diagnostics.TraceListenerCollection Listeners { get { throw null; } } public string Name { get { throw null; } } public System.Diagnostics.SourceSwitch Switch { get { throw null; } set { } } diff --git a/src/libraries/System.Diagnostics.TraceSource/src/Resources/Strings.resx b/src/libraries/System.Diagnostics.TraceSource/src/Resources/Strings.resx index 4062db3292bae6..36fd421db660e4 100644 --- a/src/libraries/System.Diagnostics.TraceSource/src/Resources/Strings.resx +++ b/src/libraries/System.Diagnostics.TraceSource/src/Resources/Strings.resx @@ -58,6 +58,9 @@ System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + '{0}' is not a valid attribute for type '{1}'. + An exception occurred while writing to the log file {0}: {1}. diff --git a/src/libraries/System.Diagnostics.TraceSource/src/System.Diagnostics.TraceSource.csproj b/src/libraries/System.Diagnostics.TraceSource/src/System.Diagnostics.TraceSource.csproj index 0cd26b1f5e6c70..a97fe112aee959 100644 --- a/src/libraries/System.Diagnostics.TraceSource/src/System.Diagnostics.TraceSource.csproj +++ b/src/libraries/System.Diagnostics.TraceSource/src/System.Diagnostics.TraceSource.csproj @@ -1,10 +1,12 @@ - + $(DefineConstants);TRACE $(NetCoreAppCurrent) + + @@ -24,6 +26,7 @@ + diff --git a/src/libraries/System.Diagnostics.TraceSource/src/System/Diagnostics/DefaultTraceListener.cs b/src/libraries/System.Diagnostics.TraceSource/src/System/Diagnostics/DefaultTraceListener.cs index 665b85850cbe9d..e808e3f8c56f2c 100644 --- a/src/libraries/System.Diagnostics.TraceSource/src/System/Diagnostics/DefaultTraceListener.cs +++ b/src/libraries/System.Diagnostics.TraceSource/src/System/Diagnostics/DefaultTraceListener.cs @@ -1,8 +1,6 @@ // Licensed to the .NET Foundation under one or more agreements. // The .NET Foundation licenses this file to you under the MIT license. -#define DEBUG -#define TRACE using System; using System.IO; using System.Text; diff --git a/src/libraries/System.Diagnostics.TraceSource/src/System/Diagnostics/InitializingSwitchEventArgs.cs b/src/libraries/System.Diagnostics.TraceSource/src/System/Diagnostics/InitializingSwitchEventArgs.cs new file mode 100644 index 00000000000000..651bfd29fb0c77 --- /dev/null +++ b/src/libraries/System.Diagnostics.TraceSource/src/System/Diagnostics/InitializingSwitchEventArgs.cs @@ -0,0 +1,18 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. + +namespace System.Diagnostics +{ + /// + /// Provides data for the event. + /// + public sealed class InitializingSwitchEventArgs : EventArgs + { + public InitializingSwitchEventArgs(Switch @switch) + { + Switch = @switch; + } + + public Switch Switch { get; } + } +} diff --git a/src/libraries/System.Diagnostics.TraceSource/src/System/Diagnostics/InitializingTraceSourceEventArgs.cs b/src/libraries/System.Diagnostics.TraceSource/src/System/Diagnostics/InitializingTraceSourceEventArgs.cs new file mode 100644 index 00000000000000..b4b3aac66ac5cc --- /dev/null +++ b/src/libraries/System.Diagnostics.TraceSource/src/System/Diagnostics/InitializingTraceSourceEventArgs.cs @@ -0,0 +1,19 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. + +namespace System.Diagnostics +{ + /// + /// Provides data for the event. + /// + public sealed class InitializingTraceSourceEventArgs : EventArgs + { + public InitializingTraceSourceEventArgs(TraceSource traceSource) + { + TraceSource = traceSource; + } + + public TraceSource TraceSource { get; } + public bool WasInitialized { get; set; } + } +} diff --git a/src/libraries/System.Diagnostics.TraceSource/src/System/Diagnostics/Switch.cs b/src/libraries/System.Diagnostics.TraceSource/src/System/Diagnostics/Switch.cs index 1b50f00c1cea4e..3ea419aaf50407 100644 --- a/src/libraries/System.Diagnostics.TraceSource/src/System/Diagnostics/Switch.cs +++ b/src/libraries/System.Diagnostics.TraceSource/src/System/Diagnostics/Switch.cs @@ -23,7 +23,7 @@ public abstract class Switch private int _switchSetting; private volatile bool _initialized; private bool _initializing; - private volatile string _switchValueString = string.Empty; + private volatile string? _switchValueString = string.Empty; private readonly string _defaultValue; private object? _initializedLock; @@ -137,7 +137,9 @@ protected int SwitchSetting if (!_initialized) { if (InitializeWithStatus()) + { OnSwitchSettingChanged(); + } } return _switchSetting; } @@ -163,12 +165,17 @@ protected int SwitchSetting protected internal virtual string[]? GetSupportedAttributes() => null; - protected string Value + /// + /// The default value assigned in the constructor. + /// + public string DefaultValue => _defaultValue; + + public string Value { get { Initialize(); - return _switchValueString; + return _switchValueString!; } set { @@ -178,6 +185,17 @@ protected string Value } } + /// + /// Occurs when a needs to be initialized. + /// + public static event EventHandler? Initializing; + + internal void OnInitializing() + { + Initializing?.Invoke(null, new InitializingSwitchEventArgs(this)); + TraceUtils.VerifyAttributes(Attributes, GetSupportedAttributes(), this); + } + private void Initialize() { InitializeWithStatus(); @@ -194,12 +212,29 @@ private bool InitializeWithStatus() return false; } - // This method is re-entrent during initialization, since calls to OnValueChanged() in subclasses could end up having InitializeWithStatus() + // This method is re-entrant during initialization, since calls to OnValueChanged() in subclasses could end up having InitializeWithStatus() // called again, we don't want to get caught in an infinite loop. _initializing = true; - _switchValueString = _defaultValue; - OnValueChanged(); + _switchValueString = null; + + try + { + OnInitializing(); + } + catch (Exception) + { + _initialized = false; + _initializing = false; + throw; + } + + if (_switchValueString == null) + { + _switchValueString = _defaultValue; + OnValueChanged(); + } + _initialized = true; _initializing = false; } @@ -238,7 +273,10 @@ internal static void RefreshAll() } } - internal void Refresh() + /// + /// Refreshes the trace configuration data. + /// + public void Refresh() { lock (InitializedLock) { diff --git a/src/libraries/System.Diagnostics.TraceSource/src/System/Diagnostics/Trace.cs b/src/libraries/System.Diagnostics.TraceSource/src/System/Diagnostics/Trace.cs index 40c31c7769bc2b..22e4c6b1e2c9dc 100644 --- a/src/libraries/System.Diagnostics.TraceSource/src/System/Diagnostics/Trace.cs +++ b/src/libraries/System.Diagnostics.TraceSource/src/System/Diagnostics/Trace.cs @@ -159,8 +159,19 @@ public static void Fail(string? message, string? detailMessage) TraceInternal.Fail(message, detailMessage); } + /// + /// Occurs when a needs to be refreshed from configuration. + /// + public static event EventHandler? Refreshing; + + internal static void OnRefreshing() + { + Refreshing?.Invoke(null, EventArgs.Empty); + } + public static void Refresh() { + OnRefreshing(); Switch.RefreshAll(); TraceSource.RefreshAll(); TraceInternal.Refresh(); diff --git a/src/libraries/System.Diagnostics.TraceSource/src/System/Diagnostics/TraceInternal.cs b/src/libraries/System.Diagnostics.TraceSource/src/System/Diagnostics/TraceInternal.cs index 0ebc7fe389045f..0454ae306aa3bd 100644 --- a/src/libraries/System.Diagnostics.TraceSource/src/System/Diagnostics/TraceInternal.cs +++ b/src/libraries/System.Diagnostics.TraceSource/src/System/Diagnostics/TraceInternal.cs @@ -46,6 +46,7 @@ public override void OnIndentSizeChanged(int indentSize) private static volatile bool s_autoFlush; private static volatile bool s_useGlobalLock; private static volatile bool s_settingsInitialized; + private static volatile bool s_settingsInitializing; // this is internal so TraceSource can use it. We want to lock on the same object because both TraceInternal and @@ -284,15 +285,24 @@ private static void InitializeSettings() { if (!s_settingsInitialized) { - // we should avoid 2 threads altering the state concurrently for predictable behavior - // though it may not be strictly necessary at present + // We should avoid 2 threads altering the state concurrently for predictable behavior + // though it may not be strictly necessary at present. lock (critSec) { + // Prevent re-entrance. + if (s_settingsInitializing) + { + return; + } + + s_settingsInitializing = true; + if (!s_settingsInitialized) { s_autoFlush = DiagnosticsConfiguration.AutoFlush; s_useGlobalLock = DiagnosticsConfiguration.UseGlobalLock; s_settingsInitialized = true; + s_settingsInitializing = false; } } } diff --git a/src/libraries/System.Diagnostics.TraceSource/src/System/Diagnostics/TraceListener.cs b/src/libraries/System.Diagnostics.TraceSource/src/System/Diagnostics/TraceListener.cs index 87944a1f1c9cf5..e7208255dcb478 100644 --- a/src/libraries/System.Diagnostics.TraceSource/src/System/Diagnostics/TraceListener.cs +++ b/src/libraries/System.Diagnostics.TraceSource/src/System/Diagnostics/TraceListener.cs @@ -51,7 +51,6 @@ protected TraceListener(string? name) public virtual string Name { get { return _listenerName ?? ""; } - set { _listenerName = value; } } diff --git a/src/libraries/System.Diagnostics.TraceSource/src/System/Diagnostics/TraceListeners.cs b/src/libraries/System.Diagnostics.TraceSource/src/System/Diagnostics/TraceListeners.cs index 514d7df1317bb9..c8733ab9a4830e 100644 --- a/src/libraries/System.Diagnostics.TraceSource/src/System/Diagnostics/TraceListeners.cs +++ b/src/libraries/System.Diagnostics.TraceSource/src/System/Diagnostics/TraceListeners.cs @@ -89,7 +89,7 @@ public void AddRange(TraceListener[] value) for (int i = 0; ((i) < (value.Length)); i = ((i) + (1))) { - this.Add(value[i]); + Add(value[i]); } } @@ -103,7 +103,7 @@ public void AddRange(TraceListenerCollection value) int currentCount = value.Count; for (int i = 0; i < currentCount; i = ((i) + (1))) { - this.Add(value[i]); + Add(value[i]); } } diff --git a/src/libraries/System.Diagnostics.TraceSource/src/System/Diagnostics/TraceSource.cs b/src/libraries/System.Diagnostics.TraceSource/src/System/Diagnostics/TraceSource.cs index d8d2a397a6da51..f9a8d23f3ec363 100644 --- a/src/libraries/System.Diagnostics.TraceSource/src/System/Diagnostics/TraceSource.cs +++ b/src/libraries/System.Diagnostics.TraceSource/src/System/Diagnostics/TraceSource.cs @@ -20,12 +20,10 @@ public class TraceSource private readonly SourceLevels _switchLevel; private readonly string _sourceName; internal volatile bool _initCalled; // Whether we've called Initialize already. + internal volatile bool _configInitializing; private StringDictionary? _attributes; - public TraceSource(string name) - : this(name, SourceLevels.Off) - { - } + public TraceSource(string name) : this(name, SourceLevels.Off) { } public TraceSource(string name, SourceLevels defaultLevel) { @@ -76,18 +74,37 @@ private void Initialize() if (_initCalled) return; - NoConfigInit(); + if (_configInitializing) + return; + + _configInitializing = true; + NoConfigInit_BeforeEvent(); + + InitializingTraceSourceEventArgs e = new InitializingTraceSourceEventArgs(this); + OnInitializing(e); + + if (!e.WasInitialized) + { + NoConfigInit_AfterEvent(); + } + + _configInitializing = false; _initCalled = true; } } - } - private void NoConfigInit() - { - _internalSwitch = new SourceSwitch(_sourceName, _switchLevel.ToString()); - _listeners = new TraceListenerCollection(); - _listeners.Add(new DefaultTraceListener()); + void NoConfigInit_BeforeEvent() + { + _listeners = new TraceListenerCollection(); + _internalSwitch = new SourceSwitch(_sourceName, _switchLevel.ToString()); + } + + void NoConfigInit_AfterEvent() + { + Debug.Assert(_listeners != null); + _listeners.Add(new DefaultTraceListener()); + } } public void Close() @@ -165,6 +182,8 @@ internal void Refresh() Initialize(); return; } + + OnInitializing(new InitializingTraceSourceEventArgs(this)); } [Conditional("TRACE")] @@ -467,27 +486,40 @@ public StringDictionary Attributes { get { - // Ensure that config is loaded Initialize(); - return _attributes ??= new StringDictionary(); } } - public string Name + /// + /// The default level assigned in the constructor. + /// + public SourceLevels DefaultLevel => _switchLevel; + + /// + /// Occurs when a needs to be initialized. + /// + public static event EventHandler? Initializing; + + internal void OnInitializing(InitializingTraceSourceEventArgs e) { - get + Initializing?.Invoke(this, e); + + TraceUtils.VerifyAttributes(Attributes, GetSupportedAttributes(), this); + + foreach (TraceListener listener in Listeners) { - return _sourceName; + TraceUtils.VerifyAttributes(listener.Attributes, listener.GetSupportedAttributes(), this); } } + public string Name => _sourceName; + public TraceListenerCollection Listeners { get { Initialize(); - return _listeners!; } } @@ -498,7 +530,6 @@ public SourceSwitch Switch get { Initialize(); - return _internalSwitch!; } set diff --git a/src/libraries/System.Diagnostics.TraceSource/src/System/Diagnostics/TraceSwitch.cs b/src/libraries/System.Diagnostics.TraceSource/src/System/Diagnostics/TraceSwitch.cs index a9f6bc742c151f..45400a06f821d4 100644 --- a/src/libraries/System.Diagnostics.TraceSource/src/System/Diagnostics/TraceSwitch.cs +++ b/src/libraries/System.Diagnostics.TraceSource/src/System/Diagnostics/TraceSwitch.cs @@ -17,8 +17,7 @@ public class TraceSwitch : Switch /// public TraceSwitch(string displayName, string? description) : base(displayName, description) - { - } + { } public TraceSwitch(string displayName, string? description, string defaultSwitchValue) : base(displayName, description, defaultSwitchValue) @@ -49,52 +48,28 @@ public TraceLevel Level /// , , , or /// . /// - public bool TraceError - { - get - { - return (Level >= TraceLevel.Error); - } - } + public bool TraceError => Level >= TraceLevel.Error; /// /// Gets a value /// indicating whether the is set to /// , , or . /// - public bool TraceWarning - { - get - { - return (Level >= TraceLevel.Warning); - } - } + public bool TraceWarning => Level >= TraceLevel.Warning; /// /// Gets a value /// indicating whether the is set to /// or . /// - public bool TraceInfo - { - get - { - return (Level >= TraceLevel.Info); - } - } + public bool TraceInfo => Level >= TraceLevel.Info; /// /// Gets a value /// indicating whether the is set to /// . /// - public bool TraceVerbose - { - get - { - return (Level == TraceLevel.Verbose); - } - } + public bool TraceVerbose => Level == TraceLevel.Verbose; /// /// diff --git a/src/libraries/System.Diagnostics.TraceSource/src/System/Diagnostics/TraceUtils.cs b/src/libraries/System.Diagnostics.TraceSource/src/System/Diagnostics/TraceUtils.cs new file mode 100644 index 00000000000000..62fde9e9cfbf7d --- /dev/null +++ b/src/libraries/System.Diagnostics.TraceSource/src/System/Diagnostics/TraceUtils.cs @@ -0,0 +1,42 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. + +using System.Configuration; +using System.IO; +using System.Reflection; +using System.Globalization; +using System.Collections; +using System.Collections.Specialized; +using System.Runtime.Versioning; + +namespace System.Diagnostics +{ + internal static class TraceUtils + { + internal static void VerifyAttributes(StringDictionary? attributes, string[]? supportedAttributes, object parent) + { + if (attributes == null) + { + throw new ArgumentNullException(nameof(attributes)); + } + + foreach (string key in attributes.Keys) + { + bool found = false; + if (supportedAttributes != null) + { + for (int i = 0; i < supportedAttributes.Length; i++) + { + if (supportedAttributes[i] == key) + found = true; + } + } + + if (!found) + { + throw new ArgumentException(SR.Format(SR.AttributeNotSupported, key, parent.GetType().FullName)); + } + } + } + } +} diff --git a/src/libraries/System.Diagnostics.TraceSource/tests/AssemblyInfo.cs b/src/libraries/System.Diagnostics.TraceSource/tests/System.Diagnostics.TraceSource.Config.Tests/AssemblyInfo.cs similarity index 100% rename from src/libraries/System.Diagnostics.TraceSource/tests/AssemblyInfo.cs rename to src/libraries/System.Diagnostics.TraceSource/tests/System.Diagnostics.TraceSource.Config.Tests/AssemblyInfo.cs diff --git a/src/libraries/System.Diagnostics.TraceSource/tests/System.Diagnostics.TraceSource.Config.Tests/StringTraceListener.cs b/src/libraries/System.Diagnostics.TraceSource/tests/System.Diagnostics.TraceSource.Config.Tests/StringTraceListener.cs new file mode 100644 index 00000000000000..efd8d8283bb0cb --- /dev/null +++ b/src/libraries/System.Diagnostics.TraceSource/tests/System.Diagnostics.TraceSource.Config.Tests/StringTraceListener.cs @@ -0,0 +1,46 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. + +using System.IO; + +namespace System.Diagnostics.TraceSourceConfigTests +{ + public class StringTraceListener : DefaultTraceListener + { + private StringWriter _writer; + public bool ShouldOverrideWriteLine { get; set; } = true; + + public StringTraceListener() + { + _writer = new StringWriter(); + AssertUiEnabled = false; + } + + public void Clear() + { + _writer = new StringWriter(); + } + + public string Output + { + get { return _writer.ToString(); } + } + + public override void Write(string message) + { + _writer.Write(message); + } + + public override void WriteLine(string message) + { + if (ShouldOverrideWriteLine) + { + _writer.WriteLine(message); + } + else + { + base.WriteLine(message); + } + } + } +} diff --git a/src/libraries/System.Diagnostics.TraceSource/tests/System.Diagnostics.TraceSource.Config.Tests/System.Diagnostics.TraceSource.Config.Tests.csproj b/src/libraries/System.Diagnostics.TraceSource/tests/System.Diagnostics.TraceSource.Config.Tests/System.Diagnostics.TraceSource.Config.Tests.csproj new file mode 100644 index 00000000000000..cd36a59ecae62a --- /dev/null +++ b/src/libraries/System.Diagnostics.TraceSource/tests/System.Diagnostics.TraceSource.Config.Tests/System.Diagnostics.TraceSource.Config.Tests.csproj @@ -0,0 +1,29 @@ + + + true + $(NetCoreAppCurrent) + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/src/libraries/System.Diagnostics.TraceSource/tests/System.Diagnostics.TraceSource.Config.Tests/TraceSourceWithConfigurationTests.cs b/src/libraries/System.Diagnostics.TraceSource/tests/System.Diagnostics.TraceSource.Config.Tests/TraceSourceWithConfigurationTests.cs new file mode 100644 index 00000000000000..0f0124469a9a13 --- /dev/null +++ b/src/libraries/System.Diagnostics.TraceSource/tests/System.Diagnostics.TraceSource.Config.Tests/TraceSourceWithConfigurationTests.cs @@ -0,0 +1,314 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. + +using System.Configuration; +using System.IO; +using System.Reflection; +using Xunit; + +namespace System.Diagnostics.TraceSourceConfigTests +{ + // Note that parallelization is disabled due to file access as each test replaces the single config file on disk. + public class ConfigurationTests + { + private static volatile string? _configFile = null; + + private static void CreateAndLoadConfigFile(string filename) + { + Configuration.Configuration config = ConfigurationManager.OpenExeConfiguration(ConfigurationUserLevel.None); + string dir = Path.GetDirectoryName(config.FilePath); + string from = Path.Combine(dir, filename); + + if (_configFile == null) + { + _configFile = Path.GetFileName(config.FilePath); + File.Copy(from, _configFile, overwrite: true); + TraceConfiguration.Register(); + // Do not call Trace.Refresh() here since the first access should be tested without it. + } + else + { + File.Copy(from, _configFile, overwrite: true); + Trace.Refresh(); + } + } + + [Fact] + [SkipOnPlatform(TestPlatforms.Browser, "Not supported on Browser")] + public void RuntimeFilterChange() + { + CreateAndLoadConfigFile("testhost_ConfigWithRuntime.config"); + + TraceSource mySource = new TraceSource("TraceSourceApp"); + StringTraceListener origListener = (StringTraceListener)mySource.Listeners["origListener"]; + StringTraceListener secondListener = (StringTraceListener)mySource.Listeners["secondListener"]; + + // Issue an error and a warning message. Only the error message should be logged. + mySource.TraceEvent(TraceEventType.Error, 1, "Error message."); + mySource.TraceEvent(TraceEventType.Warning, 2, "Warning message."); + + Assert.Equal($"TraceSourceApp Error: 1 : Error message.{Environment.NewLine}", origListener.Output); + Assert.Equal($"TraceSourceApp Error: 1 : Error message.{Environment.NewLine}", secondListener.Output); + + // Save the original settings from the configuration file. + EventTypeFilter configFilter = (EventTypeFilter)mySource.Listeners["origListener"].Filter; + Assert.NotNull(configFilter); + + // Create a new filter that logs warnings. + origListener.Filter = new EventTypeFilter(SourceLevels.Warning); + + // Allow the trace source to send messages to listeners for all event types. + // This overrides settings in the configuration file. + // If the switch level is not changed, the event filter changes have no effect. + mySource.Switch.Level = SourceLevels.All; + + // Issue a critical and warning message. + origListener.Clear(); + secondListener.Clear(); + mySource.TraceEvent(TraceEventType.Critical, 3, "Critical message."); + mySource.TraceEvent(TraceEventType.Warning, 4, "Warning message."); + + // Both should be logged for origListener. + Assert.Equal( + $"TraceSourceApp Critical: 3 : Critical message.{Environment.NewLine}" + + $"TraceSourceApp Warning: 4 : Warning message.{Environment.NewLine}", origListener.Output); + + // secondListener is unchanged and doesn't log warnings. + Assert.Equal($"TraceSourceApp Critical: 3 : Critical message.{Environment.NewLine}", secondListener.Output); + + // Restore the original filter settings. + origListener.Clear(); + secondListener.Clear(); + origListener.Filter = configFilter; + + // Issue an error and information message. Only the error message should be logged. + mySource.TraceEvent(TraceEventType.Error, 5, "Error message."); + mySource.TraceInformation("Informational message."); + + Assert.Equal($"TraceSourceApp Error: 5 : Error message.{Environment.NewLine}", origListener.Output); + Assert.Equal($"TraceSourceApp Error: 5 : Error message.{Environment.NewLine}", secondListener.Output); + + origListener.Clear(); + secondListener.Clear(); + mySource.Close(); + } + + [Fact] + [SkipOnPlatform(TestPlatforms.Browser, "Not supported on Browser")] + public void Refresh_RemoveSwitch() + { + // Use a SourceSwitch that logs Error. + CreateAndLoadConfigFile("testhost_RemoveSwitch_before.config"); + + SourceSwitch sswitch = new SourceSwitch("Refresh_RemoveSwitch_sourceSwitchToBeRemoved", "Warning"); + Assert.Equal("Warning", sswitch.DefaultValue); + Assert.Equal("Error", sswitch.Value); + + TraceSource mySource = new TraceSource("Refresh_RemoveSwitch"); + StringTraceListener listener = (StringTraceListener)mySource.Listeners["listener"]; + + Log(); + Assert.Equal( + $"Refresh_RemoveSwitch Error: 1 : Error message.{Environment.NewLine}" + + $"Refresh_RemoveSwitch Critical: 3 : Critical message.{Environment.NewLine}", listener.Output); + + // Change the switch to log All. + listener.Clear(); + CreateAndLoadConfigFile("testhost_RemoveSwitch_after.config"); + Trace.Refresh(); + + Assert.Equal("Warning", sswitch.DefaultValue); + Assert.Equal("Warning", sswitch.Value); // Changed to Warning since the switch was removed from the config. + + Log(); + Assert.Equal(string.Empty, listener.Output); // The default replacement switch is off. + + listener.Clear(); + void Log() + { + mySource.TraceEvent(TraceEventType.Error, 1, "Error message."); + mySource.TraceEvent(TraceEventType.Warning, 2, "Warning message."); + mySource.TraceEvent(TraceEventType.Critical, 3, "Critical message."); + mySource.TraceInformation("Informational message."); + } + } + + [Fact] + [SkipOnPlatform(TestPlatforms.Browser, "Not supported on Browser")] + public void Refresh_ChangeSwitch() + { + // Use a SourceSwitch that logs Error. + CreateAndLoadConfigFile("testhost_ChangeSwitch_before.config"); + + TraceSource mySource = new TraceSource("Refresh_ChangeSwitch"); + StringTraceListener listener = (StringTraceListener)mySource.Listeners["listener"]; + + mySource.TraceInformation("Informational message."); + Assert.Equal(string.Empty, listener.Output); // Switch is off. + + // Change the switch to log. + listener.Clear(); + CreateAndLoadConfigFile("testhost_ChangeSwitch_after.config"); + Trace.Refresh(); + + mySource.TraceInformation("Informational message."); + Assert.Equal($"Refresh_ChangeSwitch Information: 0 : Informational message.{Environment.NewLine}", listener.Output); + + listener.Close(); + mySource.Close(); + } + + [Fact] + [SkipOnPlatform(TestPlatforms.Browser, "Not supported on Browser")] + public void Refresh_RemoveSource() + { + // Use a SourceSwitch that logs Error. + CreateAndLoadConfigFile("testhost_RemoveSource_before.config"); + + TraceSource mySourceToBeRemoved = new TraceSource("Refresh_RemoveSource", SourceLevels.Warning); + Assert.Equal(SourceLevels.Warning, mySourceToBeRemoved.DefaultLevel); + Assert.Equal(SourceLevels.Error, mySourceToBeRemoved.Switch.Level); // Config has Error. + Assert.Equal("Error", mySourceToBeRemoved.Switch.Value); + + StringTraceListener listenerToBeRemoved = (StringTraceListener)mySourceToBeRemoved.Listeners["listener"]; + listenerToBeRemoved.Clear(); + mySourceToBeRemoved.TraceEvent(TraceEventType.Error, 1, "Error message."); + Assert.Equal($"Refresh_RemoveSource Error: 1 : Error message.{Environment.NewLine}", listenerToBeRemoved.Output); + + // Change the switch to log All. + listenerToBeRemoved.Clear(); + CreateAndLoadConfigFile("testhost_RemoveSource_after.config"); + Trace.Refresh(); + + Assert.Equal(SourceLevels.Warning, mySourceToBeRemoved.DefaultLevel); + Assert.Equal(SourceLevels.Warning, mySourceToBeRemoved.Switch.Level); // Changed to Warning since the switch was removed from the config. + Assert.Equal("Error", mySourceToBeRemoved.Switch.Value); + + mySourceToBeRemoved.TraceEvent(TraceEventType.Error, 1, "Error message."); + Assert.Equal(string.Empty, listenerToBeRemoved.Output); + + listenerToBeRemoved.Clear(); + mySourceToBeRemoved.Close(); + } + + [Fact] + [SkipOnPlatform(TestPlatforms.Browser, "Not supported on Browser")] + public void ConfigWithEvents_RuntimeListener() + { + CreateAndLoadConfigFile("testhost_ConfigWithRuntime.config"); + + TraceSource.Initializing += SubscribeToTraceSource_Initializing; + Switch.Initializing += SubscribeToSwitch_Initializing; + + TraceSource mySource = new("TraceSource_NoListeners"); + Assert.Equal(1, mySource.Listeners.Count); // The default listener was removed via the config + StringTraceListener dynamicallyAddedListener = (StringTraceListener)mySource.Listeners[0]; + + // Only the Critical should be logged. + // The config setting was to only log Error, but changed to Critical in the event handler. + Log(); + Assert.Equal($"TraceSource_NoListeners Critical: 3 : Critical message.{Environment.NewLine}", dynamicallyAddedListener.Output); + + // Log all. + dynamicallyAddedListener.Clear(); + mySource.Switch.Level = SourceLevels.All; + Log(); + Assert.Equal( + $"TraceSource_NoListeners Error: 1 : Error message.{Environment.NewLine}" + + $"TraceSource_NoListeners Warning: 2 : Warning message.{Environment.NewLine}" + + $"TraceSource_NoListeners Critical: 3 : Critical message.{Environment.NewLine}" + + $"TraceSource_NoListeners Information: 0 : Informational message.{Environment.NewLine}", dynamicallyAddedListener.Output); + + dynamicallyAddedListener.Clear(); + mySource.Close(); + TraceSource.Initializing -= SubscribeToTraceSource_Initializing; + Switch.Initializing -= SubscribeToSwitch_Initializing; + + void Log() + { + mySource.TraceEvent(TraceEventType.Error, 1, "Error message."); + mySource.TraceEvent(TraceEventType.Warning, 2, "Warning message."); + mySource.TraceEvent(TraceEventType.Critical, 3, "Critical message."); + mySource.TraceInformation("Informational message."); + } + } + + private void SubscribeToTraceSource_Initializing(object? sender, InitializingTraceSourceEventArgs e) + { + TraceSource traceSource = e.TraceSource; + if (traceSource.Name == "TraceSource_NoListeners") + { + Assert.Equal("generalSourceSwitch_Error", traceSource.Switch.DisplayName); + traceSource.Listeners.Add(new StringTraceListener()); + } + } + + private void SubscribeToSwitch_Initializing(object? sender, InitializingSwitchEventArgs e) + { + Switch sw = e.Switch; + if (sw.DisplayName == "generalSourceSwitch_Error") + { + Assert.IsType(sw); + SourceSwitch sourceSwitch = (SourceSwitch)sw; + Assert.Equal(TraceLevel.Error.ToString(), sourceSwitch.Level.ToString()); + + // Change to critical + sourceSwitch.Level = SourceLevels.Critical; + } + } + + [Fact] + [SkipOnPlatform(TestPlatforms.Browser, "Not supported on Browser")] + public void AllTypes() + { + CreateAndLoadConfigFile("testhost_AllTypes.config"); + + TraceSource mySource; + + mySource = new("ConsoleTraceListener"); + Assert.Equal("L1", mySource.Listeners[1].Name); + + mySource = new("DefaultTraceListener"); + Assert.Equal("L1", mySource.Listeners[1].Name); + + mySource = new("DelimitedListTraceListener"); + Assert.Equal("L1", mySource.Listeners[1].Name); + + // The referenced S.R.ConfigurationManager.dll is NetStandard, which does not support EventLogTraceListener. + mySource = new("EventLogTraceListener"); + Exception e = Assert.Throws(() => mySource.Listeners[1].Name); + Assert.IsType(e.InnerException); + + mySource = new("TextWriterTraceListener"); + Assert.Equal("L1", mySource.Listeners[1].Name); + + mySource = new("XmlWriterTraceListener"); + Assert.Equal("L1", mySource.Listeners[1].Name); + + Switch switch_booleanSwitch = new BooleanSwitch("booleanSwitch", null); + Assert.Equal("True", switch_booleanSwitch.Value); + + Switch switch_sourceSwitch = new SourceSwitch("sourceSwitch"); + Assert.Equal("Critical", switch_sourceSwitch.Value); + + Switch switch_traceSwitch = new TraceSwitch("traceSwitch", null); + Assert.Equal("Info", switch_traceSwitch.Value); + + TraceSource filter_sourceFilter = new("filter_sourceFilter"); + Assert.IsType(filter_sourceFilter.Listeners[1].Filter); + + TraceSource filter_eventTypeFilter = new("filter_eventTypeFilter"); + Assert.IsType(filter_eventTypeFilter.Listeners[1].Filter); + } + + [Fact] + [SkipOnPlatform(TestPlatforms.Browser, "Not supported on Browser")] + public void Switch_MissingValue_Throws() + { + Exception e = Assert.Throws(() => + CreateAndLoadConfigFile("testhost_Switch_MissingValue_Throws.config")); + + Assert.Contains("'value'", e.ToString()); + } + } +} diff --git a/src/libraries/System.Diagnostics.TraceSource/tests/System.Diagnostics.TraceSource.Config.Tests/testhost_AllTypes.config b/src/libraries/System.Diagnostics.TraceSource/tests/System.Diagnostics.TraceSource.Config.Tests/testhost_AllTypes.config new file mode 100644 index 00000000000000..fd91b2af8eafed --- /dev/null +++ b/src/libraries/System.Diagnostics.TraceSource/tests/System.Diagnostics.TraceSource.Config.Tests/testhost_AllTypes.config @@ -0,0 +1,62 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/src/libraries/System.Diagnostics.TraceSource/tests/System.Diagnostics.TraceSource.Config.Tests/testhost_ChangeSwitch_after.config b/src/libraries/System.Diagnostics.TraceSource/tests/System.Diagnostics.TraceSource.Config.Tests/testhost_ChangeSwitch_after.config new file mode 100644 index 00000000000000..e7bd8d69770ecc --- /dev/null +++ b/src/libraries/System.Diagnostics.TraceSource/tests/System.Diagnostics.TraceSource.Config.Tests/testhost_ChangeSwitch_after.config @@ -0,0 +1,16 @@ + + + + + + + + + + + + + + diff --git a/src/libraries/System.Diagnostics.TraceSource/tests/System.Diagnostics.TraceSource.Config.Tests/testhost_ChangeSwitch_before.config b/src/libraries/System.Diagnostics.TraceSource/tests/System.Diagnostics.TraceSource.Config.Tests/testhost_ChangeSwitch_before.config new file mode 100644 index 00000000000000..86f2f66d8dacce --- /dev/null +++ b/src/libraries/System.Diagnostics.TraceSource/tests/System.Diagnostics.TraceSource.Config.Tests/testhost_ChangeSwitch_before.config @@ -0,0 +1,16 @@ + + + + + + + + + + + + + + diff --git a/src/libraries/System.Diagnostics.TraceSource/tests/System.Diagnostics.TraceSource.Config.Tests/testhost_ConfigWithRuntime.config b/src/libraries/System.Diagnostics.TraceSource/tests/System.Diagnostics.TraceSource.Config.Tests/testhost_ConfigWithRuntime.config new file mode 100644 index 00000000000000..32b7fe3fd2920a --- /dev/null +++ b/src/libraries/System.Diagnostics.TraceSource/tests/System.Diagnostics.TraceSource.Config.Tests/testhost_ConfigWithRuntime.config @@ -0,0 +1,32 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/src/libraries/System.Diagnostics.TraceSource/tests/System.Diagnostics.TraceSource.Config.Tests/testhost_RemoveSource_after.config b/src/libraries/System.Diagnostics.TraceSource/tests/System.Diagnostics.TraceSource.Config.Tests/testhost_RemoveSource_after.config new file mode 100644 index 00000000000000..c07deb67560703 --- /dev/null +++ b/src/libraries/System.Diagnostics.TraceSource/tests/System.Diagnostics.TraceSource.Config.Tests/testhost_RemoveSource_after.config @@ -0,0 +1,9 @@ + + + + + + + + + diff --git a/src/libraries/System.Diagnostics.TraceSource/tests/System.Diagnostics.TraceSource.Config.Tests/testhost_RemoveSource_before.config b/src/libraries/System.Diagnostics.TraceSource/tests/System.Diagnostics.TraceSource.Config.Tests/testhost_RemoveSource_before.config new file mode 100644 index 00000000000000..4b549fe9a28ba0 --- /dev/null +++ b/src/libraries/System.Diagnostics.TraceSource/tests/System.Diagnostics.TraceSource.Config.Tests/testhost_RemoveSource_before.config @@ -0,0 +1,16 @@ + + + + + + + + + + + + + + diff --git a/src/libraries/System.Diagnostics.TraceSource/tests/System.Diagnostics.TraceSource.Config.Tests/testhost_RemoveSwitch_after.config b/src/libraries/System.Diagnostics.TraceSource/tests/System.Diagnostics.TraceSource.Config.Tests/testhost_RemoveSwitch_after.config new file mode 100644 index 00000000000000..8c388eca0864b1 --- /dev/null +++ b/src/libraries/System.Diagnostics.TraceSource/tests/System.Diagnostics.TraceSource.Config.Tests/testhost_RemoveSwitch_after.config @@ -0,0 +1,11 @@ + + + + + + + + + + + diff --git a/src/libraries/System.Diagnostics.TraceSource/tests/System.Diagnostics.TraceSource.Config.Tests/testhost_RemoveSwitch_before.config b/src/libraries/System.Diagnostics.TraceSource/tests/System.Diagnostics.TraceSource.Config.Tests/testhost_RemoveSwitch_before.config new file mode 100644 index 00000000000000..d6bb34450708aa --- /dev/null +++ b/src/libraries/System.Diagnostics.TraceSource/tests/System.Diagnostics.TraceSource.Config.Tests/testhost_RemoveSwitch_before.config @@ -0,0 +1,16 @@ + + + + + + + + + + + + + + diff --git a/src/libraries/System.Diagnostics.TraceSource/tests/System.Diagnostics.TraceSource.Config.Tests/testhost_Switch_MissingValue_Throws.config b/src/libraries/System.Diagnostics.TraceSource/tests/System.Diagnostics.TraceSource.Config.Tests/testhost_Switch_MissingValue_Throws.config new file mode 100644 index 00000000000000..046ab064dfa0f4 --- /dev/null +++ b/src/libraries/System.Diagnostics.TraceSource/tests/System.Diagnostics.TraceSource.Config.Tests/testhost_Switch_MissingValue_Throws.config @@ -0,0 +1,7 @@ + + + + + + + diff --git a/src/libraries/System.Diagnostics.TraceSource/tests/System.Diagnostics.TraceSource.Config.Tests/testhost_refresh.dll.config b/src/libraries/System.Diagnostics.TraceSource/tests/System.Diagnostics.TraceSource.Config.Tests/testhost_refresh.dll.config new file mode 100644 index 00000000000000..366da09c5fea6f --- /dev/null +++ b/src/libraries/System.Diagnostics.TraceSource/tests/System.Diagnostics.TraceSource.Config.Tests/testhost_refresh.dll.config @@ -0,0 +1,20 @@ + + + + + + + + + + + + + + + + + + diff --git a/src/libraries/System.Diagnostics.TraceSource/tests/System.Diagnostics.TraceSource.Tests/AssemblyInfo.cs b/src/libraries/System.Diagnostics.TraceSource/tests/System.Diagnostics.TraceSource.Tests/AssemblyInfo.cs new file mode 100644 index 00000000000000..a1de79002e07d5 --- /dev/null +++ b/src/libraries/System.Diagnostics.TraceSource/tests/System.Diagnostics.TraceSource.Tests/AssemblyInfo.cs @@ -0,0 +1,6 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. + +using Xunit; + +[assembly: CollectionBehavior(CollectionBehavior.CollectionPerAssembly, DisableTestParallelization = true, MaxParallelThreads = 1)] diff --git a/src/libraries/System.Diagnostics.TraceSource/tests/BooleanSwitchClassTests.cs b/src/libraries/System.Diagnostics.TraceSource/tests/System.Diagnostics.TraceSource.Tests/BooleanSwitchClassTests.cs similarity index 100% rename from src/libraries/System.Diagnostics.TraceSource/tests/BooleanSwitchClassTests.cs rename to src/libraries/System.Diagnostics.TraceSource/tests/System.Diagnostics.TraceSource.Tests/BooleanSwitchClassTests.cs diff --git a/src/libraries/System.Diagnostics.TraceSource/tests/CorrelationManagerTests.cs b/src/libraries/System.Diagnostics.TraceSource/tests/System.Diagnostics.TraceSource.Tests/CorrelationManagerTests.cs similarity index 100% rename from src/libraries/System.Diagnostics.TraceSource/tests/CorrelationManagerTests.cs rename to src/libraries/System.Diagnostics.TraceSource/tests/System.Diagnostics.TraceSource.Tests/CorrelationManagerTests.cs diff --git a/src/libraries/System.Diagnostics.TraceSource/tests/DefaultTraceListenerClassTests.cs b/src/libraries/System.Diagnostics.TraceSource/tests/System.Diagnostics.TraceSource.Tests/DefaultTraceListenerClassTests.cs similarity index 100% rename from src/libraries/System.Diagnostics.TraceSource/tests/DefaultTraceListenerClassTests.cs rename to src/libraries/System.Diagnostics.TraceSource/tests/System.Diagnostics.TraceSource.Tests/DefaultTraceListenerClassTests.cs diff --git a/src/libraries/System.Diagnostics.TraceSource/tests/EventTypeFilterClassTests.cs b/src/libraries/System.Diagnostics.TraceSource/tests/System.Diagnostics.TraceSource.Tests/EventTypeFilterClassTests.cs similarity index 100% rename from src/libraries/System.Diagnostics.TraceSource/tests/EventTypeFilterClassTests.cs rename to src/libraries/System.Diagnostics.TraceSource/tests/System.Diagnostics.TraceSource.Tests/EventTypeFilterClassTests.cs diff --git a/src/libraries/System.Diagnostics.TraceSource/tests/SourceFilterClassTests.cs b/src/libraries/System.Diagnostics.TraceSource/tests/System.Diagnostics.TraceSource.Tests/SourceFilterClassTests.cs similarity index 100% rename from src/libraries/System.Diagnostics.TraceSource/tests/SourceFilterClassTests.cs rename to src/libraries/System.Diagnostics.TraceSource/tests/System.Diagnostics.TraceSource.Tests/SourceFilterClassTests.cs diff --git a/src/libraries/System.Diagnostics.TraceSource/tests/SwitchClassTests.cs b/src/libraries/System.Diagnostics.TraceSource/tests/System.Diagnostics.TraceSource.Tests/SwitchClassTests.cs similarity index 100% rename from src/libraries/System.Diagnostics.TraceSource/tests/SwitchClassTests.cs rename to src/libraries/System.Diagnostics.TraceSource/tests/System.Diagnostics.TraceSource.Tests/SwitchClassTests.cs diff --git a/src/libraries/System.Diagnostics.TraceSource/tests/System.Diagnostics.TraceSource.Tests.csproj b/src/libraries/System.Diagnostics.TraceSource/tests/System.Diagnostics.TraceSource.Tests/System.Diagnostics.TraceSource.Tests.csproj similarity index 86% rename from src/libraries/System.Diagnostics.TraceSource/tests/System.Diagnostics.TraceSource.Tests.csproj rename to src/libraries/System.Diagnostics.TraceSource/tests/System.Diagnostics.TraceSource.Tests/System.Diagnostics.TraceSource.Tests.csproj index 7c0de93514b041..cf88f62d327e7e 100644 --- a/src/libraries/System.Diagnostics.TraceSource/tests/System.Diagnostics.TraceSource.Tests.csproj +++ b/src/libraries/System.Diagnostics.TraceSource/tests/System.Diagnostics.TraceSource.Tests/System.Diagnostics.TraceSource.Tests.csproj @@ -24,4 +24,7 @@ + + + \ No newline at end of file diff --git a/src/libraries/System.Diagnostics.TraceSource/tests/TestTextTraceListener.cs b/src/libraries/System.Diagnostics.TraceSource/tests/System.Diagnostics.TraceSource.Tests/TestTextTraceListener.cs similarity index 100% rename from src/libraries/System.Diagnostics.TraceSource/tests/TestTextTraceListener.cs rename to src/libraries/System.Diagnostics.TraceSource/tests/System.Diagnostics.TraceSource.Tests/TestTextTraceListener.cs diff --git a/src/libraries/System.Diagnostics.TraceSource/tests/TestTraceFilter.cs b/src/libraries/System.Diagnostics.TraceSource/tests/System.Diagnostics.TraceSource.Tests/TestTraceFilter.cs similarity index 100% rename from src/libraries/System.Diagnostics.TraceSource/tests/TestTraceFilter.cs rename to src/libraries/System.Diagnostics.TraceSource/tests/System.Diagnostics.TraceSource.Tests/TestTraceFilter.cs diff --git a/src/libraries/System.Diagnostics.TraceSource/tests/TestTraceListener.cs b/src/libraries/System.Diagnostics.TraceSource/tests/System.Diagnostics.TraceSource.Tests/TestTraceListener.cs similarity index 100% rename from src/libraries/System.Diagnostics.TraceSource/tests/TestTraceListener.cs rename to src/libraries/System.Diagnostics.TraceSource/tests/System.Diagnostics.TraceSource.Tests/TestTraceListener.cs diff --git a/src/libraries/System.Diagnostics.TraceSource/tests/TraceClassTests.cs b/src/libraries/System.Diagnostics.TraceSource/tests/System.Diagnostics.TraceSource.Tests/TraceClassTests.cs similarity index 100% rename from src/libraries/System.Diagnostics.TraceSource/tests/TraceClassTests.cs rename to src/libraries/System.Diagnostics.TraceSource/tests/System.Diagnostics.TraceSource.Tests/TraceClassTests.cs diff --git a/src/libraries/System.Diagnostics.TraceSource/tests/TraceEventCacheClassTests.cs b/src/libraries/System.Diagnostics.TraceSource/tests/System.Diagnostics.TraceSource.Tests/TraceEventCacheClassTests.cs similarity index 100% rename from src/libraries/System.Diagnostics.TraceSource/tests/TraceEventCacheClassTests.cs rename to src/libraries/System.Diagnostics.TraceSource/tests/System.Diagnostics.TraceSource.Tests/TraceEventCacheClassTests.cs diff --git a/src/libraries/System.Diagnostics.TraceSource/tests/TraceFilterClassTests.cs b/src/libraries/System.Diagnostics.TraceSource/tests/System.Diagnostics.TraceSource.Tests/TraceFilterClassTests.cs similarity index 100% rename from src/libraries/System.Diagnostics.TraceSource/tests/TraceFilterClassTests.cs rename to src/libraries/System.Diagnostics.TraceSource/tests/System.Diagnostics.TraceSource.Tests/TraceFilterClassTests.cs diff --git a/src/libraries/System.Diagnostics.TraceSource/tests/TraceInternalClassTests.cs b/src/libraries/System.Diagnostics.TraceSource/tests/System.Diagnostics.TraceSource.Tests/TraceInternalClassTests.cs similarity index 100% rename from src/libraries/System.Diagnostics.TraceSource/tests/TraceInternalClassTests.cs rename to src/libraries/System.Diagnostics.TraceSource/tests/System.Diagnostics.TraceSource.Tests/TraceInternalClassTests.cs diff --git a/src/libraries/System.Diagnostics.TraceSource/tests/TraceListenerClassTests.cs b/src/libraries/System.Diagnostics.TraceSource/tests/System.Diagnostics.TraceSource.Tests/TraceListenerClassTests.cs similarity index 100% rename from src/libraries/System.Diagnostics.TraceSource/tests/TraceListenerClassTests.cs rename to src/libraries/System.Diagnostics.TraceSource/tests/System.Diagnostics.TraceSource.Tests/TraceListenerClassTests.cs diff --git a/src/libraries/System.Diagnostics.TraceSource/tests/TraceListenerCollectionClassTests.cs b/src/libraries/System.Diagnostics.TraceSource/tests/System.Diagnostics.TraceSource.Tests/TraceListenerCollectionClassTests.cs similarity index 100% rename from src/libraries/System.Diagnostics.TraceSource/tests/TraceListenerCollectionClassTests.cs rename to src/libraries/System.Diagnostics.TraceSource/tests/System.Diagnostics.TraceSource.Tests/TraceListenerCollectionClassTests.cs diff --git a/src/libraries/System.Diagnostics.TraceSource/tests/TraceSourceClassTests.cs b/src/libraries/System.Diagnostics.TraceSource/tests/System.Diagnostics.TraceSource.Tests/TraceSourceClassTests.cs similarity index 99% rename from src/libraries/System.Diagnostics.TraceSource/tests/TraceSourceClassTests.cs rename to src/libraries/System.Diagnostics.TraceSource/tests/System.Diagnostics.TraceSource.Tests/TraceSourceClassTests.cs index 12ca844c78ffba..c4f5fb390c49c6 100644 --- a/src/libraries/System.Diagnostics.TraceSource/tests/TraceSourceClassTests.cs +++ b/src/libraries/System.Diagnostics.TraceSource/tests/System.Diagnostics.TraceSource.Tests/TraceSourceClassTests.cs @@ -23,6 +23,7 @@ public void DefaultListenerTest() var trace = new TraceSource("TestTraceSource"); Assert.Equal(1, trace.Listeners.Count); Assert.IsType(trace.Listeners[0]); + Assert.Equal(SourceLevels.Off, trace.Switch.Level); } [Fact] diff --git a/src/libraries/System.Diagnostics.TraceSource/tests/TraceSwitchClassTests.cs b/src/libraries/System.Diagnostics.TraceSource/tests/System.Diagnostics.TraceSource.Tests/TraceSwitchClassTests.cs similarity index 100% rename from src/libraries/System.Diagnostics.TraceSource/tests/TraceSwitchClassTests.cs rename to src/libraries/System.Diagnostics.TraceSource/tests/System.Diagnostics.TraceSource.Tests/TraceSwitchClassTests.cs diff --git a/src/libraries/System.Diagnostics.TraceSource/tests/TraceTestHelper.cs b/src/libraries/System.Diagnostics.TraceSource/tests/System.Diagnostics.TraceSource.Tests/TraceTestHelper.cs similarity index 100% rename from src/libraries/System.Diagnostics.TraceSource/tests/TraceTestHelper.cs rename to src/libraries/System.Diagnostics.TraceSource/tests/System.Diagnostics.TraceSource.Tests/TraceTestHelper.cs