Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,8 @@
<TargetFrameworks>$(NetCoreAppCurrent)-windows;$(NetCoreAppCurrent);netcoreapp3.1-windows;netcoreapp3.1;netstandard2.0;net461</TargetFrameworks>
<NoWarn>$(NoWarn);CA1847</NoWarn>
<IsPackable>true</IsPackable>
<GeneratePackageOnBuild>true</GeneratePackageOnBuild>
<ServicingVersion>1</ServicingVersion>
<PackageDescription>Provides the System.Diagnostics.PerformanceCounter class, which allows access to Windows performance counters.

Commonly Used Types:
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -45,12 +45,12 @@ internal sealed class PerformanceCounterLib
private const string LanguageKeyword = "language";
private const string DllName = "netfxperf.dll";

private const int EnglishLCID = 0x009;

private static volatile string s_computerName;
private static volatile string s_iniFilePath;
private static volatile string s_symbolFilePath;

private static CultureInfo s_englishCulture;

private PerformanceMonitor _performanceMonitor;
private readonly string _machineName;
private readonly string _perfLcid;
Expand Down Expand Up @@ -79,6 +79,25 @@ private static object InternalSyncObject
}
}

private static CultureInfo EnglishCulture
{
get
{
if (s_englishCulture is null)
{
try
{
s_englishCulture = CultureInfo.GetCultureInfo("en");
}
catch
{
s_englishCulture = CultureInfo.InvariantCulture;
}
}
return s_englishCulture;
}
}

