2009-06-23 104 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

當進程dis出現?你需要每分鐘輪詢一分鐘才能獲得1分鐘的分辨率嗎? – 2009-06-23 20:39:39

0

輪詢是容易的,但你真的應該掛鉤到win32的事件,而是接受當這些事情發生的通知。

我有一個類似的邊項目來創建一個「任務欄」類型的應用程序。我的目標是在窗口移動/創建/關閉時通知應用程序,以便我可以使用此信息來顯示/更新UI。

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; 
    } 
}