- 10/05/2020
- 8 minutes to read
-
- j
- m
- s
- j
- c
PSCustomObject
はPowerShellツールベルトに加えたいすばらしいツールです。 基本的なことから始めて、より高度な機能へと進んでいきましょう。 PSCustomObject
の使用目的は、構造化データを作成する簡単な方法を提供することです。
Note
The original version of this article appeared on the blog written by @KevinMarquette.NetSupport.jp ———————————————————————————————— この記事のオリジナルは @KevinMarquette 氏のブログです。 PowerShell チームは、このコンテンツを共有してくださった Kevin に感謝します。 彼のブログ atPowerShellExplained.com をチェックしてください。
- Creating a PSCustomObject
- Converting a hashtable
- Legacy approach
- ファイルに保存する
- Working with properties
- Adding properties
- Remove properties
- Enumerating property names
- Dynamically accessing properties
- PSCustomObject をハッシュテーブルに変換する
- プロパティのテスト
- オブジェクトメソッドの追加
- オブジェクト vs 値型
- psobject.copy()
- PSTypeName for custom object types
- Using DefaultPropertySet (the long way)
- Update-TypeData with DefaultPropertySet
- Update-TypeData with ScriptProperty
- 関数パラメータ
- Function OutputType
- Closing thoughts
Creating a PSCustomObject
私は PowerShell で を使用するのが大好きです。 そのため、オブジェクトを作成する他のすべての方法は省略しますが、これらの例のほとんどは PowerShell v3.0 以降であることを言及する必要があります。
$myObject = @{ Name = 'Kevin' Language = 'PowerShell' State = 'Texas'}
私はほぼすべてにハッシュテーブルを使用しているので、この方法は私にとってうまく機能します。 しかし、PowerShell でハッシュテーブルをよりオブジェクトのように扱いたい場合もあります。 この違いに最初に気づくのは、Format-Table
または Export-CSV
を使用したいときに、ハッシュテーブルが単なるキー/値ペアのコレクションであることに気づくときです。
$myObject.Name
Converting a hashtable
この話題のついでに、こんなこともできることをご存知ですか:
$myHashtable = @{ Name = 'Kevin' Language = 'PowerShell' State = 'Texas'}$myObject = $myHashtable
私は最初からオブジェクトを作成したいのですが、最初にhashtableで作業しなければならない場合があります。 この例は、コンストラクタがオブジェクトのプロパティをハッシュテーブルで受け取るので動作します。 重要な注意点として、この方法は動作しますが、完全に等価というわけではありません。 最大の違いは、プロパティの順序が保持されないことです。
Legacy approach
カスタム オブジェクトを作成するために New-Object
を使用する人を見たことがあるかもしれません。
$myHashtable = @{ Name = 'Kevin' Language = 'PowerShell' State = 'Texas'}$myObject = New-Object -TypeName PSObject -Property $myHashtable
この方法はかなり遅いですが、PowerShell の初期のバージョンでは最良の選択肢かもしれません。
ファイルに保存する
ハッシュテーブルをファイルに保存する最善の方法は、それを JSON として保存することだと思います。 ファイルにオブジェクトを保存する他の方法については、「ファイルへの読み取りと書き込みの多くの方法」の記事で説明しています。
Working with properties
Adding properties
Add-Member
を使用して、PSCustomObject
に新しいプロパティを追加できます。
$myObject | Add-Member -MemberType NoteProperty -Name 'ID' -Value 'KevinMarquette'$myObject.ID
Remove properties
また、オブジェクトからプロパティを削除することも可能です。
$myObject.psobject.properties.remove('ID')
psobject
はベース オブジェクト メタデータにアクセスするための隠しプロパティです。
Enumerating property names
時には、オブジェクト上のすべてのプロパティ名のリストが必要な場合があります。
$myObject | Get-Member -MemberType NoteProperty | Select -ExpandProperty Name
これと同じリストを psobject
プロパティから取得することもできます。
$myobject.psobject.properties.name
Dynamically accessing properties
私はすでに、プロパティ値に直接アクセスすることができることを述べました。
$myObject.Name
プロパティ名に文字列を使用しても動作します。
$myObject.'Name'
これをもう一歩進めて、プロパティ名に変数を使用することができます。
$property = 'Name'$myObject.$property
奇妙に見えますが、これは動作します。
PSCustomObject をハッシュテーブルに変換する
最後のセクションから続けるには、プロパティを動的に歩き、それらからハッシュテーブルを作成することが可能です。
$hashtable = @{}foreach( $property in $myobject.psobject.properties.name ){ $hashtable = $myObject.$property}
プロパティのテスト
プロパティが存在するかどうかを知る必要がある場合、そのプロパティが値を持っているかどうかをチェックすればよいのです。
if( $null -ne $myObject.ID )
しかし、もしその値が$null
であり得るなら、psobject.properties
をチェックすることでそれが存在するかどうかを確認できます。
if( $myobject.psobject.properties.match('ID').Count )
オブジェクトメソッドの追加
もしオブジェクトにスクリプトメソッドを加える必要があるなら、Add-Member
とaScriptBlock
でそれをすることができます。 現在のオブジェクトを参照する自動変数 this
を使用しなければならない。 以下は、オブジェクトをハッシュテーブルにするためのascriptblock
です。 (最後の例と同じコード)
次に、それをスクリプト プロパティとしてオブジェクトに追加します。
$myObject.ToHashtable()
オブジェクト vs 値型
オブジェクトと値型は、変数の割り当てを同じようには処理しません。
$first = 1$second = $first$second = 2
この場合、$first
は 1、$second
は 2 です。
オブジェクト変数は、実際のオブジェクトへの参照を保持します。 あるオブジェクトをnewvariableに代入しても、それらは同じオブジェクトを参照しています。
$third = @{Key=3}$fourth = $third$fourth.Key = 4
$third
と$fourth
はオブジェクトの同じインスタンスを参照しているので、$third.key
と$fourth.Key
は両方とも4です。
psobject.copy()
オブジェクトの真のコピーが必要な場合、それを複製することができます。
$third = @{Key=3}$fourth = $third.psobject.copy()$fourth.Key = 4
複製すると、オブジェクトの浅いコピーが作成されます。 この例では、$third.key
は 3、$fourth.Key
は 4 です。
私がこれを浅いコピーと呼ぶのは、ネストしたオブジェクトがある場合、そのインスタンスを作成するためです。 (プロパティが他のオブジェクトを含む場合)。 トップレベルの値のみがコピーされます。 子オブジェクトは互いを参照します。
PSTypeName for custom object types
さて、オブジェクトができたので、それを使ってできることがいくつかありますが、ほとんど明らかではないかもしれません。 最初に行う必要があるのは、それに PSTypeName
を与えることです。 これは、私が見た中で最も一般的な方法です:
$myObject.PSObject.TypeNames.Insert(0,"My.Object")
私は最近、/u/markekraus によるこの投稿からこれを行う別の方法を発見しました。 Adam Bertram と Mike Shepard のアイデアについて少し調べてみたところ、彼らはインラインで定義することができるこのアプローチについて話していました。
Note
PowerShell クラスを使用して、カスタムの PowerShell タイプを作成することもできます。 詳細については、PowerShell クラスの概要を参照してください。
Using DefaultPropertySet (the long way)
PowerShellは、デフォルトで表示するプロパティを私たちのために決定してくれます。 ネイティブ コマンドの多くには、すべての重要な作業を行う .ps1xml
フォーマット ファイルがあります。 Boe Prox によるこの投稿から、PowerShell のみを使用してカスタム オブジェクトでこれを行う別の方法があります。
これで、私のオブジェクトがシェルに落ちたとき、デフォルトでこれらのプロパティのみが表示されます。
Update-TypeData with DefaultPropertySet
これは素晴らしいですが、最近 Jeffrey Snover & Don Jones と PowerShell unplugged 2016 を見ていてよりよい方法を知りました。 Jeffrey はデフォルトのプロパティを指定するために Update-TypeData を使用していました。
$TypeData = @{ TypeName = 'My.Object' DefaultDisplayPropertySet = 'Name','Language'}Update-TypeData @TypeData
この投稿をクイックリファレンスとして持っていなければ、ほとんど覚えてしまうほど簡単な方法です。 これで、たくさんのプロパティを持つオブジェクトを簡単に作成でき、かつシェルから見たときにきれいなビューを与えることができるようになりました。
$myObject | Format-List *
Update-TypeData with ScriptProperty
Something I got out of that video was creating script properties for your objects.このビデオから得た他のことは、オブジェクトのスクリプト プロパティを作成することでした。 これは、既存のオブジェクトでも機能することを指摘する良い機会でしょう。
これは、オブジェクトが作成される前でも後でも行うことができます。 これは、スクリプト プロパティで Add-Member
を使用する場合と異なる点です。 先ほどの方法で Add-Member
を使用した場合、それはオブジェクトの特定のインスタンスにのみ存在します。 これは、この TypeName
を持つすべてのオブジェクトに適用されます。
関数パラメータ
関数やスクリプトのパラメータにこれらのカスタム タイプを使用できるようになりました。 ある関数でこれらのカスタム オブジェクトを作成し、他の関数に渡すことができます。
param( $Data )
PowerShell は、オブジェクトが指定された型であることを要求します。 それは、タイプがあなたのコードでそれをテストするステップを節約するために自動的に一致しない場合、検証エラーをスローします。
Function OutputType
高度な関数用に OutputType
を定義することもできます。
function Get-MyObject{ param ( ...
OutputType 属性値は単なるドキュメント ノートです。 それは、関数コードから派生したり、実際の関数出力と比較されることはありません。
出力タイプを使用する主な理由は、関数に関するメタ情報が意図を反映するようにするためです。 開発環境が利用できる Get-Command
や Get-Help
のようなものです。 より多くの情報が必要な場合は、ヘルプの about_Functions_OutputTypeAttribute.
With said, if you’re using Pester to unit test your functions, it would be a good ideaato validate the output objects match your OutputType.
With the way that you’re using Pester to units test for your functions. 2694>
Closing thoughts
この文脈はすべて についてでしたが、この情報の多くはオブジェクト一般に当てはまります。 ちょうどこの先週、別のものを偶然見つけ、今まで見たことがなかったことに驚きました。 私は、これらのアイデアをすべてまとめて、皆さんが全体像を把握し、それらを使用する機会があったときに意識できるようにしたいと思いました。 あなたが何かを学び、これをあなたのスクリプトに取り入れる方法を見つけることができれば幸いです。