Exception: Instance 'Name of instance' does not exist in the specified Category

后端 未结 5 1000
长情又很酷
长情又很酷 2021-01-11 16:40

When I create and use performance counters like this:

private readonly PerformanceCounter _cpuPerformanceCounter;
public ProcessViewModel(Process process)
           


        
相关标签:
5条回答
  • 2021-01-11 16:49

    Adding on to previous posts, I have seen processes being formatted like <ProcessName>_<ProcessId> - depending on the OS you are running your app on (Win XP, Win Vista, Win 7, Win 2003 or 2008 Server). In order to have a reliable way to identify your process name for obtaining other performance counters down the road, a function could look like this:

        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;
        }
    
    0 讨论(0)
  • 2021-01-11 16:50

    The origninal format that used a pid suffix (registry ProcessNameFormat = 1) appears to have changed as of .NET 4.5 (msdn link) to "processame_pid_rid". Thus, the accepted answer as currently written may no longer work for that case.

    This solution should still work for the newer formats:

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

    However all these matching solutions may be prone to a race condition where the instance name changes due to a process exiting (#9 becomes #8) just after the instance name was determined but before the new PerformanceCounter() was allocated.

    It would make much more sense for MS to provide a PerformanceCounter constructor that accepts a Pid (and possibly now RuntimeId?) directly since the instance names can change on the fly.

    0 讨论(0)
  • 2021-01-11 16:52

    I think your issue happens when there are more than one process with the same name. What PerfMon does then is append #1, #2, etc to the process name. So that means MyApp.exe executed twice will cause this exception when you try to read the performance monitor for "MyApp". Here's a link to one way of solving this: Read performance counters by pid

    0 讨论(0)
  • 2021-01-11 16:57

    You can check this code

    Use > new PerformanceCounter("Processor Information", "% Processor Time", "_Total");
    Instead of> new PerformanceCounter("Processor", "% Processor Time", "_Total");
    
    0 讨论(0)
  • 2021-01-11 17:08

    Here is my solution for all processes and multiple process instances:

    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++;
                    }
                }
            }
    
    0 讨论(0)
提交回复
热议问题