2009-06-23 106 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; 
    } 
}