2012-01-15 112 views
6

我正在寫一個程序,必須註冊啓動一個進程的時間,如記事本。 我認爲可以創建一個每秒鐘檢查所有進程的Timer。但我認爲這會減慢用戶的電腦。有沒有更好的方法來做到這一點?註冊過程開始時間的最佳方法是什麼?

+1

是的,由於許多原因,恆定輪詢是錯誤的解決方案,其中最重要的是性能下降。你正在尋找一個鉤子。但是你不能在C#中編寫鉤子DLL;你需要爲此使用C或C++。 – 2012-01-15 08:08:18

+0

你的實際目標是什麼?很難給你一個解決你的問題的答案。你想監視任何過程開始還是僅僅啓動特定過程?您是否需要準確獲取受監視流程的運行時間,或者您只對運行時間較長的流程感興趣10分鐘?根據您的答案,可能會發現輪詢是一個「足夠好」的折衷。有確切的方法來做到這一點,但這些要複雜得多。 – 2012-01-15 11:15:32

+0

對不起,**英語對我來說很難**。我想計算運行進程的時間並將其註冊到txt文件中。但我不想每秒檢查一次。 – 2012-01-15 11:32:26

回答

3

最初爲所有正在運行的進程確定創建時間。然後 使用WMI註冊進程創建事件。

請參閱下面的代碼如何使用WMI進程創建活動的一個小例子:

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編輯:

我進一步調查過程中創造的檢測與WMI和有是(更多)使用Win32_ProcessStartTrace類(請參閱TECHNET獲取更多信息)資源友好解決方案(但需要管理權限):

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

在此解決方案中,您不必設置輪詢間隔。

編輯完

BEGIN編輯2:

您可以使用Win32_ProcessStopTrace類監測過程停止事件。要組合進程啓動和進程停止事件,請使用Win32_ProcessTrace類。在事件處理程序使用ClassPath proberty開始區分/停止事件:

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

+0

-1第一個WMI在內部彙集。其次,你甚至不需要使用WMI。操作系統確實記錄了每個進程的開始時間。你所需要做的就是閱讀它。請參閱下面的答案。 – 2012-01-15 08:50:26

+0

謝謝。有沒有辦法檢查關閉過程呢? – 2012-01-15 09:25:41

+1

@MoctavaFarzán:是的,還有一個__InstanceDeletionEvent事件。但是,如果您打算同時使用__InstanceDeletionEvent和__InstanceCreationEvent,則應該訂閱__InstanceOperationEvent,然後通過評估e.NewEvent.ClassPath.ClassName屬性來檢查回調哪個事件。 – Hans 2012-01-15 09:33:36

2

沒有必要監視任何東西。您只需要枚舉進程並從進程實例StartTime中獲取。

+0

但你當然必須使用計時器或類似的東西?枚舉一次流程是不夠的。所以,我不明白你爲什麼投下我的答案? – Hans 2012-01-15 09:05:38

+0

有辦法實現它沒有計時器。您的答案的主要問題是,使用「__InstanceCreationEvent WITHIN 1」,您每秒都會進行輪詢。如果一個進程在這段時間內啓動並停止,您將永遠不會收到任何通知。如果您知道要檢查哪個進程,則在使用映像文件執行選項時可以從OS獲得回調。但是,第一個Farzan應該說明他如何獲得有問題的流程,哪些對他來說很有趣。有很多方法可以實現這一點。 – 2012-01-15 09:14:16

+0

是的,我是aggree。有許多解決方案,如圖像文件執行選項,掛鉤,使用定時器輪詢,使用WMI或使用驅動程序。所以,我真的不明白你的投票。 – Hans 2012-01-15 09:28:28

相關問題