.png)
Я хочу получить память, используемую для сеанса, через функцию PowerShell. Меня интересуют только отключенные сеансы. В диспетчере задач я могу увидеть память, используемую для сеанса ID:
Я попытался получить объем памяти, используемый в МБ, в PowerShell с помощью следующего скрипта:
# 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"
}
Но это дает мне следующий результат:
20, 481
21, 451
22, 670
23, 763
24, 949
Который далеко не соответствует используемой памяти, указанной в диспетчере задач. Как мне получить RAM на сеанс?
Обновлять Следуя предложению Vomit IT, я сделал это, но он все равно выдает мне неправильные значения:
# 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"
}
результат
20, 808288
22, 830872
23, 806404
24, 806312
25, 802892
решение1
PowerShell (наиболее оптимальный)
Спасибо Vomit ;) это работает так, как я хотел, и позволило мне увидеть использование оперативной памяти на отключенный сеанс. Я столкнулся с тем, что
Get-Counter
это очень медленно, каждый вызов в цикле занимает ~1 секунду. Поэтому я решил пойти с этимGet-CimInstance -ClassName Win32_PerfRawData_PerfProc_Process
и затем сделать рабочий набор приватным. – ринкерт
Как подчеркивает OP, производительность Get-Counter
не так оптимальна, как Get-CimInstance
при извлечении значений свойств из соответствующего класса. Эта вариация PowerShell учитывает это соображение, предлагая улучшенную производительность, если это важно для вас.
$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)";
};
Попался
Обратите внимание, что в приведенном выше решении могут возникнуть проблемы с доступом к определенным WorkingSetPrivate
значениям свойств в классе. Рассмотрите возможность добавления условной логики для игнорирования значений null и zero для получения более желательного вывода, если это необходимо.
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)"
}
}
Другие решения
Внедрение этого решения в вашу задачу соответствующим образомрешит эту проблему. Этот пример является простой версией и точным для соответствия значениям, показанным вДиспетчер задачкак вам больше нравится для активной частной оперативной памяти.
По сути это...
- Помещает
Get-Process
команду вForEach-Object
цикл для итерации каждого возвращенного процесса и значений свойств. - Использует
PSCustomObject
, сохраняяPID
в одном поле. - Использует
Get-Counter
, указываяWorking Set - Private
возвращаемое значение, приводя его к типу ,[int]
а затем делит его на1 KB
в другом поле.
Результаты вернут столбец с PID
и другой столбец с Memory (active private)
соответствующим тем, что вы видите в диспетчере задач, и Details
представление вкладок для этих свойств.
PowerShell
$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
};
};
Выход
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 (еще один вариант)
Вот еще один вариант PowerShell с использованиемForEach
оператор циклакоторый выводит только нужные значения, разделенные запятыми, что более похоже на вашу существующую логику, если это имеет значение.
$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)";
};
Выход
16464, 164
25920, 164
11412, 264
12284, 728
18488, 728
20084, 728
3660, 97732
10416, 97732
18424, 97732
1408, 57576