前回の第1回シェル芸への挑戦で牟田口先生から以下の別解をいただきました。
牟田口大介さん (@mutaguchi) 1月 24, 2013
-PassThre
パラメータ…コレがようやく理解出来たので記事にします。さらにPowerShell 3.0では-PassThru
も強化されていますのでぜひぜひ。
そもそも-PassThruって何するの
一番分かりやすい説明はコレでしょうか。
Hey, Scripting Guy! Blog - Use the PowerShell Passthru Parameter and Get Back Objects
以下の記述があります。
So, what does passthru do for me? For example, there are many Windows PowerShell cmdelts that simply work, and they do not return any data. An example is the Start-Process cmdlet. Here is an example of using the Start-Process cmdlet to start Notepad. Notice, that the line following the command is empty~中略~ If I add the passthru switched parameter to the end of the command, a Process object returns to the Windows PowerShell console.
要約すると、「返戻値を持たないコマンドレットであっても、当該コマンドのオブジェクトを返してくれる」ということです。
-PassThruパラメータの指定方法
コマンドの最後にパラメータを付けます。-PassThru
パラメ-タは引数を持たないスイッチなので、以下のような要領で使用します。
Start-Service -Name 'wuauserv' -PassThru
-PassThru
パラメータを指定しないとこうですね。
Start-Service -Name 'wuauserv'
-PassThruがやっていること
以下のような記事があります。
Powershell: how to implement standard switches?
[CmdltBinding()]
attributeを使わずに-PassThru
を実装するにはという内容です。 興味深いのでよろしければ。
-PassThruパラメータをつけると出力がどう変わるの?
コマンドによって、出力が変化します。 ここでは、以下のコマンドでの出力の違いを紹介します。
Start-Process Start-Service Out-GridView Compare-Object Add-Member
Start-Processの例
Hey, Scripting Guy! Blogで例に挙げられているStart-Process
コマンドレットの事例です。 Start-Process
は、プロセスを開始するのみで返戻値を持ちません。 コマンドを-PassThru
パラメータなしで実行すると返戻値を持たないことが分かります。
Start-Process notepad
-PassThru
パラメータをコマンドの末尾に付けることで、プロセスを実行しつつ、自身のProcessオブジェクトを返してくれます。
Start-Process notepad -PassThru
-PassThru
する事でプロセスの実行結果を返してパイプラインにつなげるため、Get-Process
などで取得する事の労力が省かれ非常に有益となります。
たとえば、プロセスを実行してから、そのプロセスの完了をWait-Process
で待機する間に処理を挟むなどです。
$firefox = Start-Process firefox -PassThru # {...入れたい処理....} Wait-Process -Id ($firefox.Id)
Start-Serviceの例
Start-Service
ではどうなるのでしょうか。Start-Service
もStart-Process
と同様に、通常は実行したサービスの状態を返しませんが-PassThru
を指定すると返しています。
Start-Service -Name 'wuauserv' -PassThru
Out-GridViewの例
PowerShell 3.0での-PassThru
の例として以下の記事があります。
Out-Grid
で-PassThru
を指定すると選んだ項目を返してくれるとあります。
たとえば、現在のプロセス一覧をGUI表示し、選んだ結果を返す例です。まずは-PassThru
なしで実行してみますが、ただ表示するだけでプロセスを選んでいても返されません。
Get-Process | Out-GridView
一方、Out-GridView
に-PassThru
パラメータを指定するとOKボタンが出来ています。OKを押すと、その際選択していたプロセス情報が標準出力に返されます。
Get-Process | Out-GridView -PassThru
Out-GridView
で選択していたプロセスが標準出力に返されました。
Compare-Objectの例
そして、今回のきっかけとなったCompare-Object
です。
出力が値だけに変化したことが分かります。-PassThru
することで扱いやすくなりますね。
Add-Memberの例
PSObjectでないオブジェクトに対して、メンバー追加など拡張するのがAdd-Member
です。NotePropertyやScriptMethodなどを追加出来るので便利なコマンドです。
Add-Member
する際は、自身が-is PSObejct
ならいいのですが、そうでない場合にはPSObjectでラップしてあげる必要があります。そこで-PassThru
パラメータです。
Add-Member
実行時に-PassThru
を付けることで、Add-Memeber
で作られたPSObjectを自身に返します。この結果、Add-MeMber
の対象オブジェクトを拡張することが可能になります。
一方Add-Member
実行時に-PassThru
を付けないとどうなるでしょうか。Start-Process
などと同様Add-Member
コマンドレットは実行結果PSObjectを返さないためAdd-Member
に失敗します。
サンプルとして、NotePropertyとしてComment
プロパティを値"Hello"
で追加してみます。
-PassThruがない場合
$sample = "ABC" $sample -is [PSObject] $sample | Add-Member NoteProperty Comment "Hello" -Force $sample.comment
結果はNotePropertyが表示できません。(Falseは、-is [PSObject]
の結果です。)
False
Get-Memeber
でプロパティを確認すると…NotePropertyの追加に失敗しています。
$sample | Get-Member -MemberType Properties | Format-Table -AutoSize TypeName: System.String Name MemberType Definition ---- ---------- ---------- Length Property int Length {get;}
-PassThruがある場合
$sample = "ABC" $sample -is [PSObject] $Sample = $sample | Add-Member NoteProperty Comment "Hello" -Force -PassThru $sample.comment
結果はNotePropertyが表示出来ました。(Falseは、-is [PSObject]
の結果です。)
False Hello
Get-Memeber
でプロパティを確認すると…しっかりNotePropertyの追加ができています。
$sample | Get-Member -MemberType Properties | Format-Table -AutoSize TypeName: System.String Name MemberType Definition ---- ---------- ---------- Comment NoteProperty System.String Comment=Hello Length Property int Length {get;}
-PassThruパラメータになれよう!!
もっともな一言がPowerShell 3.0 -PassThruにありました。習うより慣れろってことで。
The best way to learn about PowerShell's -PassThru parameter is by experimenting with examples such as Stop-Process or Out-GridView.
参考資料
- Windows PowerShell: オブジェクトをカスタマイズするさまざまな方法
- FilterとPassThruの使い方 Windows Server 2012のWDACで使用できるPowerShellコマンドレット (Add-OdbcDsn) について