スクリプトで使用するカスタム タイプを PowerShell で作成するにはどうすればよいですか?
-
09-06-2019 - |
質問
一部の PowerShell スクリプトでカスタム型を定義して使用できるようにしたいと考えています。たとえば、次の構造を持つオブジェクトが必要になったとします。
Contact
{
string First
string Last
string Phone
}
次のような関数で使用できるようにするには、これを作成するにはどうすればよいですか。
function PrintContact
{
param( [Contact]$contact )
"Customer Name is " + $contact.First + " " + $contact.Last
"Customer Phone is " + $contact.Phone
}
PowerShell ではこのようなことは可能ですか、あるいは推奨されていますか?
解決
カスタム型の作成は PowerShell で行うことができます。
Kirk Munro には、プロセスを徹底的に詳しく説明した 2 つの素晴らしい投稿があります。
本 Manning による Windows PowerShell の動作 カスタム タイプを作成するためのドメイン固有言語を作成するためのコード サンプルも含まれています。この本は全体的に素晴らしいので、本当にお勧めします。
上記を簡単に実行する方法を探しているだけの場合は、次のようなカスタム オブジェクトを作成する関数を作成できます。
function New-Person()
{
param ($FirstName, $LastName, $Phone)
$person = new-object PSObject
$person | add-member -type NoteProperty -Name First -Value $FirstName
$person | add-member -type NoteProperty -Name Last -Value $LastName
$person | add-member -type NoteProperty -Name Phone -Value $Phone
return $person
}
他のヒント
PowerShell 3 より前
PowerShell の拡張型システムでは、当初、パラメーターで行った方法に対してテストできる具体的な型を作成できませんでした。このテストが必要ない場合は、上記の他の方法を使用しても問題ありません。
サンプルスクリプトのように、キャストまたは型チェックできる実際の型が必要な場合...それ できない C# や VB.net で記述してコンパイルすることなく実行できます。PowerShell 2 では、「Add-Type」コマンドを使用して非常に簡単に実行できます。
add-type @"
public struct contact {
public string First;
public string Last;
public string Phone;
}
"@
歴史的メモ:PowerShell 1 ではさらに困難でした。CodeDom を手動で使用する必要がありました。非常に古い関数があります。 新しい構造体 PoshCode.org のスクリプトが役に立ちます。あなたの例は次のようになります。
New-Struct Contact @{
First=[string];
Last=[string];
Phone=[string];
}
使用する Add-Type
または New-Struct
実際にクラスをテストできるようになります param([Contact]$contact)
を使用して新しいものを作成します $contact = new-object Contact
等々...
PowerShell 3 の場合
キャストできる「実際の」クラスが必要ない場合は、Add-Member の方法を使用する必要はありません。 スティーブンらは実証した その上。
PowerShell 2 以降では、New-Object に -Property パラメーターを使用できます。
$Contact = New-Object PSObject -Property @{ First=""; Last=""; Phone="" }
PowerShell 3 では、 PSCustomObject
TypeName を追加するためのアクセラレータ:
[PSCustomObject]@{
PSTypeName = "Contact"
First = $First
Last = $Last
Phone = $Phone
}
まだ 1 つのオブジェクトしか取得していないため、次のオブジェクトを作成する必要があります。 New-Contact
関数を使用して、すべてのオブジェクトが同じになることを確認しますが、パラメータを PSTypeName
属性:
function PrintContact
{
param( [PSTypeName("Contact")]$contact )
"Customer Name is " + $contact.First + " " + $contact.Last
"Customer Phone is " + $contact.Phone
}
PowerShell 5 の場合
PowerShell 5 ではすべてが変わり、ついに class
そして enum
型を定義するための言語キーワードとして ( struct
でも大丈夫です):
class Contact
{
# Optionally, add attributes to prevent invalid values
[ValidateNotNullOrEmpty()][string]$First
[ValidateNotNullOrEmpty()][string]$Last
[ValidateNotNullOrEmpty()][string]$Phone
# optionally, have a constructor to
# force properties to be set:
Contact($First, $Last, $Phone) {
$this.First = $First
$this.Last = $Last
$this.Phone = $Phone
}
}
また、オブジェクトを使用せずにオブジェクトを作成する新しい方法も得られました。 New-Object
: [Contact]::new()
-- 実際、クラスを単純にしてコンストラクターを定義しない場合は、ハッシュテーブルをキャストすることでオブジェクトを作成できます (ただし、コンストラクターがなければ、すべてのプロパティを設定する必要があることを強制する方法はありません)。
class Contact
{
# Optionally, add attributes to prevent invalid values
[ValidateNotNullOrEmpty()][string]$First
[ValidateNotNullOrEmpty()][string]$Last
[ValidateNotNullOrEmpty()][string]$Phone
}
$C = [Contact]@{
First = "Joel"
Last = "Bennett"
}
これがショートカット方法です。
$myPerson = "" | Select-Object First,Last,Phone
Steven Murawski の答えは素晴らしいですが、私は短い方が好きです (むしろ、add-member 構文を使用する代わりに単にオブジェクトを選択するだけです)。
function New-Person() {
param ($FirstName, $LastName, $Phone)
$person = new-object PSObject | select-object First, Last, Phone
$person.First = $FirstName
$person.Last = $LastName
$person.Phone = $Phone
return $person
}
驚くべきことに、カスタム オブジェクトを作成するためのこの簡単なオプション (vs 3 以降) について誰も言及しませんでした。
[PSCustomObject]@{
First = $First
Last = $Last
Phone = $Phone
}
ただし、タイプは PSCustomObject になりますが、実際のカスタム タイプではありません。しかし、おそらくこれがカスタム オブジェクトを作成する最も簡単な方法です。
使用できる PSObject と Add-Member の概念があります。
$contact = New-Object PSObject
$contact | Add-Member -memberType NoteProperty -name "First" -value "John"
$contact | Add-Member -memberType NoteProperty -name "Last" -value "Doe"
$contact | Add-Member -memberType NoteProperty -name "Phone" -value "123-4567"
これは次のように出力されます。
[8] » $contact
First Last Phone
----- ---- -----
John Doe 123-4567
(私が知っている) 他の方法は、C#/VB.NET で型を定義し、そのアセンブリを PowerShell にロードして直接使用することです。
この動作により、他のスクリプトまたはスクリプトのセクションが実際のオブジェクトを操作できるようになるため、間違いなく推奨されます。
ここでは、カスタム型を作成してコレクションに保存するためのハードパスを示します。
$Collection = @()
$Object = New-Object -TypeName PSObject
$Object.PsObject.TypeNames.Add('MyCustomType.Contact.Detail')
Add-Member -InputObject $Object -memberType NoteProperty -name "First" -value "John"
Add-Member -InputObject $Object -memberType NoteProperty -name "Last" -value "Doe"
Add-Member -InputObject $Object -memberType NoteProperty -name "Phone" -value "123-4567"
$Collection += $Object
$Object = New-Object -TypeName PSObject
$Object.PsObject.TypeNames.Add('MyCustomType.Contact.Detail')
Add-Member -InputObject $Object -memberType NoteProperty -name "First" -value "Jeanne"
Add-Member -InputObject $Object -memberType NoteProperty -name "Last" -value "Doe"
Add-Member -InputObject $Object -memberType NoteProperty -name "Phone" -value "765-4321"
$Collection += $Object
Write-Ouput -InputObject $Collection