异常:Instance '在指定的类别中不存在

本文关键字:不存在 Instance 异常 | 更新日期: 2023-09-27 17:54:20

当我像这样创建和使用性能计数器时:

private readonly PerformanceCounter _cpuPerformanceCounter;
public ProcessViewModel(Process process)
        {
             _cpuPerformanceCounter = new PerformanceCounter("Process", "% Processor Time", process.ProcessName, true);
        }
public void Update()
        {
            CPU = (int)_cpuPerformanceCounter.NextValue() / Environment.ProcessorCount; // Exception
        }

…我得到一个异常实例'实例的名称'不存在于指定的类别,不明白为什么。

注:代码

<?xml version="1.0" encoding="utf-8" ?>
<configuration>
  <system.net>
    <settings>
      <performanceCounters enabled="true"/>
    </settings>
  </system.net>
</configuration>

异常:Instance '在指定的类别中不存在

加上之前的帖子,我看到过进程被格式化为_-取决于你运行应用程序的操作系统(Win XP, Win Vista, Win 7, Win 2003或2008 Server)。为了有一种可靠的方法来标识进程名,以便以后获得其他性能计数器,一个函数可以像这样:

    private string ObtainProcessName()
    {
        string baseProcessName;
        string processName = null;
        int processId;
        bool notFound = true;
        int processOptionsChecked = 0;
        int maxNrOfParallelProcesses = 3 + 1;
        try
        {
            baseProcessName = Process.GetCurrentProcess().ProcessName;
        }
        catch (Exception exception)
        {
            return null;
        }
        try
        {
            processId = Process.GetCurrentProcess().Id;
        }
        catch (Exception exception)
        {
            return null;
        }
        while (notFound)
        {
            processName = baseProcessName;
            if (processOptionsChecked > maxNrOfParallelProcesses)
            {
                break;
            }
            if (1 == processOptionsChecked)
            {
                processName = string.Format("{0}_{1}", baseProcessName, processId);
            }
            else if (processOptionsChecked > 1)
            {
                processName = string.Format("{0}#{1}", baseProcessName, processOptionsChecked - 1);
            }
            try
            {
                PerformanceCounter counter = new PerformanceCounter("Process", "ID Process", processName);
                if (processId == (int)counter.NextValue())
                {
                    notFound = !true;
                }
            }
            catch (Exception)
            {
            }
            processOptionsChecked++;
        }
        return processName;
    }

我认为您的问题发生在有多个具有相同名称的进程时。PerfMon所做的就是在进程名后面加上#1,#2等。因此,这意味着MyApp.exe执行两次将导致此异常,当你试图读取"MyApp"的性能监视器。这里有一个解决这个问题的方法的链接:通过pid

读取性能计数器

以下是我对所有流程和多个流程实例的解决方案:

var processes = Process.GetProcesses().GroupBy(g => g.ProcessName);
        List<Tuple<string, PerformanceCounter>> pcList = new List<Tuple<string, PerformanceCounter>>();
        foreach (var pg in processes)
        {
            if (pg.First().ProcessName == "Idle")
                continue;
            if (pg.Count() == 1)
            {
                var process_cpu = new PerformanceCounter(
                           "Process",
                           "% Processor Time",
                           pg.First().ProcessName
                                );
                process_cpu.NextValue();
                pcList.Add(new Tuple<string, PerformanceCounter>(pg.First().ProcessName, process_cpu));
            }
            else
            {
                int id = 1;
                foreach(var p in pg)
                {
                    var process_cpu = new PerformanceCounter(
                           "Process",
                           "% Processor Time",
                           p.ProcessName + "#" + id
                                );
                    process_cpu.NextValue();
                    pcList.Add(new Tuple<string, PerformanceCounter>(p.ProcessName + "#" + id, process_cpu));
                    id++;
                }
            }
        }

使用pid后缀的原始格式(注册表ProcessNameFormat = 1)似乎已经在。net 4.5 (msdn链接)更改为"processame_pid_rid"。因此,当前写入的可接受答案可能不再适用于这种情况。

这个解决方案应该仍然适用于较新的格式:

https://weblog.west-wind.com/posts/2014/Sep/27/Capturing-Performance-Counter-Data-for-a-Process-by-Process-Id

然而,所有这些匹配的解决方案可能容易出现竞争条件,即在确定实例名之后,在分配新的PerformanceCounter()之前,由于进程退出(#9变为#8),实例名会发生变化。

对于MS来说,提供一个直接接受Pid(现在可能还有RuntimeId?)的PerformanceCounter构造函数会更有意义,因为实例名可以动态更改。

您可以查看此代码

Use > new PerformanceCounter("Processor Information", "% Processor Time", "_Total");
Instead of> new PerformanceCounter("Processor", "% Processor Time", "_Total");