.png)
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:
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-Counter
es muy lento, cada llamada en un bucle toma aproximadamente 1 segundo. Así que opté por utilizarGet-CimInstance -ClassName Win32_PerfRawData_PerfProc_Process
el conjunto de trabajo y luego hacerlo privado. – rinkert
Como lo destaca el OP, el rendimiento Get-Counter
no es tan óptimo como Get-CimInstance
cuando 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 WorkingSetPrivate
valores 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-Process
comando en unForEach-Object
bucle para iterar cada proceso devuelto y valores de propiedad. - Utiliza un
PSCustomObject
, para almacenarloPID
en un campo. - Utiliza
Get-Counter
, especificando el valorWorking Set - Private
a devolver, convirtiéndolo en an[int]
y luego dividiéndolo1 KB
en otro campo.
Los resultados devolverán una columna con PID
y otra columna que Memory (active private)
coincida con lo que ve en el Administrador de tareas y la Details
vista 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