PowerShell (el más óptimo)

PowerShell (el más óptimo)

Quiero obtener la memoria utilizada por sesión a través de una función de PowerShell. Sólo me interesan sesiones desconectadas. En el administrador de tareas, puedo ver la memoria utilizada por ID de sesión:

ingrese la descripción de la imagen aquí

Intenté obtener la memoria utilizada en MB en PowerShell mediante el siguiente script:

# 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"
}

Pero esto me da el siguiente resultado:

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

Que no se acerca a la memoria utilizada que figura en el administrador de tareas. ¿Cómo puedo obtener la RAM por sesión?

Actualizar Según la sugerencia de Vomit IT, hice esto, pero todavía me da valores incorrectos:

# 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"
}

resultado

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

Respuesta1

PowerShell (el más óptimo)

Gracias Vomit;) eso funciona como quería y me permitió ver el uso de RAM por sesión desconectada. Experimenté que Get-Counteres muy lento, cada llamada en un bucle toma aproximadamente 1 segundo. Así que opté por utilizar Get-CimInstance -ClassName Win32_PerfRawData_PerfProc_Processel conjunto de trabajo y luego hacerlo privado. – rinkert

Como lo destaca el OP, el rendimiento Get-Counterno es tan óptimo como Get-CimInstancecuando se recuperan valores de propiedad de la clase correspondiente. Esta variación de PowerShell incorpora esta consideración y ofrece un rendimiento mejorado si es importante para usted.

$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)";
};

Un problema

Tenga en cuenta que la solución anterior puede tener problemas para acceder a ciertos WorkingSetPrivatevalores de propiedad en la clase. Considere agregar lógica condicional para ignorar los valores nulos y cero para obtener un resultado más deseable, si es necesario.

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)"
    }
}

Otras soluciones

Incorporar esta solución a su tarea en consecuenciaresolverá este problema. Este ejemplo es una versión simple y precisa para coincidir con los valores mostrados en laAdministrador de tareascomo prefiera para RAM privada activa.

Básicamente esto...

  • Pone el Get-Processcomando en un ForEach-Objectbucle para iterar cada proceso devuelto y valores de propiedad.
  • Utiliza un PSCustomObject, para almacenarlo PIDen un campo.
  • Utiliza Get-Counter, especificando el valor Working Set - Privatea devolver, convirtiéndolo en an [int]y luego dividiéndolo 1 KBen otro campo.

Los resultados devolverán una columna con PIDy otra columna que Memory (active private)coincida con lo que ve en el Administrador de tareas y la Detailsvista de pestaña allí para esas propiedades.

Potencia 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
    };
};

Producción

  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 (otra variación)

Aquí hay otra variación en PowerShell usando unForEach declaración de bucleque genera solo los valores deseados separados por comas, de manera más similar a su lógica existente en caso de que esto sea importante.

$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)";
};

Producción

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

Recursos de apoyo

información relacionada