2012-01-15 12 views
6

Piszę program, który musi zarejestrować czas rozpoczęcia procesu, taki jak notatnik. Pomyślałem, że dobrze jest stworzyć zegar, który sprawdza wszystkie procesy co sekundę. Ale myślę, że spowolni to komputer użytkownika. Czy jest lepszy sposób na zrobienie tego?Najlepszy sposób rejestrowania czasu rozpoczęcia procesu?

+1

Tak, stała odpytywanie jest niewłaściwym rozwiązaniem z wielu powodów, a nie najmniejszym z nich jest pogorszenie wydajności. Szukasz haka. Ale nie można zapisać biblioteki DLL w języku C#; do tego celu będziesz musiał użyć C lub C++. –

+0

Jaki jest Twój rzeczywisty cel? Trudno jest udzielić odpowiedzi, która rozwiązuje twój problem. Czy chcesz monitorować każdy start procesu lub tylko początek określonego procesu? Czy chcesz dokładnie monitorować środowisko wykonawcze monitorowanych procesów lub czy interesują Cię tylko procesy, które działają dłużej? 10 minut? W zależności od odpowiedzi może się okazać, że głosowanie jest kompromisem "wystarczająco dobrym". Istnieją na to konkretne sposoby, ale są one znacznie bardziej złożone. –

+0

Niestety, ** Angielski jest dla mnie trudny **. Chcę odmierzać czas uruchamiania procesu i zarejestrować go w pliku txt. Ale nie chcę tego sprawdzać w każdej sekundzie. –

Odpowiedz

3

Początkowo ustal dla wszystkich uruchomionych procesów czas utworzenia. Następnie użyj usługi WMI, aby zarejestrować zdarzenia związane z tworzeniem procesów.

Zobacz poniższy kod na mały przykład na temat korzystania z WMI na imprezy tworzenia procesu:

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:

mam dalej badane wykrywanie tworzenia proces z WMI i tam jest (więcej) odnawia przyjazne rozwiązanie (ale wymaga uprawnień administratora) przy użyciu klasy Win32_ProcessStartTrace (więcej informacji można znaleźć na stronie 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);  
} 

W tym rozwiązaniu nie trzeba ustawiać interwału odpytywania.

END EDIT

BEGIN EDIT 2:

Można użyć klasy Win32_ProcessStopTrace do monitorowania zdarzeń zatrzymania procesu. Aby połączyć oba zdarzenia rozpoczęcia procesu i zatrzymania procesu, należy użyć klasy Win32_ProcessTrace. W obsługi zdarzeń użyć ClassPath proberty odróżnić rozpoczęciem imprezy/stop:

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 pierwszy WMI wykonuje wewnętrzną pulę. Po drugie nie musisz nawet korzystać z WMI. System operacyjny zapisuje już czas rozpoczęcia każdego procesu. Wszystko, co musisz zrobić, to przeczytać. Zobacz moją odpowiedź poniżej. –

+0

Dziękuję. Czy istnieje również sposób sprawdzenia procesów zamykania? –

+1

@ MoctavaFarzán: Tak, istnieje również zdarzenie __InstanceDeletionEvent. Ale jeśli planujesz używać zarówno __InstanceDeletionEvent, jak i __InstanceCreationEvent, powinieneś zasubskrybować __InstanceOperationEvent, a następnie sprawdzić wywołanie zwrotne, które zdarzenie zostało wywołane, oceniając właściwość e.NewEvent.ClassPath.ClassName. – Hans

2

Nie ma potrzeby, aby monitorować w ogóle nic. Wszystko, co musisz zrobić, to wyliczyć swoje procesy i pobrać z Process Instances StartTime.

+0

Ale na pewno trzeba użyć timera lub czegoś podobnego? Wyliczanie procesów raz nie wystarczy. Więc nie rozumiem, dlaczego nie głosowałeś na moją odpowiedź? – Hans

+0

Istnieją sposoby, aby to osiągnąć bez licznika czasu. Główny problem z twoją odpowiedzią polega na tym, że przy "__InstanceCreationEvent WITHIN 1" odpytujesz co sekundę. Jeśli proces rozpocznie się i zakończy w tym czasie, nigdy nie otrzymasz żadnego powiadomienia. Jeśli wiesz, który proces chcesz sprawdzić, możesz uzyskać wywołanie zwrotne z systemu operacyjnego podczas korzystania z opcji wykonywania plików obrazu. Ale najpierw Farzan powinien powiedzieć, w jaki sposób otrzymuje te procesy i które są dla niego interesujące. Istnieje wiele sposobów, aby to osiągnąć. –

+0

Tak, zgadzam się. Istnieje wiele rozwiązań, takich jak opcje wykonywania plików obrazu, haki, odpytywanie za pomocą licznika czasu, korzystanie z usługi WMI lub korzystanie ze sterownika. Tak naprawdę nie rozumiałem twojego głosowania w dół. – Hans

Powiązane problemy