さて、今回の刺激元は以下です。
$shibayu36->blog; - サーバで動いているプロセスを知るために使ったコマンド
何かとBashさんとPowerShellさんは比較されるので同じような事をするにはってことで。
Get-ProcessコマンドレットとGet-WmiObject
PowerShellでProcess情報を取得するにあたり、次の2つがすぐに思いつくところです。
Get-Process #Alias = ps, gps
Get-WmiObject win32_process #Alias = gwmi
tasklist #!?
Get-ProcessとGet-WmiObject win32_processでは参照しているオブジェクトが違う
下記の通り、それぞれのコマンドレットは参照オブジェクトが違うため、取得出来る情報(プロパティ)にも差があります。
Get-Process
cmdでいうtasklist、Bashでいうpsのコマンドレット版で、.NETのSystem.Diagnostics.Processオブジェクトを利用しています。
Get-WmiObject win32_process
Windows Management Instrumentation(WMI)に含まれる、Win32_Processオブジェクトを利用しています。
tasklist
ごめんなさいしましょう (汗
取得できる情報(プロパティ)の詳細
Get-Memberコマンドレットでそれぞれを参照していただくと分かります。
まずは、みんな大好きGet-Processから。
#Get-Process | Get-Memberではメソッドも出るためPropertyに制限しています。
Get-Process | Get-Member -MemberType Property
実行結果は、以下です。 (PowerShell V3.0で行っています。)
PS C:\> Get-Process | Get-Member -MemberType Property | select Name,Definition | Format-Table -AutoSize
Name Definition
---- ----------
BasePriority int BasePriority {get;}
Container System.ComponentModel.IContainer Container {get;}
EnableRaisingEvents bool EnableRaisingEvents {get;set;}
ExitCode int ExitCode {get;}
ExitTime datetime ExitTime {get;}
Handle System.IntPtr Handle {get;}
HandleCount int HandleCount {get;}
HasExited bool HasExited {get;}
Id int Id {get;}
MachineName string MachineName {get;}
MainModule System.Diagnostics.ProcessModule MainModule {get;}
MainWindowHandle System.IntPtr MainWindowHandle {get;}
MainWindowTitle string MainWindowTitle {get;}
MaxWorkingSet System.IntPtr MaxWorkingSet {get;set;}
MinWorkingSet System.IntPtr MinWorkingSet {get;set;}
Modules System.Diagnostics.ProcessModuleCollection Modules {get;}
NonpagedSystemMemorySize int NonpagedSystemMemorySize {get;}
NonpagedSystemMemorySize64 long NonpagedSystemMemorySize64 {get;}
PagedMemorySize int PagedMemorySize {get;}
PagedMemorySize64 long PagedMemorySize64 {get;}
PagedSystemMemorySize int PagedSystemMemorySize {get;}
PagedSystemMemorySize64 long PagedSystemMemorySize64 {get;}
PeakPagedMemorySize int PeakPagedMemorySize {get;}
PeakPagedMemorySize64 long PeakPagedMemorySize64 {get;}
PeakVirtualMemorySize int PeakVirtualMemorySize {get;}
PeakVirtualMemorySize64 long PeakVirtualMemorySize64 {get;}
PeakWorkingSet int PeakWorkingSet {get;}
PeakWorkingSet64 long PeakWorkingSet64 {get;}
PriorityBoostEnabled bool PriorityBoostEnabled {get;set;}
PriorityClass System.Diagnostics.ProcessPriorityClass PriorityClass {get;set;}
PrivateMemorySize int PrivateMemorySize {get;}
PrivateMemorySize64 long PrivateMemorySize64 {get;}
PrivilegedProcessorTime timespan PrivilegedProcessorTime {get;}
ProcessName string ProcessName {get;}
ProcessorAffinity System.IntPtr ProcessorAffinity {get;set;}
Responding bool Responding {get;}
SessionId int SessionId {get;}
Site System.ComponentModel.ISite Site {get;set;}
StandardError System.IO.StreamReader StandardError {get;}
StandardInput System.IO.StreamWriter StandardInput {get;}
StandardOutput System.IO.StreamReader StandardOutput {get;}
StartInfo System.Diagnostics.ProcessStartInfo StartInfo {get;set;}
StartTime datetime StartTime {get;}
SynchronizingObject System.ComponentModel.ISynchronizeInvoke SynchronizingObject {get;set;}
Threads System.Diagnostics.ProcessThreadCollection Threads {get;}
TotalProcessorTime timespan TotalProcessorTime {get;}
UserProcessorTime timespan UserProcessorTime {get;}
VirtualMemorySize int VirtualMemorySize {get;}
VirtualMemorySize64 long VirtualMemorySize64 {get;}
WorkingSet int WorkingSet {get;}
WorkingSet64 long WorkingSet64 {get;}
次に、Get-WmiObject win32_processを見てみましょう。
Get-WmiObject win32_process | Get-Member -MemberType Property
実行結果は、以下です。 (PowerShell V3.0で行っています。)
PS C:\> Get-WmiObject win32_process | Get-Member -MemberType Property | select Name, Definition | Format-Table -AutoSize
Name Definition
---- ----------
Caption string Caption {get;set;}
CommandLine string CommandLine {get;set;}
CreationClassName string CreationClassName {get;set;}
CreationDate string CreationDate {get;set;}
CSCreationClassName string CSCreationClassName {get;set;}
CSName string CSName {get;set;}
Description string Description {get;set;}
ExecutablePath string ExecutablePath {get;set;}
ExecutionState uint16 ExecutionState {get;set;}
Handle string Handle {get;set;}
HandleCount uint32 HandleCount {get;set;}
InstallDate string InstallDate {get;set;}
KernelModeTime uint64 KernelModeTime {get;set;}
MaximumWorkingSetSize uint32 MaximumWorkingSetSize {get;set;}
MinimumWorkingSetSize uint32 MinimumWorkingSetSize {get;set;}
Name string Name {get;set;}
OSCreationClassName string OSCreationClassName {get;set;}
OSName string OSName {get;set;}
OtherOperationCount uint64 OtherOperationCount {get;set;}
OtherTransferCount uint64 OtherTransferCount {get;set;}
PageFaults uint32 PageFaults {get;set;}
PageFileUsage uint32 PageFileUsage {get;set;}
ParentProcessId uint32 ParentProcessId {get;set;}
PeakPageFileUsage uint32 PeakPageFileUsage {get;set;}
PeakVirtualSize uint64 PeakVirtualSize {get;set;}
PeakWorkingSetSize uint32 PeakWorkingSetSize {get;set;}
Priority uint32 Priority {get;set;}
PrivatePageCount uint64 PrivatePageCount {get;set;}
ProcessId uint32 ProcessId {get;set;}
QuotaNonPagedPoolUsage uint32 QuotaNonPagedPoolUsage {get;set;}
QuotaPagedPoolUsage uint32 QuotaPagedPoolUsage {get;set;}
QuotaPeakNonPagedPoolUsage uint32 QuotaPeakNonPagedPoolUsage {get;set;}
QuotaPeakPagedPoolUsage uint32 QuotaPeakPagedPoolUsage {get;set;}
ReadOperationCount uint64 ReadOperationCount {get;set;}
ReadTransferCount uint64 ReadTransferCount {get;set;}
SessionId uint32 SessionId {get;set;}
Status string Status {get;set;}
TerminationDate string TerminationDate {get;set;}
ThreadCount uint32 ThreadCount {get;set;}
UserModeTime uint64 UserModeTime {get;set;}
VirtualSize uint64 VirtualSize {get;set;}
WindowsVersion string WindowsVersion {get;set;}
WorkingSetSize uint64 WorkingSetSize {get;set;}
WriteOperationCount uint64 WriteOperationCount {get;set;}
WriteTransferCount uint64 WriteTransferCount {get;set;}
__CLASS string __CLASS {get;set;}
__DERIVATION string[] __DERIVATION {get;set;}
__DYNASTY string __DYNASTY {get;set;}
__GENUS int __GENUS {get;set;}
__NAMESPACE string __NAMESPACE {get;set;}
__PATH string __PATH {get;set;}
__PROPERTY_COUNT int __PROPERTY_COUNT {get;set;}
__RELPATH string __RELPATH {get;set;}
__SERVER string __SERVER {get;set;}
__SUPERCLASS string __SUPERCLASS {get;set;}
何が違うの?
何が違うか分からない?
ですよね~、正直簡単に利用できるのは、Get-Processです。
理由としては以下です。
- Get-Processは、デフォルトで表示されるプロパティがあるためTable表示で利用しやすい。(※)
- Get-Processの方がコマンド短い!! (psとかgps)
- Get-Processは自分のユーザープロセスは制限ないが、他プロセスはUACの昇格が必要
※Get-WmiObjectは、デフォルトをもたないため全て表示しようとするため、Format-Listです。
※Get-ProcessとGet-WmiObjectでは、Get-WmiObjectではデフォルトの出力が制限されずFormat-Tableでは表示がきれてしまうという…。
2のコマンドが短い = 利用しやすいということで大事です。
少なくとも、Get-WmiObjectでは、表形式で一覧を見ようと思ったときにはSelect-Objectで制限しないと表示もままならない訳で、これは辛いかと思っています。
ただし、両者で、出来ることは似通っています。(当然違いも有りますが)
要は、Select-ObjectとFormat-Tableで指示をすればいいのですが、デフォルトで指示しなくても見れるというのはシェル実行時などには大事な気がします。
お題に挑戦
今回のお題で違いなどを見ていきましょう。
お題のそれぞれに、Get-ProcessとGet-WmiObjectで取り組んで見ます。
必ずUAC権限昇格して行ってください。(権限昇格しないとUser Processの情報しか取得できません)
1. 動いているプロセスを知りたい
Get-Processの場合
対抗心を燃やして……psで…!!
※個人的には、Get-Processを推奨します。
#Get-Processと同一
ps
簡単ですね。タスクマネージャーのような感じででます。(一部違いますが)
Handles NPM(K) PM(K) WS(K) VM(M) CPU(s) Id ProcessName
------- ------ ----- ----- ----- ------ -- -----------
66 7 1164 1640 64 0.48 2344 ATFSVR26
139 11 1804 2900 89 0.11 540 atieclxx
100 6 800 884 25 0.02 860 atiesrxx
122 13 4436 1340 90 0.94 144 ATOK26IB
115 10 8028 9532 38 148.65 6920 audiodg
149 14 2396 3968 71 0.06 1548 BingDesktopUpdater
848 96 92512 10776 888 17.77 5580 CCC
123 11 3864 12500 98 0.08 4720 conhost
496 26 10676 5444 425 0.41 5300 CSISYN~1
430 13 1944 2444 66 3.03 452 csrss
397 25 3452 19680 321 146.58 552 csrss
346 20 5708 10612 81 0.20 1648 dasHost
87 7 1684 3184 34 0.02 3892 dllhost
300 29 36684 61020 390 1,623.00 996 dwm
572 59 16212 45328 208 2.70 436 explorer
1999 1897 99956 475056 1199 93.94 3268 explorer
Get-WmiObjectの場合
Get-Processと同じような出力を目指してみましょう。
Get-WmiObject win32_process `
| select Handles,
QuotaNonPagedPoolUsage,
QuotaPagedPoolUsage,
WorkingSetSize,
VirtualSize,
ProcessId,
Name `
| sort Name `
| Format-Table -AutoSize
……長いです。
しかも、CPU %やProcessor Timeが出てません。
※とはいってもGet-ProcessのCPUもいわゆるタスクマネージャーのようなCPUではなくProcessorTimeなのですが…
Handles QuotaNonPagedPoolUsage QuotaPagedPoolUsage WorkingSetSize VirtualSize ProcessId Name
------- ---------------------- ------------------- -------------- ----------- --------- ----
66 8 128 1695744 67633152 2344 ATFSVR26.EXE
139 12 159 3018752 93044736 540 atieclxx.exe
100 7 41 962560 25735168 860 atiesrxx.exe
122 13 168 1384448 94855168 144 ATOK26IB.EXE
107 10 80 9773056 39284736 6920 audiodg.exe
143 14 118 4059136 74346496 1548 BingDesktopUpdater.exe
854 96 857 3923968 931344384 5580 CCC.exe
496 26 707 5652480 445333504 5300 CSISYN~1.EXE
431 13 176 2498560 69406720 452 csrss.exe
404 26 715 20508672 344805376 552 csrss.exe
346 20 153 10895360 85270528 1648 dasHost.exe
87 7 63 3301376 35373056 3892 dllhost.exe
274 29 779 64684032 410939392
動いているプロセスの関係も含めて知りたい
とりあえずどんな感じに実行されているかサマリーを知りたい時は以下のコマンド。
Get-Processの場合
psにFileVersionInfoスイッチを指定するだけです。
※個人的には、Get-Processを推奨します。
#Get-Process -FileVersionInfo と同一
ps -FileVersionInfo
上記の-FileVersionInfoスイッチを付けると、参照先がTypeName: System.Diagnostics.FileVersionInfoに変わります。
そのため、取得できるPropertyも変わるのです。
短いProcess名がデフォルトではでないので、selectで指定してあげると見やすくなります。
ps -FileVersionInfo `
| select productversion, fileVersion, FileName, InternalName
出力例です。
PS C:\> ps -FileVersionInfo | select productversion, fileVersion, FileName, InternalName
ProductVersion FileVersion FileName InternalName
-------------- ----------- -------- ------------
26.0 26.0 C:\Program Files (x86)\JustSyst... ATFSVR26
6.14.11.1126 6.14.11.1126 C:\Windows\system32\atieclxx.exe ATIECLXX.EXE
6.14.11.1126 6.14.11.1126 C:\Windows\system32\atiesrxx.exe ATIESRXX.EXE
26.0 26.0 C:\Program Files (x86)\JustSyst... ATOKIB26
Format-Tableでは切れてしまうので、Format-Listの方がいいですね。
PS C:\> ps -FileVersionInfo | select productversion, fileVersion, FileName, InternalName| Format-List
ProductVersion : 26.0
FileVersion : 26.0
FileName : C:\Program Files (x86)\JustSystems\ATOK26\ATFSVR26.EXE
InternalName : ATFSVR26
ProductVersion : 6.14.11.1126
FileVersion : 6.14.11.1126
FileName : C:\Windows\system32\atieclxx.exe
InternalName : ATIECLXX.EXE
残念ながら、Get-ProcessではCommandLineでの実行引数を取れません。
実行引数を参照するには、Get-Processではなくwmiを参照する必要があります。
Get-WmiObjectの場合
上記の実行引数以外はGet-Processの方が楽なのですが…
※CommandLine以外は端折ります><
ソースもとにあった、コマンドの引数とかも表示したい時にwmiを利用します。
Get-WmiObject win32_processには、commandLineプロパティがあるので、ここで実行引数を表示させることができます。
Get-WmiObject win32_process | select caption, commandLine
出力結果です。(分かり易いsvchostで)
PS C:\Windows\system32> Get-WmiObject win32_process | select caption, commandLine
caption commandLine
------- -----------
svchost.exe C:\Windows\system32\svchost.exe -k LocalService
svchost.exe C:\Windows\System32\svchost.exe -k LocalSystemNetworkRestricted
atieclxx.exe atieclxx
svchost.exe C:\Windows\system32\svchost.exe -k NetworkService
spoolsv.exe C:\Windows\System32\spoolsv.exe
svchost.exe C:\Windows\system32\svchost.exe -k LocalServiceNoNetwork
svchost.exe C:\Windows\system32\svchost.exe -k apphost
メモリやCPUを消費しているプロセスを知る
はい、これが曲者です。というか、CPU %をイメージすると曲者です。
それ以外は、好きなようにPropertyを指定していただければ…
並び順ですが、基本的には、 | パイプでつないで、sortコマンドレット(Sort-Object)を利用することで、並び替えを指示できます。
-Descendingスイッチで逆順に並びます。(昇順)
取得結果の数制限は、パイプでつないで、selectコマンドレット(Select-Object)で -Firstや-Lastスイッチで頭のいくつという指示ができます。
例:-First 1で最初の1つ
Get-Processの場合
※個人的には、Get-Processを推奨します。
以下のコマンドでvmプロパティの昇順に、最初の10個を指定しています。
#Get-Process | sort vm -Descending | select -First 10 と同一
ps `
| sort vm -Descending `
| select -First 10
出力結果です。
PS C:\Windows\system32> ps | sort vm -Descending | select -First 10
Handles NPM(K) PM(K) WS(K) VM(M) CPU(s) Id ProcessName
------- ------ ----- ----- ----- ------ -- -----------
2022 3557 109576 134656 1634 213.72 3268 explorer
762 41 16456 13008 1521 1052 svchost
878 86 178436 150416 1261 51.40 768 powershell_ise
575 84 695064 384908 1073 3,848.73 4724 opera
701 66 164804 172380 1047 24.45 3512 powershell_ise
998 107 318592 301196 1047 4,319.28 6540 krile
320 1678 10984 19924 970 263.03 732 taskhostex
397 32 10348 11000 961 3388 svchost
879 96 91956 5472 888 28.67 5580 CCC
230 31 22056 19552 668 368.43 1780 opera_plugin_wrapper
表示順は変わりますが、以下も同じ結果です。
vmプロパティの降順に、最後の10個を指定しています。
#Get-Process | sort vm | select -Last 10 と同一
ps | sort vm | select -Last 10
出力結果です。
PS C:\Windows\system32> ps | sort vm | select -Last 10
Handles NPM(K) PM(K) WS(K) VM(M) CPU(s) Id ProcessName
------- ------ ----- ----- ----- ------ -- -----------
230 31 22056 19552 668 368.43 1780 opera_plugin_wrapper
874 96 91920 5512 887 28.67 5580 CCC
389 32 10224 10932 960 3388 svchost
323 1680 10984 20268 971 263.03 732 taskhostex
997 107 317016 299732 1047 4,325.81 6540 krile
701 66 164804 172380 1047 24.45 3512 powershell_ise
575 84 687192 377112 1065 3,849.87 4724 opera
872 88 181736 158228 1299 57.81 768 powershell_ise
763 41 16456 13008 1521 1052 svchost
2041 3563 110040 135560 1638 214.16 3268 explorer
さて、冒頭で触れたとおり、Get-Processでは、CPU %ではなく、Processor Timeしか取得できません。
そのため、CPUが…という時には見にくいです。
CPU時間ではなく%を取得するには
以下の2つが候補としてあります。
Get-Counter
Get-WmiObject Win32_PerfFormattedData_PerfProc_Process
算出ロジック
中々詳しい情報が、ローマの偉人ググレカス様に伺っても出ないので、msdnと自身で検証を重ねました。
Get-Counterは、論理CPUコア(Core-i7 860の場合 物理コア4のHTなので8です)でCookedValueを割ることで、各プロセス%が算出できます。
一方の、Get-WmiObject Win32_PerfFormattedData_PerfProc_Processは、物理CPUコア((Core-i7 860の場合 物理コア4なので4)でPercentProcessorTimeを割ることで、各プロセス%が算出できます。
ただし、検証している中で、Get-WmiObjectは、数値が実行毎にばらつきが出るようです。(謎 / 某Script Guyさんも同じような指摘を…)
一方のGet-Counterは、比較的安定しているようなので、個人的にはGet-Counterが望ましいのかと判断しています。
さっくり、CPU %を取得するコマンドを書いてみました。
Get-Counterの場合
環境変数のNUMBER_OF_PROCESSORSでCookedValueを割って、それを[int]型に型変換することで小数点を取り払っています。
($env:NUMBER_OF_PROCESSORSで環境変数の論理CPUコアにアクセスできます)
今回の場合、論理CPU =8で割っています。
(Get-Counter "\Process(*)\% Processor Time").CounterSamples `
| select InstanceName,
@{label="CPU %";expression={$_.CookedValue / $Env:NUMBER_OF_PROCESSORS -as [int]}} `
| where {$_.InstanceName -ne "idle" -and $_.InstanceName -ne "_total"} `
| sort "CPU %" -Descending `
| select -First 10 `
| Format-Table -AutoSize
出力結果です。
InstanceName CPU %
------------ -----
iexplore 28
iexplore 5
justonlineupdate 0
ccc 0
jslmaui 0
mom 0
csisyn~1 0
everything-1.2.1.421b 0
magicformation 0
skydrive 0
Get-WmiObjectの場合
ロジックは同じです。
環境変数のNUMBER_OF_PROCESSORSでPercentProcessorTimeを割って、それを[int]型に型変換することで小数点を取り払っています。
($env:NUMBER_OF_PROCESSORSにある環境変数の論理CPUコアを/2してHTを除く物理CPU数としています。)
今回の場合、物理CPU = 4で割っています。
Get-WMIObject -Query "Select * From Win32_PerfFormattedData_PerfProc_Process Where PercentProcessorTime >= 0" `
| where {$_.Name -ne "_Total" -and $_.Name -ne "Idle"} `
| sort PercentProcessorTime -Descending `
| select -First 10 `
CreatingProcessID,
Name,
PercentProcessorTime,
@{label="CPU / Core";expression = {$_.PercentProcessorTime / ($env:NUMBER_OF_PROCESSORS / 2 )}},
| Format-Table
出力結果です。
CreatingProcessID Name PercentProcessorTime CPU / Core
----------------- ---- -------------------- ----------
1632 iexplore 24 6
3268 powershell_ise 12 3
640 svchost#7 0 0
640 svchost#6 0 0
640 svchost#5 0 0
640 svchost#4 0 0
640 svchost#3 0 0
640 svchost#2 0 0
640 svchost#1 0 0
640 svchost 0 0
同時実行でないので、Gt-CounterとGet-WmiObjectには差異があります。
例え同時実行しても結果が違うことがままったのですが……。
困ったものです…が、ここではタスクマネージャーとにらめっこして近かったのがGet-Coutnerでした。
よって、Get-Counterを採用します。(海外フォーラムでも、比較してこの結論に至ったところがありましたが……さて)
まとめ と おまけ
まとめ
さて、元ソースの内容は、PowerShellでも簡単に見れることが分かるかと思います。
Get-WmiObjectを利用すると、とても冗長ですが、Get-Processを使えば簡単ですね。
Propertyの指定に、幾分冗長的な部分はありますが……ps | gmなどで確認してください。※
※Get-Process | Get-MemberのAliasです。
おまけ
Get-ProcessとGet-WmiObject win32_processにGet-Counterで得たCPU %を組み込んでみました。
function化はさせていないのですが、ここまで読まれた方には不要かと…。
参考程度にどうぞ。
Get-ProcessにGet-CouterのCPU%をプロパティとして追加する
$PerfCounter = (Get-Counter "\Process(*)\% Processor Time").CounterSamples `
| select InstanceName,
@{label="CPU %";expression={($_.CookedValue / $Env:NUMBER_OF_PROCESSORS) -as [int]}} `
| where {$_.InstanceName -ne "idle"} `
| where {$_.InstanceName -ne "_total"}
Get-Process `
| ForEach-Object {
#Join to obtain Get-Counter "CPU %" matching by InstanceName and ProcessName
$NameStr = $_.ProcessName
$processCPU = $PerfCounter | where{$_.InstanceName -match $NameStr} | select "CPU %" | sort -Unique
#Format CPU(s)
$CPU = "{0:0.00}" -F $_.CPU
#Create new Property to show all in one
New-Object PSObject -Property @{
Handles = $_.Handles
"NPM(K)" = [int]($_.NonpagedSystemMemorySize / 1KB )
"PM(K)" = [int]($_.PagedMemorySize / 1KB)
"WS(K)" = [int]($_.WorkingSet / 1KB)
"VM(M)" = [int]($_.VirtualMemorySize / 1MB)
"CPU(s)" = $CPU
"PerfCPU %" = $processCPU.'CPU %'
Id = $_.Id
ProcessName = $_.ProcessName
}
} `
| sort "PerfCPU %" -Descending `
| Format-Table Handles,"NPM(K)","PM(K)","WS(K)","VM(M)","CPU(s)","PerfCPU %",Id,ProcessName -AutoSize
出力結果(抜粋)です。
Handles NPM(K) PM(K) WS(K) VM(M) CPU(s) PerfCPU % Id ProcessName
------- ------ ----- ----- ----- ------ --------- -- -----------
851 81 174484 216312 1146 4.62 2 8184 powershell_ise
607 59 112424 103364 424 78.25 2 5232 GOM
1112 118 150296 173608 593 900.02 1 6400 iexplore
629 46 55076 7532 415 160.93 1 5820 iexplore
515 30 12248 4572 179 3.18 1 5784 iexplore
629 47 16720 29316 294 14.84 1 1632 iexplore
974 118 104024 118452 569 3297.99 1 3184 iexplore
147 12 2024 2012 71 0.06 0 2392 vmware-usbarbitrator64
Get-WmiObjectにGet-CouterのCPU%をプロパティとして追加する
$PerfCounter = (Get-Counter "\Process(*)\% Processor Time").CounterSamples `
| select InstanceName,
@{label="CPU %";expression={($_.CookedValue / $Env:NUMBER_OF_PROCESSORS) -as [int]}} `
| where {$_.InstanceName -ne "idle"} `
| where {$_.InstanceName -ne "_total"}
Get-WmiObject win32_process `
| ForEach-Object {
$Nametemp = $_.Name
$NameStr = $Nametemp.Substring(0,$Nametemp.Length-4)
$processName = $PerfCounter.InstanceName | where{$_ -match $NameStr} | select -Unique
$processCPU = $PerfCounter | where{$_.InstanceName -match $NameStr} | select "CPU %" | sort -Unique
New-Object PSObject -Property @{
Handles = $_.Handles
"NPM(K)" = $_.QuotaNonPagedPoolUsage
"PM(K)" = $_.QuotaPagedPoolUsage
"WS(K)" = [int]($_.WorkingSetSize / 1KB)
"VM(M)" = [int]($_.VirtualSize / 1MB)
"PerfCPU %" = $processCPU.'CPU %'
ProcessId = $_.ProcessId
ProcessName = $_.Name
}
} `
| sort "PerfCPU %" -Descending `
| Format-Table Handles,"NPM(K)","PM(K)","WS(K)","VM(M)","PerfCPU %",ProcessId,ProcessName -AutoSize
出力結果(抜粋)です。
Handles NPM(K) PM(K) WS(K) VM(M) PerfCPU % ProcessId ProcessName
------- ------ ----- ----- ----- --------- --------- -----------
607 59 523 103300 424 1 5232 GOM.exe
396 32 108 10948 960 0 3388 svchost.exe
886 97 862 1884 892 0 5580 CCC.exe
65 9 140 1264 71 0 5532 JSLMAUI.exe
300 34 373 1672 588 0 5500 MOM.exe
496 26 707 5268 425 0 5300 CSISYN~1.EXE
簡単な説明
Get-Counterでは、ProcessNameしかとれず、ProcessIdが取れません。
そこで、Get-ProcessやGet-WmiObjectで取得したProcessNameと、Get-Counterで取得したProcessNameの合致を確認してそのProcessのCPU %としてGet-Coutnerの取得結果を紐づけています。
これをGet-Processから ForEach-Objectでつないだ{}内で各Processに対して行っています。
最後に、紐づけたCPU %をGet-ProcessやGet-WiObjectで、一覧結果表示できるように新しいPropertyを追加しています。
New-Object -Propertyは、汎用的に利用できる手段なので非常に有用ですね。