diff --git a/eng/Common.globalconfig b/eng/Common.globalconfig index 49de8011d44..c75fbec9493 100644 --- a/eng/Common.globalconfig +++ b/eng/Common.globalconfig @@ -253,7 +253,7 @@ dotnet_diagnostic.CA1805.severity = none dotnet_diagnostic.CA1806.severity = none # Initialize reference type static fields inline -dotnet_diagnostic.CA1810.severity = suggestion +dotnet_diagnostic.CA1810.severity = warning # Avoid uninstantiated internal classes dotnet_diagnostic.CA1812.severity = none diff --git a/src/Build/BackEnd/Components/RequestBuilder/IntrinsicTasks/ItemGroupLoggingHelper.cs b/src/Build/BackEnd/Components/RequestBuilder/IntrinsicTasks/ItemGroupLoggingHelper.cs index c1679d38212..4f67ed79862 100644 --- a/src/Build/BackEnd/Components/RequestBuilder/IntrinsicTasks/ItemGroupLoggingHelper.cs +++ b/src/Build/BackEnd/Components/RequestBuilder/IntrinsicTasks/ItemGroupLoggingHelper.cs @@ -44,7 +44,9 @@ internal static class ItemGroupLoggingHelper /// to materialize the Message as that's a declaration assembly. We inject the logic /// here. /// +#pragma warning disable CA1810 // Initialize reference type static fields inline static ItemGroupLoggingHelper() +#pragma warning restore CA1810 // Initialize reference type static fields inline { BuildEventArgs.ResourceStringFormatter = ResourceUtilities.FormatResourceStringIgnoreCodeAndKeyword; TaskParameterEventArgs.MessageGetter = GetTaskParameterText; diff --git a/src/Build/Evaluation/ProjectRootElementCache.cs b/src/Build/Evaluation/ProjectRootElementCache.cs index bb85186e17c..17ecae43227 100644 --- a/src/Build/Evaluation/ProjectRootElementCache.cs +++ b/src/Build/Evaluation/ProjectRootElementCache.cs @@ -71,14 +71,13 @@ internal class ProjectRootElementCache : ProjectRootElementCacheBase /// If this number is increased much higher, the datastructure may /// need to be changed from a linked list, since it's currently O(n). /// -#pragma warning disable CA1802 // Use literals where appropriate - private static readonly int s_maximumStrongCacheSize = 200; -#pragma warning restore CA1802 // Use literals where appropriate + private static readonly int s_maximumStrongCacheSize = + int.TryParse(Environment.GetEnvironmentVariable("MSBUILDPROJECTROOTELEMENTCACHESIZE"), out int cacheSize) ? cacheSize : 200; /// /// Whether the cache should log activity to the Debug.Out stream /// - private static bool s_debugLogCacheActivity; + private static bool s_debugLogCacheActivity = Environment.GetEnvironmentVariable("MSBUILDDEBUGXMLCACHE") == "1"; /// /// Whether the cache should check file content for cache entry invalidation. @@ -86,7 +85,7 @@ internal class ProjectRootElementCache : ProjectRootElementCacheBase /// /// Value shall be true only in case of testing. Outside QA tests it shall be false. /// - private static bool s_сheckFileContent; + private static bool s_сheckFileContent = !string.IsNullOrEmpty(Environment.GetEnvironmentVariable("MSBUILDCACHECHECKFILECONTENT")); #if DEBUG /// @@ -123,24 +122,6 @@ internal class ProjectRootElementCache : ProjectRootElementCacheBase /// private Object _locker = new Object(); - /// - /// Static constructor to choose cache size. - /// - static ProjectRootElementCache() - { - // Configurable in case a customer has related perf problems after shipping and so that - // we can measure different values for perf easily. - string userSpecifiedSize = Environment.GetEnvironmentVariable("MSBUILDPROJECTROOTELEMENTCACHESIZE"); - if (!String.IsNullOrEmpty(userSpecifiedSize)) - { - // Not catching as this is an undocumented setting - s_maximumStrongCacheSize = Convert.ToInt32(userSpecifiedSize, NumberFormatInfo.InvariantInfo); - } - - s_debugLogCacheActivity = Environment.GetEnvironmentVariable("MSBUILDDEBUGXMLCACHE") == "1"; - s_сheckFileContent = !String.IsNullOrEmpty(Environment.GetEnvironmentVariable("MSBUILDCACHECHECKFILECONTENT")); - } - /// /// Creates an empty cache. /// diff --git a/src/MSBuild/XMake.cs b/src/MSBuild/XMake.cs index 3ef0dabb711..7fec6c6b1f4 100644 --- a/src/MSBuild/XMake.cs +++ b/src/MSBuild/XMake.cs @@ -127,7 +127,9 @@ public enum ExitType /// /// Static constructor /// +#pragma warning disable CA1810 // Initialize reference type static fields inline static MSBuildApp() +#pragma warning restore CA1810 // Initialize reference type static fields inline { try { diff --git a/src/Shared/ExceptionHandling.cs b/src/Shared/ExceptionHandling.cs index f4ebaa3bc9c..fcd48395a31 100644 --- a/src/Shared/ExceptionHandling.cs +++ b/src/Shared/ExceptionHandling.cs @@ -36,12 +36,7 @@ namespace Microsoft.Build.Shared /// internal static class ExceptionHandling { - private static readonly string s_debugDumpPath; - - static ExceptionHandling() - { - s_debugDumpPath = GetDebugDumpPath(); - } + private static readonly string s_debugDumpPath = GetDebugDumpPath(); /// /// Gets the location of the directory used for diagnostic log files. diff --git a/src/Shared/FrameworkLocationHelper.cs b/src/Shared/FrameworkLocationHelper.cs index 135c2aa2b49..01ff320cf7d 100644 --- a/src/Shared/FrameworkLocationHelper.cs +++ b/src/Shared/FrameworkLocationHelper.cs @@ -33,7 +33,7 @@ internal enum DotNetFrameworkArchitecture /// /// Indicates the 64-bit .NET Framework /// - Bitness64 = 2 + Bitness64 = 2, } /// @@ -72,7 +72,7 @@ internal static class FrameworkLocationHelper internal static readonly Version visualStudioVersion170 = new Version(17, 0); // keep this up-to-date; always point to the latest visual studio version. - internal static readonly Version visualStudioVersionLatest = visualStudioVersion160; + internal static readonly Version visualStudioVersionLatest = visualStudioVersion170; private const string dotNetFrameworkRegistryPath = "SOFTWARE\\Microsoft\\.NETFramework"; private const string dotNetFrameworkSetupRegistryPath = "SOFTWARE\\Microsoft\\NET Framework Setup\\NDP"; @@ -145,7 +145,7 @@ internal static class FrameworkLocationHelper /// /// List the supported .net versions. /// - private static readonly DotNetFrameworkSpec[] s_dotNetFrameworkSpecs = + private static DotNetFrameworkSpec[] DotNetFrameworkSpecs() => new DotNetFrameworkSpec[] { // v1.1 new DotNetFrameworkSpecLegacy( @@ -225,7 +225,7 @@ internal static class FrameworkLocationHelper /// /// The items must be ordered by the version, because some methods depend on that fact to find the previous visual studio version. /// - private static readonly VisualStudioSpec[] s_visualStudioSpecs = + private static readonly Lazy VisualStudioSpecs = new(() => new VisualStudioSpec[] { // VS10 new VisualStudioSpec(visualStudioVersion100, "Windows\\v7.0A", null, null, new [] @@ -255,7 +255,7 @@ internal static class FrameworkLocationHelper dotNetFrameworkVersion40, dotNetFrameworkVersion45, dotNetFrameworkVersion451, - dotNetFrameworkVersion452 + dotNetFrameworkVersion452, }), // VS14 @@ -269,7 +269,7 @@ internal static class FrameworkLocationHelper dotNetFrameworkVersion451, dotNetFrameworkVersion452, dotNetFrameworkVersion46, - dotNetFrameworkVersion461 + dotNetFrameworkVersion461, }), // VS15 @@ -328,7 +328,7 @@ internal static class FrameworkLocationHelper dotNetFrameworkVersion472, dotNetFrameworkVersion48, }), - }; + }); #if FEATURE_WIN32_REGISTRY /// @@ -373,20 +373,14 @@ private static readonly (Version, Version)[,] s_explicitFallbackRulesForPathToDo { (dotNetFrameworkVersion471, visualStudioVersion160), (dotNetFrameworkVersion47, visualStudioVersion160) }, { (dotNetFrameworkVersion472, visualStudioVersion160), (dotNetFrameworkVersion471, visualStudioVersion160) }, { (dotNetFrameworkVersion48, visualStudioVersion160), (dotNetFrameworkVersion472, visualStudioVersion160) }, - }; + }; #endif // FEATURE_WIN32_REGISTRY - private static readonly IReadOnlyDictionary s_dotNetFrameworkSpecDict; - private static readonly IReadOnlyDictionary s_visualStudioSpecDict; + private static readonly Lazy> DotNetFrameworkSpecDict = new(() => DotNetFrameworkSpecs().ToDictionary(spec => spec.Version)); + private static readonly Lazy> VisualStudioSpecDict = new(() => VisualStudioSpecs.Value.ToDictionary(spec => spec.Version)); #endregion // Static member variables - static FrameworkLocationHelper() - { - s_dotNetFrameworkSpecDict = s_dotNetFrameworkSpecs.ToDictionary(spec => spec.Version); - s_visualStudioSpecDict = s_visualStudioSpecs.ToDictionary(spec => spec.Version); - } - #region Static properties internal static string PathToDotNetFrameworkV11 @@ -1118,13 +1112,13 @@ private static string FindRegistryValueUnderKey private static VisualStudioSpec GetVisualStudioSpec(Version version) { - ErrorUtilities.VerifyThrowArgument(s_visualStudioSpecDict.TryGetValue(version, out VisualStudioSpec spec), "FrameworkLocationHelper.UnsupportedVisualStudioVersion", version); + ErrorUtilities.VerifyThrowArgument(VisualStudioSpecDict.Value.TryGetValue(version, out VisualStudioSpec spec), "FrameworkLocationHelper.UnsupportedVisualStudioVersion", version); return spec; } private static DotNetFrameworkSpec GetDotNetFrameworkSpec(Version version) { - ErrorUtilities.VerifyThrowArgument(s_dotNetFrameworkSpecDict.TryGetValue(version, out DotNetFrameworkSpec spec), "FrameworkLocationHelper.UnsupportedFrameworkVersion", version); + ErrorUtilities.VerifyThrowArgument(DotNetFrameworkSpecDict.Value.TryGetValue(version, out DotNetFrameworkSpec spec), "FrameworkLocationHelper.UnsupportedFrameworkVersion", version); return spec; } @@ -1473,11 +1467,11 @@ public virtual string GetPathToDotNetFrameworkSdkTools(VisualStudioSpec visualSt // i.e. fallback to v110 if the current visual studio version is v120. if (!foundExplicitRule) { - int index = Array.IndexOf(s_visualStudioSpecs, visualStudioSpec); + int index = Array.IndexOf(VisualStudioSpecs.Value, visualStudioSpec); if (index > 0) { // The items in the array "visualStudioSpecs" must be ordered by version. That would allow us to fallback to the previous visual studio version easily. - VisualStudioSpec fallbackVisualStudioSpec = s_visualStudioSpecs[index - 1]; + VisualStudioSpec fallbackVisualStudioSpec = VisualStudioSpecs.Value[index - 1]; generatedPathToDotNetFrameworkSdkTools = FallbackToPathToDotNetFrameworkSdkToolsInPreviousVersion( this.Version, fallbackVisualStudioSpec.Version); @@ -1570,10 +1564,8 @@ public virtual string GetPathToWindowsSdk() #if FEATURE_WIN32_REGISTRY private static string FallbackToPathToDotNetFrameworkSdkToolsInPreviousVersion(Version dotNetFrameworkVersion, Version visualStudioVersion) { - VisualStudioSpec visualStudioSpec; - DotNetFrameworkSpec dotNetFrameworkSpec; - if (s_visualStudioSpecDict.TryGetValue(visualStudioVersion, out visualStudioSpec) - && s_dotNetFrameworkSpecDict.TryGetValue(dotNetFrameworkVersion, out dotNetFrameworkSpec) + if (VisualStudioSpecDict.Value.TryGetValue(visualStudioVersion, out VisualStudioSpec visualStudioSpec) + && DotNetFrameworkSpecDict.Value.TryGetValue(dotNetFrameworkVersion, out DotNetFrameworkSpec dotNetFrameworkSpec) && visualStudioSpec.SupportedDotNetFrameworkVersions.Contains(dotNetFrameworkVersion)) { return dotNetFrameworkSpec.GetPathToDotNetFrameworkSdkTools(visualStudioSpec); diff --git a/src/Shared/MSBuildNameIgnoreCaseComparer.cs b/src/Shared/MSBuildNameIgnoreCaseComparer.cs index 47beaffd08c..f02c8c5cada 100644 --- a/src/Shared/MSBuildNameIgnoreCaseComparer.cs +++ b/src/Shared/MSBuildNameIgnoreCaseComparer.cs @@ -22,16 +22,7 @@ internal class MSBuildNameIgnoreCaseComparer : IConstrainedEqualityComparer /// The processor architecture on which we are running, but default it will be x86 /// - private static readonly NativeMethodsShared.ProcessorArchitectures s_runningProcessorArchitecture; - - /// - /// We need a static constructor to retrieve the running ProcessorArchitecture that way we can - /// avoid using optimized code that will not run correctly on IA64 due to alignment issues - /// - static MSBuildNameIgnoreCaseComparer() - { - s_runningProcessorArchitecture = NativeMethodsShared.ProcessorArchitecture; - } + private static readonly NativeMethodsShared.ProcessorArchitectures s_runningProcessorArchitecture = NativeMethodsShared.ProcessorArchitecture; /// /// The default immutable comparer instance. diff --git a/src/Shared/TypeLoader.cs b/src/Shared/TypeLoader.cs index d296c8c7547..fe5ea680c49 100644 --- a/src/Shared/TypeLoader.cs +++ b/src/Shared/TypeLoader.cs @@ -23,7 +23,7 @@ internal class TypeLoader /// /// AssemblyContextLoader used to load DLLs outside of msbuild.exe directory /// - private static readonly CoreClrAssemblyLoader s_coreClrAssemblyLoader; + private static readonly CoreClrAssemblyLoader s_coreClrAssemblyLoader = new CoreClrAssemblyLoader(); #endif /// @@ -41,13 +41,6 @@ internal class TypeLoader /// private Func _isDesiredType; -#if FEATURE_ASSEMBLYLOADCONTEXT - static TypeLoader() - { - s_coreClrAssemblyLoader = new CoreClrAssemblyLoader(); - } -#endif - /// /// Constructor. /// diff --git a/src/Tasks/CultureInfoCache.cs b/src/Tasks/CultureInfoCache.cs index 4955e8a766e..a5c52d41275 100644 --- a/src/Tasks/CultureInfoCache.cs +++ b/src/Tasks/CultureInfoCache.cs @@ -19,35 +19,34 @@ namespace Microsoft.Build.Tasks /// internal static class CultureInfoCache { - private static readonly HashSet ValidCultureNames; + private static readonly HashSet ValidCultureNames = InitializeValidCultureNames(); - static CultureInfoCache() + static HashSet InitializeValidCultureNames() { - ValidCultureNames = new HashSet(StringComparer.OrdinalIgnoreCase); - #if !FEATURE_CULTUREINFO_GETCULTURES if (!AssemblyUtilities.CultureInfoHasGetCultures()) { - ValidCultureNames = HardcodedCultureNames; - return; + return HardcodedCultureNames; } #endif - + HashSet validCultureNames = new(StringComparer.OrdinalIgnoreCase); foreach (CultureInfo cultureName in AssemblyUtilities.GetAllCultures()) { - ValidCultureNames.Add(cultureName.Name); + validCultureNames.Add(cultureName.Name); } // https://docs.microsoft.com/en-gb/windows/desktop/Intl/using-pseudo-locales-for-localization-testing // These pseudo-locales are available in versions of Windows from Vista and later. // However, from Windows 10, version 1803, they are not returned when enumerating the // installed cultures, even if the registry keys are set. Therefore, add them to the list manually. - var pseudoLocales = new[] { "qps-ploc", "qps-ploca", "qps-plocm", "qps-Latn-x-sh" }; + string[] pseudoLocales = new[] { "qps-ploc", "qps-ploca", "qps-plocm", "qps-Latn-x-sh" }; foreach (string pseudoLocale in pseudoLocales) { - ValidCultureNames.Add(pseudoLocale); + validCultureNames.Add(pseudoLocale); } + + return validCultureNames; } /// diff --git a/src/Tasks/GenerateResource.cs b/src/Tasks/GenerateResource.cs index e5cb2b89c17..8d14a11f700 100644 --- a/src/Tasks/GenerateResource.cs +++ b/src/Tasks/GenerateResource.cs @@ -546,29 +546,6 @@ public GenerateResource() // do nothing } -#if FEATURE_COM_INTEROP - /// - /// Static constructor checks the registry opt-out for mark-of-the-web rejection. - /// - static GenerateResource() - { - if (!NativeMethodsShared.IsWindows) - { - allowMOTW = true; - return; - } - try - { - object allowUntrustedFiles = Registry.GetValue(@"HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\.NETFramework\SDK", "AllowProcessOfUntrustedResourceFiles", null); - if (allowUntrustedFiles is string allowUntrustedFilesString) - { - allowMOTW = allowUntrustedFilesString.Equals("true", StringComparison.OrdinalIgnoreCase); - } - } - catch { } - } -#endif - /// /// Logs a Resgen.exe command line that indicates what parameters were /// passed to this task. Since this task is replacing Resgen, and we used @@ -931,7 +908,7 @@ public override bool Execute() } #if FEATURE_COM_INTEROP - private static bool allowMOTW; + private static readonly bool AllowMOTW = !NativeMethodsShared.IsWindows || (Registry.GetValue(@"HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\.NETFramework\SDK", "AllowProcessOfUntrustedResourceFiles", null) is string allowUntrustedFiles && allowUntrustedFiles.Equals("true", StringComparison.OrdinalIgnoreCase)); private const string CLSID_InternetSecurityManager = "7b8a2d94-0ac9-11d1-896c-00c04fb6bfc4"; private const uint ZoneInternet = 3; @@ -942,7 +919,7 @@ public override bool Execute() private bool IsDangerous(String filename) { // If they are opted out, there's no work to do - if (allowMOTW) + if (AllowMOTW) { return false; } diff --git a/src/Tasks/GetFrameworkPath.cs b/src/Tasks/GetFrameworkPath.cs index 999bd44f434..5793e004a7c 100644 --- a/src/Tasks/GetFrameworkPath.cs +++ b/src/Tasks/GetFrameworkPath.cs @@ -14,26 +14,6 @@ namespace Microsoft.Build.Tasks /// public class GetFrameworkPath : TaskExtension { - static GetFrameworkPath() - { - s_path = new Lazy(() => ToolLocationHelper.GetPathToDotNetFramework(TargetDotNetFrameworkVersion.Latest)); - s_version11Path = new Lazy(() => ToolLocationHelper.GetPathToDotNetFramework(TargetDotNetFrameworkVersion.Version11)); - s_version20Path = new Lazy(() => ToolLocationHelper.GetPathToDotNetFramework(TargetDotNetFrameworkVersion.Version20)); - s_version30Path = new Lazy(() => ToolLocationHelper.GetPathToDotNetFramework(TargetDotNetFrameworkVersion.Version30)); - s_version35Path = new Lazy(() => ToolLocationHelper.GetPathToDotNetFramework(TargetDotNetFrameworkVersion.Version35)); - s_version40Path = new Lazy(() => ToolLocationHelper.GetPathToDotNetFramework(TargetDotNetFrameworkVersion.Version40)); - s_version45Path = new Lazy(() => ToolLocationHelper.GetPathToDotNetFramework(TargetDotNetFrameworkVersion.Version45)); - s_version451Path = new Lazy(() => ToolLocationHelper.GetPathToDotNetFramework(TargetDotNetFrameworkVersion.Version451)); - s_version452Path = new Lazy(() => ToolLocationHelper.GetPathToDotNetFramework(TargetDotNetFrameworkVersion.Version452)); - s_version46Path = new Lazy(() => ToolLocationHelper.GetPathToDotNetFramework(TargetDotNetFrameworkVersion.Version46)); - s_version461Path = new Lazy(() => ToolLocationHelper.GetPathToDotNetFramework(TargetDotNetFrameworkVersion.Version461)); - s_version462Path = new Lazy(() => ToolLocationHelper.GetPathToDotNetFramework(TargetDotNetFrameworkVersion.Version462)); - s_version47Path = new Lazy(() => ToolLocationHelper.GetPathToDotNetFramework(TargetDotNetFrameworkVersion.Version47)); - s_version471Path = new Lazy(() => ToolLocationHelper.GetPathToDotNetFramework(TargetDotNetFrameworkVersion.Version471)); - s_version472Path = new Lazy(() => ToolLocationHelper.GetPathToDotNetFramework(TargetDotNetFrameworkVersion.Version472)); - s_version48Path = new Lazy(() => ToolLocationHelper.GetPathToDotNetFramework(TargetDotNetFrameworkVersion.Version48)); - } - #region ITask Members /// @@ -52,23 +32,22 @@ public override bool Execute() // it still seems to give an advantage perhaps because there is one less string copy. // In a large build, this adds up. // PERF NOTE: We also only find paths we are actually asked for (via tags) - - private static readonly Lazy s_path; - private static readonly Lazy s_version11Path; - private static readonly Lazy s_version20Path; - private static readonly Lazy s_version30Path; - private static readonly Lazy s_version35Path; - private static readonly Lazy s_version40Path; - private static readonly Lazy s_version45Path; - private static readonly Lazy s_version451Path; - private static readonly Lazy s_version452Path; - private static readonly Lazy s_version46Path; - private static readonly Lazy s_version461Path; - private static readonly Lazy s_version462Path; - private static readonly Lazy s_version47Path; - private static readonly Lazy s_version471Path; - private static readonly Lazy s_version472Path; - private static readonly Lazy s_version48Path; + private static readonly Lazy s_path = new Lazy(() => ToolLocationHelper.GetPathToDotNetFramework(TargetDotNetFrameworkVersion.Latest)); + private static readonly Lazy s_version11Path = new Lazy(() => ToolLocationHelper.GetPathToDotNetFramework(TargetDotNetFrameworkVersion.Version11)); + private static readonly Lazy s_version20Path = new Lazy(() => ToolLocationHelper.GetPathToDotNetFramework(TargetDotNetFrameworkVersion.Version20)); + private static readonly Lazy s_version30Path = new Lazy(() => ToolLocationHelper.GetPathToDotNetFramework(TargetDotNetFrameworkVersion.Version30)); + private static readonly Lazy s_version35Path = new Lazy(() => ToolLocationHelper.GetPathToDotNetFramework(TargetDotNetFrameworkVersion.Version35)); + private static readonly Lazy s_version40Path = new Lazy(() => ToolLocationHelper.GetPathToDotNetFramework(TargetDotNetFrameworkVersion.Version40)); + private static readonly Lazy s_version45Path = new Lazy(() => ToolLocationHelper.GetPathToDotNetFramework(TargetDotNetFrameworkVersion.Version45)); + private static readonly Lazy s_version451Path = new Lazy(() => ToolLocationHelper.GetPathToDotNetFramework(TargetDotNetFrameworkVersion.Version451)); + private static readonly Lazy s_version452Path = new Lazy(() => ToolLocationHelper.GetPathToDotNetFramework(TargetDotNetFrameworkVersion.Version452)); + private static readonly Lazy s_version46Path = new Lazy(() => ToolLocationHelper.GetPathToDotNetFramework(TargetDotNetFrameworkVersion.Version46)); + private static readonly Lazy s_version461Path = new Lazy(() => ToolLocationHelper.GetPathToDotNetFramework(TargetDotNetFrameworkVersion.Version461)); + private static readonly Lazy s_version462Path = new Lazy(() => ToolLocationHelper.GetPathToDotNetFramework(TargetDotNetFrameworkVersion.Version462)); + private static readonly Lazy s_version47Path = new Lazy(() => ToolLocationHelper.GetPathToDotNetFramework(TargetDotNetFrameworkVersion.Version47)); + private static readonly Lazy s_version471Path = new Lazy(() => ToolLocationHelper.GetPathToDotNetFramework(TargetDotNetFrameworkVersion.Version471)); + private static readonly Lazy s_version472Path = new Lazy(() => ToolLocationHelper.GetPathToDotNetFramework(TargetDotNetFrameworkVersion.Version472)); + private static readonly Lazy s_version48Path = new Lazy(() => ToolLocationHelper.GetPathToDotNetFramework(TargetDotNetFrameworkVersion.Version48)); /// /// Path to the latest framework, whatever version it happens to be diff --git a/src/Utilities/TrackedDependencies/FileTracker.cs b/src/Utilities/TrackedDependencies/FileTracker.cs index d33f0b35127..b3c775b9642 100644 --- a/src/Utilities/TrackedDependencies/FileTracker.cs +++ b/src/Utilities/TrackedDependencies/FileTracker.cs @@ -85,7 +85,7 @@ public static class FileTracker // Is equal to C:\Documents and Settings\All Users\Application Data on XP, and C:\ProgramData on Vista+. // But for backward compatibility, the paths "C:\Documents and Settings\All Users\Application Data" and "C:\Users\All Users\Application Data" are still accessible via Junction point on Vista+. // Thus this list is created to store all possible common application data paths to cover more cases as possible. - private static readonly List s_commonApplicationDataPaths; + private static readonly List s_commonApplicationDataPaths = InitializeCommonApplicationDataPaths(); // The name of the standalone tracker tool. private const string s_TrackerFilename = "Tracker.exe"; @@ -105,29 +105,31 @@ public static class FileTracker #endregion -#region Static constructor +#region Static Member Initializers - static FileTracker() + static List InitializeCommonApplicationDataPaths() { - s_commonApplicationDataPaths = new List(); + List commonApplicationDataPaths = new(); string defaultCommonApplicationDataPath = FileUtilities.EnsureTrailingSlash(Environment.GetFolderPath(Environment.SpecialFolder.CommonApplicationData).ToUpperInvariant()); - s_commonApplicationDataPaths.Add(defaultCommonApplicationDataPath); + commonApplicationDataPaths.Add(defaultCommonApplicationDataPath); string defaultRootDirectory = Path.GetPathRoot(defaultCommonApplicationDataPath); string alternativeCommonApplicationDataPath1 = FileUtilities.EnsureTrailingSlash(Path.Combine(defaultRootDirectory, @"Documents and Settings\All Users\Application Data").ToUpperInvariant()); if (!alternativeCommonApplicationDataPath1.Equals(defaultCommonApplicationDataPath, StringComparison.Ordinal)) { - s_commonApplicationDataPaths.Add(alternativeCommonApplicationDataPath1); + commonApplicationDataPaths.Add(alternativeCommonApplicationDataPath1); } string alternativeCommonApplicationDataPath2 = FileUtilities.EnsureTrailingSlash(Path.Combine(defaultRootDirectory, @"Users\All Users\Application Data").ToUpperInvariant()); if (!alternativeCommonApplicationDataPath2.Equals(defaultCommonApplicationDataPath, StringComparison.Ordinal)) { - s_commonApplicationDataPaths.Add(alternativeCommonApplicationDataPath2); + commonApplicationDataPaths.Add(alternativeCommonApplicationDataPath2); } + + return commonApplicationDataPaths; } #endregion