Windows PowerShell: オブジェクトをカスタマイズするさまざまな方法

実際のところ、最終成果物がカスタム オブジェクトであれば、その作成方法は、どのようなものでもかまいません。

Don Jones

最近、私は Windows PowerShell を使用するための 12 個のベスト プラクティスの概要を紹介したブログ記事 (英語) を執筆しました。12 番目のベスト プラクティスでは、スクリプトや関数で、テキストではなくオブジェクトを出力することを推奨しています。このブログ記事では、Write-Host コマンドレットを使用しているときには、少し立ち止まって、処理内容を検討することにも言及しています。Write-Host コマンドレットで行っているのは、テキストの生成です。

このブログ記事の公開後間もなく、読者の方から、実際にカスタム オブジェクトを作成するのに使用したコードについての問い合わせがあり、このようなアプローチを初めて見たと言われました。Windows PowerShell では、どのような処理についても、さまざまな実行方法が用意されているので、これは驚くべきことではありませんでした。この読者の方から、カスタム オブジェクトを生成するさまざまな方法を紹介する記事を書いてはどうかという提案を受けたので、今月の記事で、このトピックを取り上げることにしました。

省略しない方法

ここで紹介するのは、多くの人が、カスタム オブジェクトの作成時に使用すると思われる方法です。私は、この方法を ”標準的なアプローチ” (教科書どおりのアプローチ) と呼んでいます。この方法では、入力作業が多くなりますが、わかりやすいという長所があります。変数 $os と変数 $bios に、それぞれオブジェクトを格納しているとしましょう。次のように、これらのオブジェクトの指定した情報を組み合わせることができます。

$object = New-Object –TypeNamePSObject $object | Add-Member –MemberTypeNoteProperty –Name OSBuild –Value $os.BuildNumber $object | Add-Member –MemberTypeNoteProperty –Name OSVersion –Value $os.Version $object | Add-Member –MemberTypeNoteProperty –Name BIOSSerial –Value $bios.SerialNumber Write-Output $object

このパターンを使用して、最終的に出力するオブジェクトをパイプラインに出力する前に必要な情報を追加できます。

-PassThru: 簡単なショートカット

1 つ目のアプローチは、Add-Member コマンドレットに対して、オブジェクトをパイプラインに戻すように指示することで簡略化できます。

$object = New-Object –TypeNamePSObject $object | Add-Member –MemberTypeNoteProperty –Name OSBuild –Value $os.BuildNumber –PassThru | Add-Member –MemberTypeNoteProperty –Name OSVersion –Value $os.Version –PassThru | Add-Member –MemberTypeNoteProperty –Name BIOSSerial –Value $bios.SerialNumber Write-Output $object

行末にパイプ文字を配置すると、Windows PowerShell では、次の物理行で、パイプラインに含まれる次のコマンドを探す必要があると認識します。基本的に、これは、長いコマンドを複数の物理行に分けるための方法です。この方法を –PassThru スイッチと組み合わせて使用すると、3 つの個別のコマンドを 1 つのコマンドにすることができます。

最先端のハッシュ テーブル

ここまでに紹介した 2 つのアプローチは有効ですが、とても冗長です。スクリプトを見ても、どのような処理が行われているのかを視覚的に特定することは困難です。New-Object コマンドレットを使うと、より簡単なアプローチになります。このコマンドレットでは、新しく作成したオブジェクトに追加する必要があるプロパティ名と値を格納したハッシュ テーブル (連想配列) を作成することが可能です。これらのプロパティは、自動的に NoteProperty として作成されます。

$properties = @{'OSBuild'=$os.BuildNumber; 'OSVersion'=$os.version; 'BIOSSerial'=$bios.SerialNumber} $object = New-Object –TypeNamePSObject –Prop $properties Write-Output $object

結果は同じですが、最初の 2 つのアプローチよりも、ずっとわかりやすいと思います。聡明な読者の方の中には、かっこで囲んだ式を使用して、さらにスクリプトを短くできる方もいらっしゃるでしょう。ただし、かっこを使用すると、スクリプトが読みづらくなる可能性があります。

