SEブログ

【PowerShell】オブジェクトを操作するコマンドを使う

 

こんにちは!SE ブログの相馬です。

 

 

 

今回は、コマンドレットでオブジェクトの操作について書きました。コマンドレットの実行で取得したオブジェクトをどうやって使えばよいのか、サンプルスクリプトを参考にしながら簡単に纏めてみました。

 

 

 

Select-Object

 

 

Select-Object コマンドレットはオブジェクトの一部を指定する事ができます。

 

オブジェクトの一部を選択する (Select-Object) | Microsoft

 

 

オブジェクトに対して、Select-Object コマンドレットを使えば、オブジェクトの中にあるデータにアクセスする事ができます。では早速ですが、Windows のサービス情報を取得して最初の 5 行目だけを選択してコンソールに表示してみます。

 

Get-Service | Select-Object -First 5


# 実行結果

Status Name DisplayName 
------ ---- ----------- 
Running AdobeARMservice Adobe Acrobat Update Service 
Stopped AfVpnService AfVpnService 
Stopped AJRouter AllJoyn Router Service 
Stopped ALG Application Layer Gateway Service 
Stopped AppIDSvc Application Identity

 

 

 

こんな感じで最初の Get-Service コマンドレットによってオブジェクト(ここではサービスの情報)が表示されます。そしてパイプラインを使い、次のコマンドレットでオブジェクトの中にあるものを必要な分だけ取り出して表示します。このオブジェクトというのは理解していない方はなかなか分かりにくいと思いますが、ここではサービスの情報という名の箱だと思ってください。

 

 

上の処理では Get-Service コマンドレットを実行するとサービスの一覧が表示されますよね。まずは、この一覧表が箱(オブジェクト)だと思ってください。そしてその箱の中にはサービスの名前やマシン名など、プロパティというものが入っています。ですので、サービスから必要なプロパティを指定してあげるようなイメージになります。

 

 

使い方としては、例えばこんなサンプルだと分かり易いかと思います。使いたいコマンドレットの実行結果のオブジェクトを、Get-Member に渡してあげるのです。そうすると、Get-Memger を使って Get-Service のプロパティやメソッドなどを調べる事ができます。こういう使い方で覚えてゆくと、コマンドレットで使えるプロパティやメソッドがすぐ分かりますので便利ですので是非活用すると良いでしょう。

 

Get-Service | Get-Member

TypeName: System.ServiceProcess.ServiceController

Name MemberType Definition 
---- ---------- ---------- 
...
ServiceName Property string ServiceName {get;set;} 
ServicesDependedOn Property System.ServiceProcess.ServiceController[] ServicesDependedOn {get;} 
...
StartType Property System.ServiceProcess.ServiceStartMode StartType {get;} 
Status Property System.ServiceProcess.ServiceControllerStatus Status {get;} 

 

 

 

で、これで使えるプロパティやメソッドなどが確認できました。次に「サービス名の一覧が欲しいな、あとサービスが開始しているとか停止しているとかの状態が欲しいな」とかを考えます。するとそれがプロパティなのか、メソッドなのかが分かります。ここではサービス名もステータスもプロパティになりますので、オブジェクトからプロパティを指定してあげれば良いのです。ですので以下のような書き方になります。

 

 

話は戻りますが、Select-Object はオブジェクトの一部を選択できるコマンドレットになります。オブジェクトの一部とはプロパティやメソッドなどを指します。

 

 

では次に Get-Service コマンドレットで取得されたオブジェクトに対して名前をステータスを指定して表示してみます。

 

Get-Service | Select-Object Name, Status


# 実行結果

Name Status
---- ------
AdobeARMservice Running
AfVpnService Stopped
AJRouter Stopped
ALG Stopped
AppIDSvc Stopped

 

 

 

話はそれますが、特定のサービスの状態だけ取得したい場合はどうしたら良いでしょうか?例えば WinRM のサービスが欲しいんだけど、サービス名が明確に分からない時は以下のように Get-Service に -Name オプションを付けて検索対象の文字列をダブルクオーテーションで囲ってあげれば良いのです。

 

Get-Service -Name "Win*"


# 実行結果

