WMI Process Watching utilise trop de temps processeur! Une meilleure méthode?

StackOverflow https://stackoverflow.com/questions/345199

  •  19-08-2019
  •  | 
  •  

Question

Je dois surveiller le démarrage ou l'arrêt de certains processus sur une machine Windows. J'utilise actuellement le système WMI et l'interroge toutes les 5 secondes, mais cela provoque un pic du processeur toutes les 5 secondes, car WMI est WMI. Existe-t-il une meilleure façon de le faire? Je pourrais simplement faire une liste des processus en cours et y attacher un événement Exited via l'espace de noms System.Diagnostics, mais il n'y a pas de gestionnaire d'événements pour la création.

Était-ce utile?

La solution

Ce n’est pas exactement ce que vous feriez dans le monde réel, mais devriez aider. Cela semble ne pas beaucoup conduire mon processeur.

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

Autres conseils

J'ai eu des pics de ressources processeur lors de l'écoute d'événements WMI, dans les cas où je n'ai pas réussi à me détacher correctement de mes événements lors de la sortie / du nettoyage. Vous voudrez peut-être vérifier que vous ne présentez pas de "fuites". Abonnements aux événements WMI. Juste au cas où, détachez-vous de l'événement le plus tôt possible et assurez-vous de toujours le faire.

Pour illustrer davantage, voici un exemple tiré de mon livre PowerShell à l'écoute. aux événements WMI à l'aide de la bibliothèque PSEventing:

  

Add-PSSnapin PSEventing -ErrorAction   SilentlyContinue

     

$ queryString = @ '       SELECT *       FROM __InstanceModificationEvent       DANS 10       OÙ           TargetInstance ISA 'Win32_Service'           AND TargetInstance.Name = 'w3svc'           AND TargetInstance.State = 'Arrêté' '@

     

$ query = New-Object System.Management.WQLEventQuery `       -argumentList $ queryString

     

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

     

Observateur Connect-EventListener   EventArrived

     

$ watcher.Start ()

     

echo "En attente du service W3CSVC   pour arrêter ... " Get-Event -wait |       foreach {           Write-Host -foreground Red " Le service W3SVC s'est arrêté! & Quot;       }

     

$ watcher.Stop ()

     

Observateur Disconnect-EventListener EventArrived

     

echo "done"

Si je ne fais pas le bit Disconnect-EventListener à la sortie du script, des pics de processeur surviennent la troisième ou la quatrième fois que j'attache à l'événement. À mon avis, le système tente toujours de diffuser des événements.

Si vous recherchez uniquement le PID / le nom de vos processus, vous pouvez également choisir les événements Win32_ProcessTrace, en utilisant une requête WQL telle que "SELECT * FROM Win32_ProcessTrace WHERE TargetInstance.ProcessName =" name "=" name "" le cas échéant * .

Le piège de l'utilisation de "SELECT * FROM __InstanceModificationEvent WITHIN 10 WHERE TargetInstance ISA 'Win32Process' AND TargetInstance.Name = 'name' & ';'; est dans la façon dont cela fonctionne sur le back-end. Si vous inspectez wbemess.log dans votre répertoire% windir% \ system32 \ wbem \ logs, vous remarquerez les journaux suivants (à l'aide de __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

Comme vous pouvez le constater, la mise en oeuvre de l'événement sur la machine distante consiste à effectuer une requête sur Win32_Process à un intervalle spécifié par votre valeur dans la clause WITHIN. En conséquence, les processus qui démarrent et s’arrêtent dans ce sondage ne déclencheront jamais un événement.

Vous pouvez définir la clause WITHIN sur une petite valeur pour essayer de minimiser cet effet, mais la meilleure solution consiste à utiliser un événement réel tel que Win32_ProcessTrace, qui doit toujours se déclencher.

* Notez que MSDN indique que Win32_ProcessTrace requiert au minimum Windows XP sur un ordinateur client et Windows 2003 sur un ordinateur serveur pour fonctionner. Si vous utilisez un système d’exploitation plus ancien, vous risquez d’être bloqué à l’aide de la requête __InstanceModificationEvent.

Ma réponse ici mentionne une alternative autre que WMI: https://stackoverflow.com/a/50315772/3721646 Les requêtes WMI peuvent coûter de lourdes performances au processeur si elles ne sont pas conçues correctement. Si un événement intrinsèque de la classe Win32_Process est utilisé pour suivre un événement de création de processus, les performances sont fortement affectées. Une autre approche consiste à exploiter les journaux d'audit de sécurité. Vous pouvez activer le suivi des processus à l'aide de la stratégie de sécurité locale ou à l'aide d'un objet de stratégie de groupe dans le cas de plusieurs ordinateurs. Une fois le suivi du processus lancé, vous pouvez vous abonner aux journaux des événements de sécurité avec une requête XML personnalisée pour surveiller certains processus qui vous intéressent. L'ID d'événement de création de processus est 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>
Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top