internal PerformanceCounterLib(string machineName, string lcid)
{
_machineName = machineName;
Expand Down Expand Up @@ -277,11 +296,11 @@ private static string SymbolFilePath

internal static bool CategoryExists(string machine, string category)
{
PerformanceCounterLib library = GetPerformanceCounterLib(machine, new CultureInfo(EnglishLCID));
PerformanceCounterLib library = GetPerformanceCounterLib(machine, EnglishCulture);
if (library.CategoryExists(category))
return true;

if (CultureInfo.CurrentCulture.Parent.LCID != EnglishLCID)
if (CultureInfo.CurrentCulture.Parent.Name != EnglishCulture.Name)
{
CultureInfo culture = CultureInfo.CurrentCulture;
while (culture != CultureInfo.InvariantCulture)
Expand Down Expand Up @@ -349,11 +368,11 @@ internal void Close()

internal static bool CounterExists(string machine, string category, string counter)
{
PerformanceCounterLib library = GetPerformanceCounterLib(machine, new CultureInfo(EnglishLCID));
PerformanceCounterLib library = GetPerformanceCounterLib(machine, EnglishCulture);
bool categoryExists = false;
bool counterExists = library.CounterExists(category, counter, ref categoryExists);

if (!categoryExists && CultureInfo.CurrentCulture.Parent.LCID != EnglishLCID)
if (!categoryExists && CultureInfo.CurrentCulture.Parent.Name != EnglishCulture.Name)
{
CultureInfo culture = CultureInfo.CurrentCulture;
while (culture != CultureInfo.InvariantCulture)
Expand Down Expand Up @@ -753,7 +772,7 @@ internal static string[] GetCategories(string machineName)
culture = culture.Parent;
}

library = GetPerformanceCounterLib(machineName, new CultureInfo(EnglishLCID));
library = GetPerformanceCounterLib(machineName, EnglishCulture);
return library.GetCategories();
}

Expand All @@ -772,7 +791,7 @@ internal static string GetCategoryHelp(string machine, string category)

//First check the current culture for the category. This will allow
//PerformanceCounterCategory.CategoryHelp to return localized strings.
if (CultureInfo.CurrentCulture.Parent.LCID != EnglishLCID)
if (CultureInfo.CurrentCulture.Parent.Name != EnglishCulture.Name)
{
CultureInfo culture = CultureInfo.CurrentCulture;

Expand All @@ -788,7 +807,7 @@ internal static string GetCategoryHelp(string machine, string category)

//We did not find the category walking up the culture hierarchy. Try looking
// for the category in the default culture English.
library = GetPerformanceCounterLib(machine, new CultureInfo(EnglishLCID));
library = GetPerformanceCounterLib(machine, EnglishCulture);
help = library.GetCategoryHelp(category);

if (help == null)
Expand All @@ -808,9 +827,9 @@ private string GetCategoryHelp(string category)

internal static CategorySample GetCategorySample(string machine, string category)
{
PerformanceCounterLib library = GetPerformanceCounterLib(machine, new CultureInfo(EnglishLCID));
PerformanceCounterLib library = GetPerformanceCounterLib(machine, EnglishCulture);
CategorySample sample = library.GetCategorySample(category);
if (sample == null && CultureInfo.CurrentCulture.Parent.LCID != EnglishLCID)
if (sample == null && CultureInfo.CurrentCulture.Parent.Name != EnglishCulture.Name)
{
CultureInfo culture = CultureInfo.CurrentCulture;
while (culture != CultureInfo.InvariantCulture)
Expand Down Expand Up @@ -845,11 +864,11 @@ private CategorySample GetCategorySample(string category)

internal static string[] GetCounters(string machine, string category)
{
PerformanceCounterLib library = GetPerformanceCounterLib(machine, new CultureInfo(EnglishLCID));
PerformanceCounterLib library = GetPerformanceCounterLib(machine, EnglishCulture);
bool categoryExists = false;
string[] counters = library.GetCounters(category, ref categoryExists);

if (!categoryExists && CultureInfo.CurrentCulture.Parent.LCID != EnglishLCID)
if (!categoryExists && CultureInfo.CurrentCulture.Parent.Name != EnglishCulture.Name)
{
CultureInfo culture = CultureInfo.CurrentCulture;
while (culture != CultureInfo.InvariantCulture)
Expand Down Expand Up @@ -910,7 +929,7 @@ internal static string GetCounterHelp(string machine, string category, string co

//First check the current culture for the counter. This will allow
//PerformanceCounter.CounterHelp to return localized strings.
if (CultureInfo.CurrentCulture.Parent.LCID != EnglishLCID)
if (CultureInfo.CurrentCulture.Parent.Name != EnglishCulture.Name)
{
CultureInfo culture = CultureInfo.CurrentCulture;
while (culture != CultureInfo.InvariantCulture)
Expand All @@ -925,7 +944,7 @@ internal static string GetCounterHelp(string machine, string category, string co

//We did not find the counter walking up the culture hierarchy. Try looking
// for the counter in the default culture English.
library = GetPerformanceCounterLib(machine, new CultureInfo(EnglishLCID));
library = GetPerformanceCounterLib(machine, EnglishCulture);
help = library.GetCounterHelp(category, counter, ref categoryExists);

if (!categoryExists)
Expand Down Expand Up @@ -990,7 +1009,8 @@ private static string[] GetLanguageIds()

internal static PerformanceCounterLib GetPerformanceCounterLib(string machineName, CultureInfo culture)
{
string lcidString = culture.LCID.ToString("X3", CultureInfo.InvariantCulture);
// EnglishCulture.LCID == 9 will be false only if running with Globalization Invariant Mode. Use "009" at that time as default English language identifier.
string lcidString = EnglishCulture.LCID == 9 ? culture.LCID.ToString("X3", CultureInfo.InvariantCulture) : "009";

machineName = (machineName == "." ? ComputerName : machineName).ToLowerInvariant();

Expand Down Expand Up @@ -1135,11 +1155,11 @@ private Hashtable GetStringTable(bool isHelp)

internal static bool IsCustomCategory(string machine, string category)
{
PerformanceCounterLib library = GetPerformanceCounterLib(machine, new CultureInfo(EnglishLCID));
PerformanceCounterLib library = GetPerformanceCounterLib(machine, EnglishCulture);
if (library.IsCustomCategory(category))
return true;

if (CultureInfo.CurrentCulture.Parent.LCID != EnglishLCID)
if (CultureInfo.CurrentCulture.Parent.Name != EnglishCulture.Name)
{
CultureInfo culture = CultureInfo.CurrentCulture;
while (culture != CultureInfo.InvariantCulture)
Expand Down Expand Up @@ -1174,10 +1194,10 @@ internal static PerformanceCounterCategoryType GetCategoryType(string machine, s
{
PerformanceCounterCategoryType categoryType = PerformanceCounterCategoryType.Unknown;

PerformanceCounterLib library = GetPerformanceCounterLib(machine, new CultureInfo(EnglishLCID));
PerformanceCounterLib library = GetPerformanceCounterLib(machine, EnglishCulture);
if (!library.FindCustomCategory(category, out categoryType))
{
if (CultureInfo.CurrentCulture.Parent.LCID != EnglishLCID)
if (CultureInfo.CurrentCulture.Parent.Name != EnglishCulture.Name)
{
CultureInfo culture = CultureInfo.CurrentCulture;
while (culture != CultureInfo.InvariantCulture)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,8 +2,10 @@
// The .NET Foundation licenses this file to you under the MIT license.

using System;
using System.Globalization;
using System.Collections;
using System.Collections.Specialized;
using Microsoft.DotNet.RemoteExecutor;
using Xunit;

namespace System.Diagnostics.Tests
Expand Down Expand Up @@ -287,6 +289,32 @@ public static void PerformanceCounter_NextSample_MultiInstance()
}
}

private static bool CanRunInInvariantMode => RemoteExecutor.IsSupported && !PlatformDetection.IsNetFramework;

[ConditionalTheory(nameof(CanRunInInvariantMode))]
[PlatformSpecific(TestPlatforms.Windows)]
[InlineData(true)]
[InlineData(false)]
public static void RunWithGlobalizationInvariantModeTest(bool predefinedCultures)
{
ProcessStartInfo psi = new ProcessStartInfo() { UseShellExecute = false };
psi.Environment.Add("DOTNET_SYSTEM_GLOBALIZATION_INVARIANT", "1");
psi.Environment.Add("DOTNET_SYSTEM_GLOBALIZATION_PREDEFINED_CULTURES_ONLY", predefinedCultures ? "1" : "0");
RemoteExecutor.Invoke(() =>
{
// Ensure we are running inside the Globalization invariant mode.
Assert.Equal("", CultureInfo.CurrentCulture.Name);

// This test ensure creating PerformanceCounter object while we are running with Globalization Invariant Mode.
// PerformanceCounter used to create cultures using LCID's which fail in Globalization Invariant Mode.
// This test ensure no failure should be encountered in this case.
using (PerformanceCounter counterSample = new PerformanceCounter("Processor", "Interrupts/sec", "0", "."))
{
Assert.Equal("Processor", counterSample.CategoryName);
}
}, new RemoteInvokeOptions { StartInfo = psi}).Dispose();
}

public static PerformanceCounter CreateCounterWithCategory(string name, bool readOnly, PerformanceCounterCategoryType categoryType )
{
var category = Helpers.CreateCategory(name, categoryType);
Expand Down