
我想透過 PowerShell 函數取得每個會話使用的記憶體。我只對斷開連接的會話感興趣。在任務管理器中,我可以看到每個 sessionID 使用的記憶體:
我嘗試透過以下腳本取得PowerShell中MB中使用的mem:
# 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;)它按我想要的方式工作,並允許我查看每個斷開連接的會話的 RAM 使用情況。我確實經歷過速度
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
類別中的某些屬性值時可能會出現問題。如有必要,請考慮新增條件邏輯以忽略空值和零值,以獲得更理想的輸出。
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)"
}
}
其他解決方案
將此解決方案相應地納入您的任務中將解決這個問題。這個例子是一個簡單的版本,準確匹配中顯示的值工作管理員正如您喜歡的活動專用 RAM 一樣。
本質上這個...
- 將
Get-Process
命令放入循環中ForEach-Object
以迭代每個返回的進程和屬性值。 PSCustomObject
在儲存PID
一個欄位時使用, 。- 使用
Get-Counter
,指定Working Set - Private
要傳回的 ,將其轉換為 an[int]
,然後將其除以1 KB
另一個欄位。
結果將傳回一列和PID
另一列,該列與Memory (active private)
您從工作管理員和Details
這些屬性的標籤檢視中看到的內容相符。
電源外殼
$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