2009-06-23 5 views
1

Я хотел бы разработать приложение (которое работает всегда в фоновом режиме), чтобы отслеживать использование приложений (msword, excel, powerpoint, * .exe и т. Д.).Как отслеживать использование приложения?

Я могу обработать отправку данных в базу данных, но точно не знаю, с чего начать с мониторинга запущенных приложений (когда они начинаются, когда они останавливаются). У кого-нибудь есть подсказки?

ответ

3

Вы можете периодически опрашивать список запущенных процессов с использованием System.Diagnostics.Process.GetProcesses().

Этот следующий код выводит информацию о запуске и выходе процессов. Выход из системных процессов не будет распознаваться.

class Program 
{ 
    struct ProcessStartTimePair 
    { 
     public Process Process { get; set; } 
     public DateTime StartTime { get; set; } 
     public DateTime ExitTime 
     { 
      get 
      { 
       return DateTime.Now; // approximate value 
      } 
     } 

     public ProcessStartTimePair(Process p) : this() 
     { 
      Process = p; 
      try 
      { 
       StartTime = p.StartTime; 
      } 
      catch (System.ComponentModel.Win32Exception) 
      { 
       StartTime = DateTime.Now; // approximate value 
      } 
     } 
    } 

    static void Main(string[] args) 
    { 
     List<ProcessStartTimePair> knownProcesses = new List<ProcessStartTimePair>(); 
     while (true) 
     { 
      foreach (Process p in Process.GetProcesses()) 
      { 
       if (!knownProcesses.Select(x => x.Process.Id).Contains(p.Id)) 
       { 
        knownProcesses.Add(new ProcessStartTimePair(p)); 
        Console.WriteLine("Detected new process: " + p.ProcessName); 
       } 
      } 

      for (int i = 0; i < knownProcesses.Count; i++) 
      { 
       ProcessStartTimePair pair = knownProcesses[i]; 
       try 
       { 
        if (pair.Process.HasExited) 
        { 
         Console.WriteLine(pair.Process.ProcessName + " has exited (alive from {0} to {1}).", pair.StartTime.ToString(), pair.ExitTime.ToString()); 
         knownProcesses.Remove(pair); 
         i--; // List was modified, 1 item less 
         // TODO: Store in the info in the database 
        } 
       } 
       catch (System.ComponentModel.Win32Exception) 
       { 
        // Would have to check whether the process still exists in Process.GetProcesses(). 
        // The process probably is a system process. 
       } 
      } 
      Console.WriteLine(); 
      System.Threading.Thread.Sleep(1000); 
     } 
    } 
} 

Возможно, вы можете просто проигнорировать системные процессы, которые не позволяют вам прочитать свойство HasExited.

Редактировать

Вот .net версии 2.0:

static void Main(string[] args) 
    { 
     List<ProcessStartTimePair> knownProcesses = new List<ProcessStartTimePair>(); 
     while (true) 
     { 
      foreach (Process p in Process.GetProcesses()) 
      { 
       if (!ProcessIsKnown(knownProcesses, p.Id)) 
       { 
        knownProcesses.Add(new ProcessStartTimePair(p)); 
        Console.WriteLine("Detected new process: " + p.ProcessName); 
       } 
      } 

      for (int i = 0; i < knownProcesses.Count; i++) 
      [...] 
     } 
    } 

    static bool ProcessIsKnown(List<ProcessStartTimePair> knownProcesses, int ID) 
    { 
     foreach (ProcessStartTimePair pstp in knownProcesses) 
     { 
      if (pstp.Process.Id == ID) 
      { 
       return true; 
      } 
     } 
     return false; 
    } 

Обратите внимание, что код может быть улучшена, и только показывает концепцию.

+0

Что происходит, когда процесс появляется? Вы должны опросить каждую минуту, чтобы получить разрешение в 1 минуту? –

+0

Да, вам нужно будет каждую минуту вытаскивать за это. Я бы сохранил все существующие процессы в списке и проверить, есть ли новые или некоторые из них вышли. – weiqure

+0

Да, я думаю, что как только приложение закроется, ExitTime не будет accisble (поскольку он не работает). Я хочу сказать, что пользователь 'jdoe' использовал excel в общей сложности 44 минуты в июле – Jason

1

Вы можете периодически просматривать все окна верхнего уровня и записывать текст заголовка окна; и, основываясь на этом, делают некоторые выводы о том, какая программа работает.

Или вы можете сделать это через имя процесса или комбинацию.

Для перечисления окон см. http://msdn.microsoft.com/en-us/library/ms633497(VS.85).aspx и here is how to use it in managed code. Для перечисления процессов, используйте метод Process.GetProcesses или увидеть http://www.codeproject.com/KB/threads/enumprocess.aspx

0

Опрос легко, но вы действительно должны подключаться к событиям win32 и получать уведомления о том, когда это происходит.

У меня есть аналогичный боковой проект для создания приложения типа «задача». Моя цель заключается в том, чтобы приложение было уведомлено, когда окна перемещаются/создаются/закрываются, поэтому я могу использовать эту информацию для отображения/обновления пользовательского интерфейса.

bb4win У приложения есть этот «слой», где он может захватывать различные виды уведомлений из системы и использует его для создания альтернативной оболочки рабочего стола. Исходный код используется и кодируется в c.

Это ссылка, которую я использовал для начала работы с Win32 Hooks.

1

Можно использовать WMI, чтобы получить уведомление, когда процессы начинаются/Выход

A full working example is in a blog post on ASP.NET.

Основы него (скопированные из блога для потомков):

Создать класс, который наследуется от ManagementEventWatcher

Внутри конструктора, установить:

this.Query.QueryLanguage = "WQL"; 
this.Query.QueryString = @"SELECT * FROM 
__InstanceOperationEvent WITHIN 1 WHERE TargetInstance ISA 'Win32_Process'"; 
this.EventArrived += watcher_EventArrived; // Delegate for EventArrivedEventHandler 

сделать EventArrivedEventHandler как :

private void watcher_EventArrived(object sender, EventArrivedEventArgs e) 
{ 
    string eventType = e.NewEvent.ClassPath.ClassName; 
    Win32_Process proc = new 
     Win32_Process(e.NewEvent["TargetInstance"] as ManagementBaseObject); 

    switch (eventType) 
    { 
     case "__InstanceCreationEvent": 
      Console.WriteLine("Process Created"); 
      break; 
     case "__InstanceDeletionEvent": 
      Console.WriteLine("Process Deleted (Ended)"); 
      break; 
     case "__InstanceModificationEvent": 
      Console.WriteLine("Process Modified (possibly still running)"); 
      break; 
    } 
}