tech.guitarrapc.cóm

Technical updates

PowerShellの-PassThruパラメータについて

前回の第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-ServiceStart-Processと同様に、通常は実行したサービスの状態を返しませんが-PassThruを指定すると返しています。

Start-Service -Name 'wuauserv' -PassThru

Out-GridViewの例

PowerShell 3.0での-PassThruの例として以下の記事があります。

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.

参考資料

牟田口先生からコメントいただきました

牟田口大介さん (@mutaguchi)