How to get process' CPU usage knowing PID?

Collapse
X
 
  • Time
  • Show
Clear All
new posts
  • Dimon
    New Member
    • Jul 2007
    • 18

    How to get process' CPU usage knowing PID?

    I'm trying to send out an alert in case when process takes more than certain % of CPU. I'm using the following code to get it:

    PerformanceCoun ter pcProcess = new PerformanceCoun ter();
    pcProcess.Categ oryName = "Process";
    pcProcess.Count erName = "% Processor Time";
    pcProcess.Insta nceName = "ProcessNam e";
    pcProcess.NextV alue();
    System.Threadin g.Thread.Sleep( 1000);
    double d = pcProcess.NextV alue();
    //Console.WriteLi ne("Process:{0 } CPU% {1}", strProcessName, d);

    After that I'm using d variable to check if alert needs to be sent out or not.

    But the problem is my program is running in many instances meaning all those instances have the same process name in task manager and therefore I don't know which one is which. So the point is I want each instance to check its own % process time, how do I separate them? I can get PID using Process class but how would I use it?
    Or maybe you know the way to set a process name in the beginning of the code for each instance?
    Also say there are 3 processes with the same name, which one's % Processor Time would PerformanceCoun ter get using the code above?

    Thank you in advance!
  • Dimon
    New Member
    • Jul 2007
    • 18

    #2
    please need help ASAP!

    Comment

    • Plater
      Recognized Expert Expert
      • Apr 2007
      • 7872

      #3
      If you are running your .exe 3 times, each will have a different PID.
      If they are running as threads, you can use the thread ID.

      Other then that I'm not sure what you are asking?

      Comment

      • Dimon
        New Member
        • Jul 2007
        • 18

        #4
        Originally posted by Plater
        If you are running your .exe 3 times, each will have a different PID.
        If they are running as threads, you can use the thread ID.

        Other then that I'm not sure what you are asking?
        Yes, that's the whole point - I can get PID for each one but how would I use it to get CPU usage for every instance? Using PerformanceCoun ter class I can retrieve CPU usage knowing process name, but since process name is the same for all three instances I need to distinguish them somehow so that I know what instance is related to what CPU usage.

        Comment

        • Plater
          Recognized Expert Expert
          • Apr 2007
          • 7872

          #5
          Cannot you get process usage information based on PID? Because I am pretty sure you can get at that from withen the code.
          Or you can go through the Process class and maybe find it.

          Comment

          • Dimon
            New Member
            • Jul 2007
            • 18

            #6
            Originally posted by Plater
            Cannot you get process usage information based on PID? Because I am pretty sure you can get at that from withen the code.
            Or you can go through the Process class and maybe find it.
            Well, if I could get this information based on PID I wouldn't post :)
            I tried to go through Process class but couldn't find anything except this
            Process.GetCurr entProcess().To talProcessorTim e, but I'm not sure how it's related to CPU usage (%) that you can see in task manager.

            Comment

            • TRScheel
              Recognized Expert Contributor
              • Apr 2007
              • 638

              #7
              Originally posted by Dimon
              Well, if I could get this information based on PID I wouldn't post :)
              I tried to go through Process class but couldn't find anything except this
              Process.GetCurr entProcess().To talProcessorTim e, but I'm not sure how it's related to CPU usage (%) that you can see in task manager.
              [code=cpp]
              static void Main(string[] args)
              {
              foreach (Process p in Process.GetProc esses())
              {
              PerformanceCoun ter pc = new PerformanceCoun ter();
              pc.InstanceName = p.ProcessName;

              Thread TestThread = new Thread(new ParameterizedTh readStart(GetCP UPercentage));
              TestThread.Star t(pc);
              }
              ConsoleUtilitie s.PressAnyKey(" ");
              }

              static void GetCPUPercentag e(Object pc)
              {
              try
              {
              ((PerformanceCo unter)pc).Categ oryName = "Process";
              ((PerformanceCo unter)pc).Count erName = "% Processor Time";
              ((PerformanceCo unter)pc).NextV alue();
              Thread.Sleep(10 00);
              Console.WriteLi ne("{0}: {1}%", ((PerformanceCo unter)pc).Insta nceName, ((PerformanceCo unter)pc).NextV alue());
              }
              catch { }
              }
              [/code]

              That can be easily modified to grab the process in question. For instance, if you passed an array to GetCpuPercentag e, and in one item you had the performance counter and in another you had the process, you could grab the PID of the problematic instance.


              EDIT: ConsoleUtilitie s is a library I built of common things I do on the console (such as, say "Press any key to continue")

              Comment

              • Dimon
                New Member
                • Jul 2007
                • 18

                #8
                Originally posted by TRScheel
                [code=cpp]
                static void Main(string[] args)
                {
                foreach (Process p in Process.GetProc esses())
                {
                PerformanceCoun ter pc = new PerformanceCoun ter();
                pc.InstanceName = p.ProcessName;

                Thread TestThread = new Thread(new ParameterizedTh readStart(GetCP UPercentage));
                TestThread.Star t(pc);
                }
                ConsoleUtilitie s.PressAnyKey(" ");
                }

                static void GetCPUPercentag e(Object pc)
                {
                try
                {
                ((PerformanceCo unter)pc).Categ oryName = "Process";
                ((PerformanceCo unter)pc).Count erName = "% Processor Time";
                ((PerformanceCo unter)pc).NextV alue();
                Thread.Sleep(10 00);
                Console.WriteLi ne("{0}: {1}%", ((PerformanceCo unter)pc).Insta nceName, ((PerformanceCo unter)pc).NextV alue());
                }
                catch { }
                }
                [/code]

                That can be easily modified to grab the process in question. For instance, if you passed an array to GetCpuPercentag e, and in one item you had the performance counter and in another you had the process, you could grab the PID of the problematic instance.


                EDIT: ConsoleUtilitie s is a library I built of common things I do on the console (such as, say "Press any key to continue")
                Thank you.
                But I'm not sure how your code helps me. Let's look at the example:
                I have program named test.exe. There are three scheduled tasks that runs this program with different parameters on the same server, say "test 1/2/3". If you look at the task manager u'll see 3 processes with the "test" name.
                Using your code in main method in loop through the processes it gets process with the "test" name and passes it in to the GetCpuPercentag e method, but how does it know what "test" process from the list of processes to grab? There are three of them. I need to write it the way so say instance test1 checks just process that was created by this instance and doesn't touch other two with the same name.

                BTW, forgot to mention - I'm working with Framework 1.1 (trying to convince management to switch to at least 2 version), so ParameterizedTh readStart won't really work. I'm not even sure what it's for as I never dealt with such Thread constructor :)

                Comment

                • TRScheel
                  Recognized Expert Contributor
                  • Apr 2007
                  • 638

                  #9
                  Originally posted by Dimon
                  Thank you.
                  But I'm not sure how your code helps me. Let's look at the example:
                  I have program named test.exe. There are three scheduled tasks that runs this program with different parameters on the same server, say "test 1/2/3". If you look at the task manager u'll see 3 processes with the "test" name.
                  Using your code in main method in loop through the processes it gets process with the "test" name and passes it in to the GetCpuPercentag e method, but how does it know what "test" process from the list of processes to grab? There are three of them. I need to write it the way so say instance test1 checks just process that was created by this instance and doesn't touch other two with the same name.

                  BTW, forgot to mention - I'm working with Framework 1.1 (trying to convince management to switch to at least 2 version), so ParameterizedTh readStart won't really work. I'm not even sure what it's for as I never dealt with such Thread constructor :)

                  Well, I was getting to the fact that if you pass the process into the thread start function as well, you will have all the information about that specific process (such as the PID, etc).

                  ParameterizedTh readStart lets you pass variables into a thread start. Without this, you will need to rethink how my method works.

                  Here is the updated code (and please note, its a staple example of ugly arse code, coded for functionality):

                  [code=cpp]
                  static void Main(string[] args)
                  {
                  foreach (Process p in Process.GetProc esses())
                  {
                  PerformanceCoun ter pc = new PerformanceCoun ter();
                  pc.InstanceName = p.ProcessName;

                  Thread TestThread = new Thread(new ParameterizedTh readStart(GetCP UPercentage));
                  ArrayList al = new ArrayList();
                  al.Add(pc);
                  al.Add(p);
                  TestThread.Star t(al);
                  }
                  ConsoleUtilitie s.PressAnyKey(" ");
                  }

                  static void GetCPUPercentag e(Object Params)
                  {
                  PerformanceCoun ter pc = (PerformanceCou nter)((ArrayLis t)Params)[0];
                  Process p = (Process)((Arra yList)Params)[1];
                  try
                  {
                  pc.CategoryName = "Process";
                  pc.CounterName = "% Processor Time";
                  pc.NextValue();
                  Thread.Sleep(10 00);
                  Console.WriteLi ne("{0} | {1}: {2}%", pc.InstanceName , p.Id, pc.NextValue()) ;
                  }
                  catch { }
                  }
                  [/code]

                  Comment

                  • Plater
                    Recognized Expert Expert
                    • Apr 2007
                    • 7872

                    #10
                    The process class contains a thing that lets you see what the command line arguments to the program was. So if you started the programs:
                    "test.exe 123"
                    "test.exe 4-6-7"
                    "test.exe blah"

                    You would be able to see the "123", "4-6-7", "blah" in the Process class.

                    Comment

                    • TRScheel
                      Recognized Expert Contributor
                      • Apr 2007
                      • 638

                      #11
                      Originally posted by Plater
                      The process class contains a thing that lets you see what the command line arguments to the program was. So if you started the programs:
                      "test.exe 123"
                      "test.exe 4-6-7"
                      "test.exe blah"

                      You would be able to see the "123", "4-6-7", "blah" in the Process class.
                      That underneath the StartInfo properties?

                      Comment

                      • Plater
                        Recognized Expert Expert
                        • Apr 2007
                        • 7872

                        #12
                        Originally posted by TRScheel
                        That underneath the StartInfo properties?
                        Yup:
                        Didn't you say each instance of test.exe is monitoring it's own cpu usage?
                        So couldn't you use Process.GetCurr entProcess(); to get the correct process ID for the running one (as opposed to the PID for one of the other test.exe's running)
                        Code:
                        System.Diagnostics.Process p;
                        p = System.Diagnostics.Process.GetCurrentProcess();
                        int mypid = p.Id;
                        string myEXE = p.MainModule.FileName;
                        string myarguments = p.StartInfo.Arguments;
                        MessageBox.Show("PID: " + mypid.ToString() + "\r\n" + myEXE + "\r\n" + myarguments);

                        Comment

                        • Dimon
                          New Member
                          • Jul 2007
                          • 18

                          #13
                          Originally posted by Plater
                          Yup:
                          Didn't you say each instance of test.exe is monitoring it's own cpu usage?
                          So couldn't you use Process.GetCurr entProcess(); to get the correct process ID for the running one (as opposed to the PID for one of the other test.exe's running)
                          Code:
                          System.Diagnostics.Process p;
                          p = System.Diagnostics.Process.GetCurrentProcess();
                          int mypid = p.Id;
                          string myEXE = p.MainModule.FileName;
                          string myarguments = p.StartInfo.Arguments;
                          MessageBox.Show("PID: " + mypid.ToString() + "\r\n" + myEXE + "\r\n" + myarguments);
                          Thank you, but again, I definitely can get PID for each instance, the thing is I don't know how to use it to get CPU usage as PerformanceCoun ter class uses process name to get it instead of PID.

                          Note, my program doesn't have parameters, it runs without them, this was just an example. And even if I could get parameter how would it help me to get CPU usage for that particular instance? So the only things I can get are name of the program(process name) and PID for each ones. But I'm not sure how knowing process name helps me since there are 3 of them in task manager with the same name.
                          So the question is - how would I get CPU usage (%) knowing PID?

                          Comment

                          • Plater
                            Recognized Expert Expert
                            • Apr 2007
                            • 7872

                            #14
                            Ok, sorry about that. For some reason I still had it in my head that you wanted the PID.

                            I just looked into creating the performance counter through windows management console and I saw something under the instances:
                            "explorer"
                            "explorer#1 "

                            It appears the first process gets it's name and after that a # and a counter is appended to the isntance name.

                            So I guess what you would have to do to figure who came first, would be to look at the StartTime of the Process Object....but that seems like it wouldn't be a garuntee.


                            I think you can compute it from the Process object though.
                            Like some formula of total time run against the time spent in user/privledged CPU. You might then have to compare that against the system idle process' values of the same thing.

                            Comment

                            • Dimon
                              New Member
                              • Jul 2007
                              • 18

                              #15
                              Ok thank you all, I guess I found the way to do it using Win32_PerfForma ttedData_PerfPr oc_Process class from WMI. It's that simple.

                              Comment

                              Working...