Status Name DisplayName 
------ ---- ----------- 
Running WinDefend Windows Defender Antivirus Service 
Running WinHttpAutoProx... WinHTTP Web Proxy Auto-Discovery Se...
Running Winmgmt Windows Management Instrumentation 
Running WinRM Windows Remote Management (WS-Manag...

 

 

 

以上、Select-Object の説明はここまでとしておきます。次は Where-Object の説明に進みます。

 

 

 

Where-Object

 

 

Where-Object コマンドレットは、コマンドレットで取得されたオブジェクトをフィルターする事ができます。

 

Where-Object コマンドレットの使用 | Microsoft TechNet

 

 

オブジェクトに対して、Where-Object コマンドレットを使えば、オブジェクトの中にあるデータをフィルターする事ができます。では早速見てみましょう。ここでは Windows のプロセスから CPU の分だけデータを表示したい場合についてです。

 

 

最初に Get-Process コマンドレットでオブジェクト(プロセス情報)を取得します。ここからパイプラインを使って、オブジェクトから欲しい情報を抜き出してみます。

 

Get-Process | Where-Object { $_.CPU -ge 10 }


# 実行結果

Handles NPM(K) PM(K) WS(K) CPU(s) Id SI ProcessName 
------- ------ ----- ----- ------ -- -- ----------- 
335 54 255724 260660 83.59 11304 1 chrome 
1825 75 71696 105848 48.94 14960 1 chrome 
538 54 118280 111132 18.94 15136 1 chrome 
413 38 75744 104548 13.78 15248 1 chrome 
1982 91 46224 65264 18.44 9460 1 explorer 
1479 276 278668 328420 67.05 1296 1 iexplore 
769 57 54104 63804 15.73 14244 1 OneDrive

 

 

 

また、Where-Object コマンドレットを複数使い、更にフィルターする事もできます。以下は、Get-Service コマンドレットで取得されたオブジェクトをパイプラインでつなぎ、Where-Object で app という文字列が含まれるサービスをフィルターし、パイプラインでつなぎ、サービスのステータスが停止しているものをフィルターしています。

 

Get-Service | Where-Object { $_.Name -like '*app*' } | Where-Object { $_.Status -eq 'Stopped' }


# 実行結果

Status Name DisplayName 
------ ---- ----------- 
Stopped AppIDSvc Application Identity 
Stopped AppMgmt Application Management 
Stopped AppReadiness App Readiness 
Stopped AppVClient Microsoft App-V Client 
Stopped AppXSvc AppX Deployment Service (AppXSVC) 
Stopped COMSysApp COM+ System Application 
Stopped dmwappushservice dmwappushsvc 
Stopped EntAppSvc Enterprise App Management Service

 

 

 

Where-Object の説明は以上です。次は Group-Object の説明に進みます。

 

 

Group-Object

 

 

Group-Object コマンドレットは、指定したプロパティを簡単にグループ化して、カテゴリに含まれるアイテム数を算出してくれます。

指定したプロパティが何件あるか簡単に算出してくれるのでアイテム数をすぐに算出したい時に便利なコマンドレットだと思います。

 

Group-Object コマンドレットの使用 | Microsoft TechNet

 

 

ここでは、Windows のイベントログ(システム)の直近 100 件を、Source のプロパティを元にグループ化してみます。実行結果を見ますと、Name というカラムが Source のプロパティで Name 毎にカテゴリー分けされて、Count で件数が表示されています。

 

Get-Eventlog system -newest 100 | Group-Object -Property Source


# 実行結果

Count Name Group 
----- ---- ----- 
1 EventLog {System.Diagnostics.EventLogEntry} 
9 Service Control Manager {System.Diagnostics.EventLogEntry, System.Diagnostics.EventLogEntry, Syst...
71 Microsoft-Windows-Kern... {System.Diagnostics.EventLogEntry, System.Diagnostics.EventLogEntry, Syst...
3 Microsoft-Windows-Time... {System.Diagnostics.EventLogEntry, System.Diagnostics.EventLogEntry, Syst...
9 DCOM {System.Diagnostics.EventLogEntry, System.Diagnostics.EventLogEntry, Syst...
1 WinRM {System.Diagnostics.EventLogEntry} 
1 Microsoft-Windows-User... {System.Diagnostics.EventLogEntry} 
1 Microsoft-Windows-Winl... {System.Diagnostics.EventLogEntry} 
1 VMnetuserif {System.Diagnostics.EventLogEntry} 
1 vmx86 {System.Diagnostics.EventLogEntry} 
1 Microsoft-Windows-WLAN... {System.Diagnostics.EventLogEntry} 
1 VMnetBridge {System.Diagnostics.EventLogEntry}

 

 

 

Group-Object の説明は以上です。次は Sort-Object の説明に進みます。

 

 

 

Sort-Object

 

 

Sort-Object コマンドレットは、コマンドレットで取得されたオブジェクトのデータを並び替える事ができます。

 

Sort-Object コマンドレットの使用 | Microsoft TechNet

 

 

ここでは、Windows のプロセスを CPU とプロセス名だけ指定して、CPU を元に降順にソートして最初の 10 件を表示しています。

 

Get-Process | Select-Object CPU, ProcessName | Sort-Object CPU -Descending | Select-Object -First 10


# 実行結果

CPU ProcessName 
--- ----------- 
321.6875 chrome 
252.0625 chrome 
142.078125 chrome 
117.546875 iexplore 
93.078125 chrome 
62.203125 powershell_ise 
59.8125 ImeBroker 
37.1875 audiodg 
35.859375 Lenovo.Modern.ImController.PluginHost.SettingsApp
30.734375 explorer

</pre>

&nbsp;

&nbsp;

&nbsp;

上の内容とは別にここでは、Windows のイベントログの最新 100 件のデータを Sort-Object で Source のみ指定して並び替えて、Group-Object で Source をカテゴリーにして表示しています。

&nbsp;
<pre>
Get-Eventlog system -newest 100 | Sort-Object Source | Group-Object -Property Source 

# 実行結果

Count Name Group
----- ---- -----
9 DCOM {System.Diagnostics.EventLogEntry, System.Diagnostics.EventLogEntry, Syst...
1 EventLog {System.Diagnostics.EventLogEntry}
71 Microsoft-Windows-Kern... {System.Diagnostics.EventLogEntry, System.Diagnostics.EventLogEntry, Syst...
3 Microsoft-Windows-Time... {System.Diagnostics.EventLogEntry, System.Diagnostics.EventLogEntry, Syst...
1 Microsoft-Windows-User... {System.Diagnostics.EventLogEntry}
1 Microsoft-Windows-Winl... {System.Diagnostics.EventLogEntry}
1 Microsoft-Windows-WLAN... {System.Diagnostics.EventLogEntry}
9 Service Control Manager {System.Diagnostics.EventLogEntry, System.Diagnostics.EventLogEntry, Syst...
1 VMnetBridge {System.Diagnostics.EventLogEntry}
1 VMnetuserif {System.Diagnostics.EventLogEntry}
1 vmx86 {System.Diagnostics.EventLogEntry}
1 WinRM {System.Diagnostics.EventLogEntry}

 

 


Sort-Object の説明は以上です。次は ForEach-Object の説明に進みます。

 

 

 

ForEach-Object

 

 

ForEach-Object コマンドレットは、コマンドレットで取得されたオブジェクトのデータを繰り返し処理する事ができます。

 

Foreach-Object コマンドレットの使用 | Microsoft TechNet

 

 

ここでは、C:\temp\log フォルダのディレクトリを Get-ChildItem コマンドレットでデータを取得し、3 日前以前のファイルを削除します。

 

  1. C:\temp\log を $purge_dir に代入
  2. 3 を $retention に代入
  3. Get-ChildItem コマンドレットで $purge_dir で指定したディレクトリのファイルを再帰的に取得
  4. Where-Object コマンドレットで最後に保存された日が (Get-Date).AddDays(-$retention) 、つまり 3 日前より前のオブジェクトを取得
  5. ForEach-Object コマンドレットでファイル名を取得し、削除を繰り返す

 

$purge_dir = "C:\temp\log"
$retention = 3

Get-ChildItem -File -Recurse $purge_dir | `
    Where-Object { $_.LastWriteTime -lt (Get-Date).AddDays(-$retention)} | `
        ForEach-Object { `
            $_.fullname | del -Force `
        }

# 実行結果は以下の画像を参照

 

 

 

削除前(まだ log1.txt ~ log5.txt があります。)

 

 

削除後(log1.txt ~ log5.txt が削除されました。)

 

 

 

 

以上となります。いかがでしょうか。

 

 

今回出てきたオブジェクトを操作するコマンドレットを組み合わせて使う事によって、色々な操作ができるようになると思います。例えば、ログファイルのローテーションで、古いファイルは削除したりする場合はこのような方法でできると思います。~日より前の古いファイルを自動的に削除したり移動したりする事ができるようになりますので、このような用途は使えますし便利だと思います。

 

 

では最後までお読みいただきありがとうございました!