EnumProcesses() vs. CreateToolhelp32Snapshot()

Lesezeit: 4 Minuten

Ich habe mich gefragt, ob es Unterschiede gibt – hauptsächlich in Bezug auf die Leistung – zwischen den beiden Win32-API-Funktionen EnumProcesses() und CreateToolhelp32Snapshot() zum Auflisten aller aktiven Prozesse und geladenen Module. Oder ob das eine besser zu verwenden ist als das andere und warum.

Benutzer-Avatar
Alex

Hier sind Ergebnisse einiger Funktionen:

  • EnumProcesses: 16 ms, 207 Prozesse
  • CreateToolhelp32Snapshot: 141 ms (16 ms), 207 Prozesse
  • WTSEnumerateProcesses: 16 ms, 207 Prozesse
  • WTSEnumerateProcessesEx(WTS_CURRENT_SESSION): 16 ms, 98 Prozesse
  • WTSEnumerateProcessesEx(WTS_ANY_SESSION): 16 ms, 207 Prozesse

Auf dem Computer wird Windows 8 mit aktivierter Benutzerkontensteuerung ausgeführt, der Benutzer ist nicht erhöht (hat z. B. keinen Zugriff auf Systemprozesse). Hauptprozess ist 32-Bit, Maschine ist 64-Bit, also gibt es viele 64-Bit-Prozesse. Es gibt: Sitzung 0 für das System, Sitzung 1 für den aktuellen Konsolenbenutzer, Sitzung 2 für einen anderen Fast-Switch-Benutzer. 207 Prozesse insgesamt (diese sind sowohl 32- als auch 64-Bit, einschließlich Pseudo-“System”-Prozess) – 207 wird auch von Process Explorer bestätigt. Unter diesen 207 Prozessen: 23 Prozesse sind für Sitzung 2, 98 Prozesse – für Sitzung 1 und die restlichen – für Sitzung 0.

Die Ergebnisse gelten für einen Zyklus von 10 einzelnen Funktionsaufrufen. Sie sind bei jedem Durchlauf zu 100 % reproduzierbar.

Für CreateToolhelp32Snapshot ist das Hauptergebnis der Aufruf von CreateToolhelp32Snapshot selbst, und das zweite Ergebnis (in Klammern) ist der Zyklus mit First/Next.

Ich denke, die Leute verwechseln “alle Prozesse aufzählen” (PIDs abrufen) und “Name des Prozesses/exe abrufen”. Der erste (“enumerate”) hat überhaupt keine Probleme mit x32/x64-Cross-Bitness. Aber letzteres (“get name”) hat Probleme – nicht jede Methode funktioniert über x32/x64.

Ich denke, sie sind in Bezug auf Leistung (und Ergebnisse) ziemlich gleich, da sie beide dieselbe zugrunde liegende NT-API aufrufen, obwohl CreateToolhelp32Snapshot() einen leichten Overhead haben kann, da es ein Abschnittsobjekt erstellt und alle Informationen dorthin kopiert EnumProcesses ()/EnumProcessModules() arbeitet direkt mit vom Benutzer bereitgestellten Puffern. In der realen Welt ist der Unterschied jedoch wahrscheinlich vernachlässigbar.

