Frage

Ich muß aufpassen, wenn bestimmte Prozesse gestartet werden oder auf einer Windows-Maschine gestoppt. Ich bin derzeit in den WMI-System abgegriffen und es alle 5 Sekunden abfragt, aber dies führt zu einer CPU Spike alle 5 Sekunden, da WMI WMI. Gibt es einen besseren Weg, dies zu tun? Ich konnte nur eine Liste der laufenden Prozesse machen und ein Ereignis Exited ihnen durch den System.Diagnostics Namespace anhängen, aber es gibt keine Event-Handler für die Schöpfung.

War es hilfreich?

Lösung

Dies ist nicht genau, wie Sie es in der realen Welt tun würden aber helfen sollen. Das scheint nicht meine CPU viel überhaupt zu fahren.

    static void Main(string[] args)
    {
        // Getting all instances of notepad
        // (this is only done once here so start up some notepad instances first)
        // you may want use GetProcessByPid or GetProcesses and filter them as required
        Process[] processesToWatch = Process.GetProcessesByName("notepad");

        foreach (var process in processesToWatch)
        {
            process.EnableRaisingEvents = true;
            process.Exited +=
                (s, e) => Console.WriteLine("An instance of notepad exited");
        }

        Thread watchThread = new Thread(() =>
            {
                while (true)
                {
                    Process[] processes = Process.GetProcesses();
                    foreach (var process in processes)
                    {
                        Console.WriteLine("{0}:{1}", process.Id, process.ProcessName);
                    }
                    // Don't dedicate a thread to this like I'm doing here
                    // setup a timer or something similiar
                    Thread.Sleep(2000);
                }
            });
        watchThread.IsBackground = true;
        watchThread.Start();

        Console.WriteLine("Polling processes and waiting for notepad process exit events");
        Console.ReadLine();
    }

Andere Tipps

Ich habe CPU-Spitzen hat, als in den Fällen WMI-Ereignisse zu hören, wo ich es versäumt habe, bei der Ausfahrt / Bereinigung richtig von meinen Ereignissen zu lösen. Vielleicht möchten Sie nicht „undichte“ WMI Ereignisabonnements überprüfen. Nur für den Fall lösen sich von der Veranstaltung so früh wie möglich und stellen Sie sicher, Sie tun es immer.

weiter zu veranschaulichen, hier ein Beispiel von meinem Powershell Buch , der zuhört um WMI-Ereignisse der PSEventing Bibliothek:

  

Add-PSSnapin PSEventing -ErrorAction   SilentlyContinue

     

$ querystring = @‘       WÄHLEN *       VON __InstanceModificationEvent       INNERHALB VON 10       WO           TargetInstance ISA 'Win32_Service'           UND TargetInstance.Name = 'w3svc'           UND TargetInstance.State = 'Gestoppt' ‚@

     

