Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

The best way to register process start time?

Tags:

c#

process

timer

I am writing a program that must register time of starting a process such as notepad. I thought that it is good to create a Timer that checks all of processes every second. But I think that it will slow down the user's computer. Is there a better way of doing this?

like image 780
Mostafa Farzán Avatar asked Jan 15 '12 08:01

Mostafa Farzán


2 Answers

Initially determine for all running processes the creation time. Then use WMI to register for process creation events.

See the code below for a small example on how to use WMI for process creation events:

static void Main(string[] args)
{
  using (ManagementEventWatcher eventWatcher =
            new ManagementEventWatcher(@"SELECT * FROM 
   __InstanceCreationEvent WITHIN 1 WHERE TargetInstance ISA 'Win32_Process'"))
  {
    // Subscribe for process creation notification.
    eventWatcher.EventArrived += ProcessStarted_EventArrived; 
    eventWatcher.Start();
    Console.In.ReadLine();
    eventWatcher.EventArrived -= ProcessStarted_EventArrived;
    eventWatcher.Stop();
  }
}


static void ProcessStarted_EventArrived(object sender, EventArrivedEventArgs e)
{
  ManagementBaseObject obj = e.NewEvent["TargetInstance"] as ManagementBaseObject;

  // The Win32_Process class also contains a CreationDate property.
  Console.Out.WriteLine("ProcessName: {0} " + obj.Properties["Name"].Value);
}

BEGIN EDIT:

I've further investigated process creation detection with WMI and there is a (more) resouces friendly solution (but needs administrative privileges) using the Win32_ProcessStartTrace class (please see TECHNET for further information):

using (ManagementEventWatcher eventWatcher =
          new ManagementEventWatcher(@"SELECT * FROM Win32_ProcessStartTrace"))
{
  // Subscribe for process creation notification.
  eventWatcher.EventArrived += ProcessStarted_EventArrived;
  eventWatcher.Start();
  Console.Out.WriteLine("started");
  Console.In.ReadLine();
  eventWatcher.EventArrived -= ProcessStarted_EventArrived;
  eventWatcher.Stop();
}

static void ProcessStarted_EventArrived(object sender, EventArrivedEventArgs e)
{               
  Console.Out.WriteLine("ProcessName: {0} " 
          + e.NewEvent.Properties["ProcessName"].Value);     
}

In this solution you do not have to set an polling interval.

END EDIT

BEGIN EDIT 2:

You could use the Win32_ProcessStopTrace class to monitor process stop events. To combine both process start and process stop events use the Win32_ProcessTrace class. In the event handler use the ClassPath proberty to distinguish between start/stop events:

using (ManagementEventWatcher eventWatcher =
       new ManagementEventWatcher(@"SELECT * FROM Win32_ProcessTrace"))
{          
  eventWatcher.EventArrived += Process_EventArrived;
  eventWatcher.Start();
  Console.Out.WriteLine("started");
  Console.In.ReadLine();
  eventWatcher.EventArrived -= Process_EventArrived;
  eventWatcher.Stop();
}

static void Process_EventArrived(object sender, EventArrivedEventArgs e)
{
  Console.Out.WriteLine(e.NewEvent.ClassPath); // Use class path to distinguish
                                               // between start/stop process events.
  Console.Out.WriteLine("ProcessName: {0} " 
      + e.NewEvent.Properties["ProcessName"].Value);     
}

END EDIT 2

like image 61
Hans Avatar answered Sep 16 '22 16:09

Hans


There is no need to monitor anything at all. All you need to do is to enumerate your processes and fetch from the Process Instances StartTime.

like image 23
Alois Kraus Avatar answered Sep 17 '22 16:09

Alois Kraus