PowerShell (am besten geeignet)

PowerShell (am besten geeignet)

Ich möchte den pro Sitzung verwendeten Speicher über eine PowerShell-Funktion abrufen. Mich interessieren nur getrennte Sitzungen. Im Taskmanager kann ich den pro Sitzungs-ID verwendeten Speicher sehen:

Bildbeschreibung hier eingeben

Ich habe versucht, den in MB verwendeten Arbeitsspeicher in PowerShell mithilfe des folgenden Skripts abzurufen:

# Get all user sessions
$sessions = qwinsta | Where-Object { $_ -match 'Disc' }
$procs = get-process # | where-object {$_.ProcessName -ne "Idle"}

foreach ($session in $sessions)
{
    $sessionId = ($session -split '\s+')[2]
    $usrprocs = $procs | where-object {$_.SessionId -eq $sessionId}
    $usrMem=0
    foreach($proc in $usrprocs)
    {
         $usrMem = $usrMem + [int64]($proc.WorkingSet64/(1024*1024))         
    }
    echo "$sessionId, $usrMem"
}

Aber das gibt mir das folgende Ergebnis:

20, 481
21, 451
22, 670
23, 763
24, 949

Das ist nicht annähernd der im Task-Manager angegebene Arbeitsspeicherverbrauch. Wie kann ich den RAM pro Sitzung ermitteln?

Aktualisieren Aufgrund des Vorschlags von Vomit IT habe ich Folgendes getan, bekomme aber trotzdem noch die falschen Werte angezeigt:

# Get all user sessions
$sessions = qwinsta | Where-Object { ($_ -match 'Disc') }

foreach ($session in $sessions)
{
    $sessionId = ($session -split '\s+')[2]
    $usrprocs = Get-Process | Where-Object { $_.SessionId -eq $sessionId }
    $usrMem=0
    foreach($proc in $usrprocs)
    {
         $usrMem = $usrMem + [int](Get-Counter -Counter "\Process($($proc.Name))\Working Set - Private").CounterSamples.CookedValue / 1KB      
    }
    echo "$sessionId, $usrMem"
}

Ergebnis

20, 808288
22, 830872
23, 806404
24, 806312
25, 802892

Antwort1

PowerShell (am besten geeignet)

Danke, Vomit ;), das funktioniert wie gewünscht und ermöglicht mir, die RAM-Nutzung pro getrennter Sitzung zu sehen. Ich habe die Erfahrung gemacht, dass es Get-Countersehr langsam ist, jeder Aufruf in einer Schleife dauert ca. 1 Sekunde. Also habe ich mich dafür entschieden, mitzumachen Get-CimInstance -ClassName Win32_PerfRawData_PerfProc_Processund dann den Arbeitssatz privat zu machen. – rinkert

Wie vom OP hervorgehoben, Get-Counterist die Leistung nicht so optimal wie Get-CimInstancebeim Abrufen von Eigenschaftswerten aus der entsprechenden Klasse. Diese Variante von PowerShell berücksichtigt diese Überlegung und bietet eine verbesserte Leistung, falls dies für Sie von Bedeutung ist.

$session = quser | Where-Object { ($_ -match 'Disc') } 2>&1;
$sId = $session | ForEach-Object  { ($_ -split '\s+')[2]};
$processes = Get-Process | Where-Object { $_.SessionId -in $sId };

foreach ($process in $processes) {
    $workingSet = [int](Get-CimInstance -ClassName Win32_PerfRawData_PerfProc_Process -Filter "Name='$($process.Name)'").WorkingSetPrivate / 1KB;
    "$($process.Id), $($workingSet)";
};

Ein Gotcha

Bitte beachten Sie, dass die obige Lösung möglicherweise Probleme beim Zugriff auf bestimmte WorkingSetPrivateEigenschaftswerte in der Klasse hat. Erwägen Sie bei Bedarf das Hinzufügen einer bedingten Logik, um Null- und Nullwerte zu ignorieren und so ein besseres Ergebnis zu erzielen.

foreach ($process in $processes) {
    $instance = Get-CimInstance -ClassName Win32_PerfRawData_PerfProc_Process -Filter "Name='$($process.Name)'"
    if ($instance.WorkingSetPrivate -ne $null -and $instance.WorkingSetPrivate -gt 0) {
        $workingSet = [int]($instance.WorkingSetPrivate / 1KB)
        "$($process.Id), $($workingSet)"
    }
}

Andere Lösungen

Integrieren Sie diese Lösung entsprechend in Ihre Aufgabewird dieses Problem lösen. Dieses Beispiel ist eine einfache Version und entspricht genau den Werten in derTaskmanagerwie Sie es für aktiven privaten RAM bevorzugen.

Im Wesentlichen dies ...

  • Fügt den Get-ProcessBefehl in eine ForEach-ObjectSchleife ein, um jeden zurückgegebenen Prozess- und Eigenschaftswert zu durchlaufen.
  • Verwendet ein PSCustomObject, um die PIDin einem Feld zu speichern.
  • Verwendet Get-Counter, gibt an, was Working Set - Privatezurückgegeben werden soll, wandelt es in ein um [int]und dividiert das dann 1 KBin einem anderen Feld durch .

Die Ergebnisse geben eine Spalte mit PIDund eine weitere Spalte mit der Memory (active private)Übereinstimmung mit dem zurück, was Sie im Task-Manager und in der DetailsRegisterkartenansicht dort für diese Eigenschaften sehen.

Power Shell

$session = quser | Where-Object { ($_ -match 'Disc') } 2>&1;
$sId = $session | ForEach-Object  { ($_ -split '\s+')[2]};

Get-Process | Where-Object { $_.SessionId -in $sId } | ForEach-Object {
    [PSCustomObject]@{
        "PID" = $_.Id
        "Memory (active private)" = [int](Get-Counter -Counter "\Process($($_.Name))\Working Set - Private").CounterSamples.CookedValue / 1KB
    };
};

Ausgabe

  PID Memory (active private)
  --- -----------------------
16464                     164
25920                     164
11412                     264
12284                     712
18488                     712
20084                     712
 3660                   96952
10416                   96952
18424                   96952
 1408                   59000

PowerShell (eine andere Variante)

Hier ist eine weitere Variante in PowerShell mit einemForEach loop-Anweisungdas nur die gewünschten Werte mit Komma getrennt ausgibt und damit Ihrer vorhandenen Logik ähnelt, falls dies von Bedeutung ist.

$session = quser | Where-Object { ($_ -match 'Disc') } 2>&1;
$sId = $session | ForEach-Object  { ($_ -split '\s+')[2]};

$processes = Get-Process | Where-Object { $_.SessionId -in $sId };

foreach ($process in $processes) {
    $workingSet = (Get-Counter -Counter "\Process($($process.Name))\Working Set - Private").CounterSamples.CookedValue / 1KB;
    "$($process.Id), $([int]$workingSet)";
};

Ausgabe

16464, 164
25920, 164
11412, 264
12284, 728
18488, 728
20084, 728
3660, 97732
10416, 97732
18424, 97732
1408, 57576

Unterstützende Ressourcen

verwandte Informationen