$ query = New-Object System.Management.WQLEventQuery `       -ArgumentList $ querystring

     

$ watcher = New-Object   System.Management.ManagementEventWatcher ($ query)

     

Connect-Eventlistener watcher   EventArrived

     

$ watcher.Start ()

     

echo „Warten auf den W3CSVC Service   zu stoppen ...“Get-Event -wait | foreach {           Write-Host -foreground Red "Der W3SVC-Dienst beendet hat!"       }

     

$ watcher.Stop ()

     

Disconnect-Eventlistener Beobachter EventArrived

     

echo "done"

Wenn ich nicht tue der Disconnect-Eventlistener Bit auf Skript Ausgang, bekomme ich CPU das dritte oder vierte Mal Spikes ich auf das Ereignis anhang. Meine Vermutung ist, dass das System immer noch versucht, Ereignisse zu liefern.

Wenn Sie nur für PID / Namen des Prozesses suchen, können Sie stattdessen auf Win32_ProcessTrace Ereignissen abholen wollen, eine WQL-Abfrage wie „SELECT * FROM Win32_ProcessTrace WHERE TargetInstance.ProcessName =‚name‘“ ggf. * .

Die Falle der Verwendung von "SELECT * FROM __InstanceModificationEvent INNERHALB VON 10 WHERE TargetInstance ISA 'Win32Process UND TargetInstance.Name = 'name'" in ist, wie es funktioniert am hinteren Ende. Wenn Sie überprüfen wbemess.log in Ihrem% windir% \ system32 \ wbem \ logs-Verzeichnis, werden Sie die folgenden Protokolle feststellen (mit __InstanceDeletionEvent):

(Wed Jul 22 13:58:31 2009.73889577) : Registering notification sink with query select * from __InstanceDeletionEvent within 10 where TargetInstance ISA 'Win32_Process' in namespace //./root/CIMV2.
(Wed Jul 22 13:58:31 2009.73889577) : Activating filter 047209E0 with query select * from __InstanceDeletionEvent within 10 where TargetInstance ISA 'Win32_Process' in namespace //./root/CIMV2.
(Wed Jul 22 13:58:31 2009.73889577) : Activating filter 0225E560 with query select * from __ClassOperationEvent where TargetClass isa "Win32_Process" in namespace //./root/CIMV2.
(Wed Jul 22 13:58:31 2009.73889577) : Activating filter 'select * from __ClassOperationEvent where TargetClass isa "Win32_Process"' with provider $Core
(Wed Jul 22 13:58:31 2009.73889587) : Activating filter 'select * from __InstanceDeletionEvent within 10 where TargetInstance ISA 'Win32_Process'' with provider $Core
(Wed Jul 22 13:58:31 2009.73889587) : Instituting polling query select * from Win32_Process to satisfy event query select * from __InstanceDeletionEvent within 10 where TargetInstance ISA 'Win32_Process'
(Wed Jul 22 13:58:31 2009.73889587) : Executing polling query 'select * from Win32_Process' in namespace '//./root/CIMV2'
(Wed Jul 22 13:58:31 2009.73889697) : Polling query 'select * from Win32_Process' done
(Wed Jul 22 13:58:41 2009.73899702) : Executing polling query 'select * from Win32_Process' in namespace '//./root/CIMV2'
(Wed Jul 22 13:58:41 2009.73899792) : Polling query 'select * from Win32_Process' done

Wie Sie sehen können, ist die eigentliche Ereignis Implementierung auf dem entfernten Rechner eine Abfrage Win32_Process auf einem Intervall durchzuführen, die durch Ihren Wert in dem WITHIN-Klausel angegeben ist. Als Ergebnis, dass alle Prozesse starten und innerhalb dieser Umfrage stoppen wird nie ein Ereignis ausgelöst.

Sie können die WITHIN-Klausel auf einen kleinen Wert gesetzt, diesen Effekt zu versuchen und zu minimieren, aber die bessere Lösung ist ein wahres Ereignis wie Win32_ProcessTrace zu verwenden, der sollte immer Feuer.

* Beachten Sie, dass MSDN zeigt Win32_ProcessTrace ein Minimum von Windows XP auf einem Client-Rechner und Windows 2003 auf einer Server-Maschine erfordert zu arbeiten. Wenn Sie mit einem älteren Betriebssystem arbeiten, können Sie stecken können die __InstanceModificationEvent Abfrage verwendet wird.

Meine Antwort hier erwähnt eine andere Möglichkeit, als WMI: https://stackoverflow.com/a/50315772/3721646 WMI-Abfragen können schwere CPU-Leistung kosten, wenn nicht richtig ausgelegt. Wenn ein intrinsisches Ereignis von Win32_Process Klasse verwendet wird Prozesserstellung Ereignis zu verfolgen, Leistung in diesen Auswirkungen stark. Ein alternativer Ansatz ist Security-Audit-Protokolle zu nutzen. Sie können Prozessverfolgung mithilfe der lokalen Sicherheitsrichtlinie oder die Verwendung eines GPO bei mehreren Maschinen ermöglichen. Sobald die Prozessverfolgung beginnt, können Sie mit einer benutzerdefinierten XML-Abfrage, um Sicherheitsereignisprotokolle abonnieren Sie bestimmen Prozesse Ihres Interesses zu überwachen. Die Prozesserstellung Ereignis-ID ist 4688. `

<QueryList>
 <Query Id="0" Path="Security">
   <Select Path="Security">
       *[EventData[Data[@Name='NewProcessName'] ='C:\Windows\explorer.exe']]
       and
       *[System[(EventID=4688)]]
   </Select>
 </Query>
</QueryList>
Lizenziert unter: CC-BY-SA mit Zuschreibung
Nicht verbunden mit StackOverflow
scroll top