例外:实例“实例名称”在指定的类别中不存在

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

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 } 

…我得到一个exception实例“实例的名称”在指定的类别中不存在,并且不理解原因。

PS代码

         

…包含在App.config中。

添加到以前的post,我看到进程被格式化为 _ – 取决于您运行应用程序的操作系统(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”的性能监视器时,这意味着执行两次MyApp.exe将导致此exception。 这是解决此问题的一种方法的链接: 通过pid读取性能计数器

使用pid后缀(注册表ProcessNameFormat = 1)的origninal格式似乎已从.NET 4.5( msdn链接 )更改为“processame_pid_rid”。 因此,当前所写的已接受的答案可能不再适用于该案例。

此解决方案仍应适用于较新的格式:

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

但是,所有这些匹配解决方案都可能容易出现竞争条件,其中实例名称由于进程退出而变化(#9变为#8),紧接在确定实例名称之后但在分配新的PerformanceCounter()之前。

MS提供一个直接接受Pid(可能现在是RuntimeId?)的PerformanceCounter构造函数会更有意义,因为实例名称可以随时更改。

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

 var processes = Process.GetProcesses().GroupBy(g => g.ProcessName); List> pcList = new List>(); 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(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(p.ProcessName + "#" + id, process_cpu)); id++; } } } 

您可以查看此代码

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