Ich bevorzuge EnumProcesses() etwas, da es (IMO) eine einfacher zu verwendende API ist, aber CreateToolhelp32Snapshot() gibt bei Bedarf mehr Informationen zurück. Der einzige Nachteil von EnumProcesses() ist, dass Sie es in einer Schleife aufrufen sollten, da Sie möglicherweise keinen ausreichend großen Puffer zugewiesen haben; CreateToolhelp32Snapshot() übernimmt die Pufferverwaltung für Sie. In der Praxis ordne ich dem Stapel einfach einen Puffer zu, der groß genug ist, um 1024 Prozess-IDs oder Modul-Handles aufzunehmen. Bisher ist mir noch kein System begegnet, bei dem eine dieser Grenzen auch nur annähernd erreicht wäre. Natürlich haben wir vor nicht allzu langer Zeit dasselbe über MAX_PATH gesagt und jetzt stoßen wir damit auf Probleme …

  • Ruft tatsächlich an EnumProcesses() in einer Schleife ist das kein Problem. Benutz einfach std::vector<BYTE> zur Verwaltung der Pufferlebensdauer.

    – scharfer Zahn

    26. Oktober 2010 um 11:46 Uhr

  • Ah, sie rufen also dieselbe zugrunde liegende API auf. Das deckt größtenteils ab, was ich wissen wollte. Vielen Dank.

    – jay.lee

    27. Oktober 2010 um 22:31 Uhr

  • “groß genug, um 1024 Prozess-IDs zu speichern” – das könnte auf Terminaldienste-/Remotedesktopmaschinen, die 30 Benutzer mit jeweils 40 Prozessen bedienen, leicht erschöpft sein.

    – Alex

    2. Oktober 2015 um 14:03 Uhr

Ich erinnere mich nicht genau, aber im Gegensatz zu CreateToolhelp32Snapshot() hat EnumProcesses() eine von zwei oder beiden Einschränkungen: 1. Listet keine 64-Bit-Prozesse auf, wenn sie von einem 32-Bit-Prozess auf einem x64-Betriebssystem aufgerufen werden. 2. Listet erhöhte Prozesse unter Vista und Win7 nicht auf.

  • Um EnumProcesses effektiv zu nutzen, muss man höchstwahrscheinlich jeden Prozess öffnen und Informationen abfragen. Wenn man PROCESS_QUERY_INFORMATION und PROCESS_VM_READ anfordert (die von GetModuleBaseName benötigt werden), schlägt dies bei einigen Prozessen fehl. Um die in Dmitriys Antwort erwähnten Einschränkungen zu vermeiden, kann man mit PROCESS_QUERY_LIMITED_INFORMATION öffnen und stattdessen GetProcessImageFileName verwenden (außer bei alten Windows-Versionen).

    – Lexika

    25. Mai 2017 um 9:15 Uhr

CreateToolhelp32Snapshot FTW. EnumProcesses listet nicht alle Systemprozesse wie alle Instanzen von svchost.exe auf, zumindest nicht unter Win XP.

IMO liegt der Hauptunterschied in den Anforderungen an Berechtigungen. Ich habe Fälle gesehen, in denen EnumProcesses() würde scheitern, aber CreateToolhelp32Snapshot() lief einwandfrei.

Also musste ich einmal Code schreiben, der einen bestimmten Prozess auf einem System erkennt und entsprechend reagiert. Ich habe es mit geschrieben EnumProcesses() und es funktionierte gut auf meiner Maschine, aber nicht auf den Maschinen der Tester. Ich habe es gerade mit umgeschrieben CreateToolhelp32Snapshot() und ich habe noch nie von Problemen damit gehört.

  • Als ich mir das letzte Mal EnumProcesses() und CreateToolhelp32Snapshot() angesehen habe, haben beide dieselbe zugrunde liegende NT-API (NtQuerySystemInformation) aufgerufen, daher bin ich mir nicht sicher, wie Sie unterschiedliche Ergebnisse erhalten würden.

    – Lukas

    26. Oktober 2010 um 11:25 Uhr

  • Als ich mir das letzte Mal EnumProcesses() und CreateToolhelp32Snapshot() angesehen habe, haben beide dieselbe zugrunde liegende NT-API (NtQuerySystemInformation) aufgerufen, daher bin ich mir nicht sicher, wie Sie unterschiedliche Ergebnisse erhalten würden.

    – Lukas

    26. Oktober 2010 um 11:25 Uhr

1371580cookie-checkEnumProcesses() vs. CreateToolhelp32Snapshot()

This website is using cookies to improve the user-friendliness. You agree by using the website further.

Privacy policy