RAM-Auslastung eines fremden Prozesses richtig auslesen (wie im Taskmanager) mit WMI ?!

  • VB.NET
  • .NET (FX) 1.0–2.0

Es gibt 5 Antworten in diesem Thema. Der letzte Beitrag () ist von Fakiz.

    RAM-Auslastung eines fremden Prozesses richtig auslesen (wie im Taskmanager) mit WMI ?!

    Hi liebe Community,

    ich habe aktuell folgenden Code, um die RAM-Auslastung eines Prozesses zu ermitteln:

    VB.NET-Quellcode

    1. Dim p As Process = Process.GetProcessById(123) ' 123 ist nur exemplarisch
    2. MessageBox.Show(p.PrivateMemorySize64)

    Leider weicht dieser Wert deutlich von dem Wert aus dem Taskmanager ab.
    So hat ein Programm laut Taskmanager ca. 21 MB ausgelagert, und mit dem o.g. Code werden mir ca. 30 MB angezeigt.

    Im Taskmanager steht die Beschreibung "Arbeitsspeicher (privater Arbeitssatz)".
    Deshalb habe ich auch die Methode PrivateMemorySize64 benutzt.
    Auch mit anderen Methoden konnte ich die vom Taskmanager angezeigten 21 MB nicht erreichen.

    Nach einigem googlen und durchstöbern bin ich dann auf WMI gestoßen, wo ich aber für meine Zwecke keine Denkanstöße gefunden habe.
    Ich sollte evtl. dazu sagen, dass ich noch nie was mit WMI gemacht habe, es aber nicht scheue, da dies ja schon ein mächtiges Werkzeug ist.

    Hat da jemand schon Erfahrung in diesem Thema und kann diese mit mir teilen?

    Ich danke Euch :rolleyes:


    Edit:

    Gerade selber herausgefunden.
    Mit WMI bekomme ich den selben Wert wie im Taskmanager angezeigt.

    1. Import

    VB.NET-Quellcode

    1. Imports System.Management


    2. Auslesen

    VB.NET-Quellcode

    1. Try
    2. Dim searcher As New ManagementObjectSearcher("root\CIMV2", "SELECT * FROM Win32_PerfFormattedData_PerfProc_Process")
    3. For Each queryObj As ManagementObject In searcher.Get()
    4. Console.WriteLine("-----------------------------------")
    5. Console.WriteLine(queryObj("Name"))
    6. Console.WriteLine("-----------------------------------")
    7. Console.WriteLine("WorkingSetPrivate: {0}", queryObj("WorkingSetPrivate"))
    8. Next
    9. Catch err As ManagementException
    10. MessageBox.Show("An error occurred while querying for WMI data: " & err.Message)
    11. End Try


    Zur Info, ich habe die ensprechenden Klassen und Namespaces mit dem Programm WMICodeCreator gefunden, habe es mal angehangen.
    Dateien

    Dieser Beitrag wurde bereits 8 mal editiert, zuletzt von „TRiViUM“ ()

    Hallo,
    PrivateMemorySize64 dürfte dir den 'Arbeitssatz (Speicher)' zurück geben. Für den fall das dir WMI zu langsam ist kannst du das ganze mittels der PerformanceCounter -Klasse aus dem Namespace System.Diagnostics lösen.

    Spoiler anzeigen

    VB.NET-Quellcode

    1. perfCounter = New System.Diagnostics.PerformanceCounter("Process", "Working Set - Private", System.Diagnostics.Process.GetCurrentProcess().ProcessName)
    2. textBox1.Text = String.Format("RAM: {0} K", (perfCounter.RawValue / 1024))


    PS: wenn du das ganze genu so wie im TaskMgr angezeigt bekommen willst

    VB.NET-Quellcode

    1. textBox1.Text = String.Format("RAM: {0} K", (Convert.ToDouble(perfCounter.RawValue) / 1024 / 1024).ToString("f3"))


    @Fakiz
    Hi!
    habe Deine Variante mal eben getestet und mir ist aufgefallen, dass es um einiges länger dauert, bis ich die Information mit dem PerformanceCounter anzezeigt bekomme, als mit WMI.
    Dabei vergehen bei Deinem Vorschlag ca. 7 Sekunden beim ersten mal ausführen. Danach geht es etwas flotter, ca. 4 Sekunden.

    Mit WMI dauert das ganze nur wenige Sekunden für alle Prozesse.
    Allerdings ist es mit nem PerfCounter nicht so viel Code.

    Letztendlich benutzt WMI doch auch nur nen PerfCounter?!

    Mir ist noch aufgefallen, dass ich den Wert von Working Set - Private wie folgt teilen muss, um das Ergebnis wie im Taskmanager zu bekommen: / 1024 / 1000 und nicht / 1024 / 1024 oder / 1000 / 1000, warum auch immer.

    Edit:
    Folgender Code funktioniert bei mir einwandfrei und vorallem flott:

    VB.NET-Quellcode

    1. Imports System.management
    2. Public Class Form1
    3. Private Sub Form1_Load(sender As Object, e As EventArgs) Handles MyBase.Load
    4. Try
    5. Using searcher As New ManagementObjectSearcher("root\CIMV2", "SELECT * FROM Win32_PerfFormattedData_PerfProc_Process")
    6. For Each queryObj As ManagementObject In searcher.Get()
    7. Console.WriteLine("-----------------------------------")
    8. Console.WriteLine(String.Format("{0} {1} K", queryObj("Name"), (Convert.ToDouble(queryObj("WorkingSetPrivate")) / 1024 / 1000).ToString("f3")))
    9. Console.WriteLine("-----------------------------------")
    10. Next
    11. End Using
    12. Catch err As ManagementException
    13. MessageBox.Show("An error occurred while querying for WMI data: " & err.Message)
    14. End Try
    15. End Sub
    16. End Class

    Dieser Beitrag wurde bereits 7 mal editiert, zuletzt von „TRiViUM“ ()

    Dabei vergehen bei Deinem Vorschlag ca. 7 Sekunden beim ersten mal ausführen. Danach geht es etwas flotter, ca. 4 Sekunden.

    Sehr interesant, damit hätte ich nicht gerechnet. Bei mir dauert es mit dem PerformanceCounter bei der ersten Abfrage 1 Sekunde mit WMI 0.5 Sekunden. Danach braucht der PerformanceCounter nur noch ~0.2 Sekunden.

    Letztendlich benutzt WMI doch auch nur nen PerfCounter?!

    Da bin ich mir nicht sicher hab mich damit noch nie befasst. Vermute aber es wird genau umgekehrt sein, der PerformanceCounter wird auf WMI zu greifen.

    Fakiz schrieb:

    Vermute aber es wird genau umgekehrt sein, der PerformanceCounter wird auf WMI zu greifen

    Ich dachte das, weil die Klassen so bei WMI beginnen (siehe Anhang).
    Und wenn der PerformanceCounter auf WMI zugreift, wieso geht es dann nicht schneller direkt mit WMI darauf zuzugreifen?
    Bilder
    • Unbenannt.png

      151,03 kB, 888×619, 193 mal angesehen
    Ich würde sagen das daß an einem spezifizierten Query liegt. Du kannst dir dafür wbemtest mal anguken WinTaste + R und wbemtest eingeben. Damit öffnet sich das Testprogramm für Windows-Verwaltungsintrumentation. Teste ich hier SELECT * FROM Win32_PerfFormattedData_PerfProc_Process Where Name="_Total" komme ich auf vergleichbare Werte wie mit dem PerformanceCounter + InstanceName = _Total.

    Aber wie gesagt ich kann hier total flasch liegen. Aufschluss dürfte hier MSDN oder evtl. der Objekt -Katalog von VS bringen.