$object = New-Object –TypeNamePSObject –Prop (@{'OSBuild'=$os.BuildNumber; 'OSVersion'=$os.version; 'BIOSSerial'=$bios.SerialNumber}) Write-Output $object

さらに一歩先へ

すべての例で、パイプラインに出力する前にカスタム オブジェクトを変数 ($object) に格納していることにお気付きだと思います。その理由は単純で、このようにすると、さらにオブジェクトを操作できるようになるからです。たとえば、次のようにオブジェクトに独自の型名を付けることができます。

$object.PSObject.TypeNames.Insert(0,'My.Custom.Name')

このようにすると、オブジェクトを表示するときに使用する既定の書式設定のカスタム レイアウトを作成できます。この技法は、『 Windows PowerShell Scripting and Toolmaking 』(Concentrated Technology and Interface Technical Training、2011 年) で多く取り上げました。この書籍は、私が執筆した短編物で、独自に作成した Windows PowerShell ツールの出力としてカスタム オブジェクトを作成することに重点を置いています。

十人十色

処理が完了すれば、Windows PowerShell では、間違った方法はありません。とは言っても、特に初心者の方にとっての読みやすさと習得しやすさを考慮して、使用することを避けているアプローチがあります。そのような方法の 1 つを紹介しましょう。ここでも、変数 $os と変数 $bios に、情報を抽出するオブジェクトが格納されているとします。

$os | Select-Object –Property @{n='OSVersion';e={$_.Version}}, @{n='OSBuild';e={$_.BuildNumber}}, @{n='BIOSSerial';e={$bios.SerialNumber}}

ここまでに紹介した方法と同じ結果が生成されますが、ぞっとするような構文を使用しています。多数の句読点と構造体が含まれており、Select-Object コマンドレットが 3 つのハッシュテーブルを使用して行っていることについて詳しく理解する必要があります。

基本的に、ここでは、(Format コマンドレットと共通の) Select-Object コマンドレット固有の構文を使用して、カスタム プロパティを生成しています。この構文は、ソフトウェア開発経験のある人が使用しているのを見かけます。私を含む多くの人にとって、この構文を解析するのは骨が折れる作業なので、この構文の使用は避けています。

拡張しなければ Windows PowerShell の価値はない

Windows PowerShell は、正常ではない処理を行えるという点で独自性があります。たとえば、先ほどのハッシュテーブルの例に戻りましょう。先ほどの処理は、次のように行うこともできます。

$info = @{} $info.OSBuild=$os.BuildNumber $info.OSVersion=$os.version $info.BIOSSerial=$bios.SerialNumber $object = New-Object –TypeNamePSObject –Prop $info Write-Output $object

ここでは、空のハッシュテーブルを作成して、存在しないプロパティを参照することで情報を追加しています。たとえば、OSBuild プロパティに初めてアクセスしようとしたときに、Windows PowerShell では、$info オブジェクト (空のハッシュテーブル) に、OSBuild プロパティが存在しないことを認識します。Windows PowerShell では、このプロパティを暗黙的に作成して値を割り当てます。正常ではない処理ですが、問題なく機能します。

道徳的な観点で: テキストではなくオブジェクトを

カスタム オブジェクトを作成する場合でも、コンソール ウィンドウにテキストのみを出力する代わりに、カスタム オブジェクトを作成できます。オブジェクトは、テキストとは比べ物にならないほど柔軟性が高いので、スクリプトや関数の出力を他のものと統合することができます。

Don Jones

Don Jones は、Microsoft MVP の受賞者で、『Learn Windows PowerShell in a Month of Lunches』(Manning Publications、2011 年) の著者でもあります。この書籍は、管理者が Windows PowerShell を効率的に使用できるようにすることを目的としています。また、一般ユーザーを対象にオンサイトの Windows PowerShell トレーニングも開催しています。Don に対するお問い合わせについては、彼の Web サイト (ConcentratedTech.com、英語) を参照してください。

関連コンテンツ