性能计数器实例名称与进程名称

Xha*_*lie 4 c# process performancecounter

我正在连接到该Process类别中的各种性能计数器.我使用以下c#方法来确定获取计数器时要使用的实例名称:

private const string _categoryName = "Process";
private const string _processIdCounter = "ID Process";

public static bool TryGetInstanceName(Process process, out string instanceName)
{
    PerformanceCounterCategory processCategory = new PerformanceCounterCategory(_categoryName);
    string[] instanceNames = processCategory.GetInstanceNames();
    foreach (string name in instanceNames)
    {
        using (PerformanceCounter processIdCounter = new PerformanceCounter(_categoryName, _processIdCounter, name, true))
        {
            if (process.Id == (int)processIdCounter.RawValue)
            {
                instanceName = name;
                return true;
            }
        }
    }

    instanceName = null;
    return false;
}
Run Code Online (Sandbox Code Playgroud)

现在,我注意到返回的实例名称通常与值相匹配Process.ProcessName.

实例名称和进程名称如何相关?

我问,因为我想简化foreach例程中的循环,这样我就不必获取ID Process与当前进程不匹配的实例的计数器.我设想了一个可能如下所示的最终方法:

public static bool TryGetInstanceName(Process process, out string instanceName)
{
    PerformanceCounterCategory processCategory = new PerformanceCounterCategory(_categoryName);
    string[] instanceNames = processCategory.GetInstanceNames();
    foreach (string name in instanceNames)
    {
        if (name /* more or less matches */ process.ProcessName)
        {
            using (PerformanceCounter processIdCounter = new PerformanceCounter(_categoryName, _processIdCounter, name, true))
            {
                // ...
            }
        }
    }

    instanceName = null;
    return false;
}
Run Code Online (Sandbox Code Playgroud)

Xha*_*lie 9

看到答案没有到来,我做了一些更多的试验和错误测试,并观察到以下行为:

定期流程

看来,对于具有给定名称的第一个常规进程,进程名称与实例名称匹配.对于具有相同名称的后续处理,实例名通过附加修改#1,#2...

令人震惊的是,似乎也可以更改与进程关联的实例名称.这似乎发生在数字序列中较早的进程结束时.确定实例名称和获取相关计数器之间存在竞争条件!

服务流程

在服务控制管理器下运行的Windows NT服务的行为方式与常规流程的行为方式相同.如果您在数字序列中较早结束服务进程,则实例名称似乎也会更改.

ASP.NET应用程序

除了进程名称之外,相同的假设适用于IIS下托管的应用程序w3wp.不同的应用.池肯定会通过启动和停止应用程序获得不同的进程.我确定实例名称在上述相同的情况下以相同的方式更改.

结论

我的结论是实例名称始终进程名称开头,方法可以修改如下:

public static bool TryGetInstanceName(Process process, out string instanceName)
{
    PerformanceCounterCategory processCategory = new PerformanceCounterCategory(_categoryName);
    string[] instanceNames = processCategory.GetInstanceNames();
    foreach (string name in instanceNames)
    {
        if (name.StartsWith(process.ProcessName))
        {
            using (PerformanceCounter processIdCounter = new PerformanceCounter(_categoryName, _processIdCounter, name, true))
            {
                if (process.Id == (int)processIdCounter.RawValue)
                {
                    instanceName = name;
                    return true;
                }
            }
        }
    }

    instanceName = null;
    return false;
}
Run Code Online (Sandbox Code Playgroud)

此外,在使用返回的实例名称时,确认存在上述竞争条件至关重要.

(如果没有进一步的输入,我会接受这个作为答案.请随意纠正我.)

  • 通过[注册表更改](https://support.microsoft.com/en-us/help/281884/the-process-object-in-performance-monitor-can-display-process-ids-pids),您可以配置窗口使用表单ProcessName_PID而不是附加#1等,这显然避免了[进程实例名称更改的可怕行为](https://blogs.technet.microsoft.com/askperf/2010/03/29 /性能监视器识别流程逐PID-代替-的实例/). (2认同)