.png)
PowerShell 関数を使用して、セッションごとに使用されているメモリを取得したいと考えています。切断されたセッションのみに関心があります。タスク マネージャーでは、セッション ID ごとに使用されているメモリを確認できます。
次のスクリプトを使用して、PowerShell で使用されているメモリを MB 単位で取得しようとしました。
# 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
。必要に応じて、より望ましい出力を得るために、null 値とゼロ値を無視する条件付きロジックを追加することを検討してください。
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
1 つのフィールドに格納します。 - を使用し
Get-Counter
、Working Set - Private
返す を指定して にキャストし、それを別のフィールドで[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