概要
とりあえず基礎っぽいものってことで、以下の構成のオブジェクトを作成してみた。
実際は、Get-Hogeでなんかの情報取得して、Where-ObjectやSelect-Object使って特定のプロパティ抜き出したものでオブジェクト作ることが多いと思う。
CSV読み込んでデータ処理したい場合なんかにもたぶん便利。
↓それっぽいクラス図
TestObject
+ Index[]:int
+ Name[]:string #最初に適当に定義しておく
+ Width[]:int #値は適当に乱数で決める
+ Height[]:int #値は適当に乱数で決める
+ TriangleArea[]:double #上記2つから求めた三角形の面積
+ SearchForIndex():object #Index番号を指定して検索するメソッド
+ Search():object #検索に使うプロパティ名と値を指定して検索するメソッド
先に最終的なコードを掲載
function Get-TestObject{
$obj_ary = @() # return用オブジェクト
$names = @(
"foo"
"bar"
"hoge"
"fuga"
"fuga" # 同名でも可
)
# 各プロパティを定義
$i = 1
foreach($item in $names){
$obj = New-Object PSCustomObject
$obj | Add-Member -NotePropertyMembers @{
Index = $i
Name = $item
Height = ( 1 + (Get-Random 9) ) # ランダムで1~10代入
Width = ( 1 + (Get-Random 9) ) # ランダムで1~10代入
}
$obj | Add-Member -MemberType ScriptProperty -Name TriangleArea -Value {
$this.Width * $this.Height / 2
}
$i += 1
$obj_ary += ($obj | Select-Object Index, Name, Width, Height, TriangleArea)
}
# Index番号を指定して検索するメソッド
$obj_ary | Add-Member -MemberType ScriptMethod -Name SearchForIndex -Value {
param($index)
$ret = ($this | Where-Object { $_.Index -eq $index })
return $ret
}
# 検索に使うプロパティ名と値を指定して検索するメソッド
$obj_ary | Add-Member -MemberType ScriptMethod -Name Search -Value {
param($prop, $value)
$ret = ($this | Where-Object { $_.$prop -eq $value })
return $ret
}
# return
$obj_ary
}
# テスト用実行コマンド
$test = Get-TestObject
echo '##### $test ###############'
echo $test
echo '##### $test | ft ###############'
echo $test | ft
echo '##### $test | Get-Member ###############'
echo $test | Get-Member
echo '##### ($test).name ###############'
echo ($test).name
echo '##### ($test).SearchForIndex(1) | ft ###############'
echo ($test).SearchForIndex(1) | ft
echo '##### ($test).Search("Name", "fuga") | ft ###############'
echo ($test).Search("Name", "fuga") | ft
echo '##### $test | Where-Object { $_.TriangleArea -gt 10 } | ft ###############'
echo $test | Where-Object { $_.TriangleArea -gt 10 } | ft
echo '####################'
申し訳程度の解説
だいたいコード見ればわかるけど、ポイントはたぶん3つ。
- PSCustomObjectで1レコード分のオブジェクトを作る
- 単純に連想配列で作ると綺麗にならない
- オブジェクトにパイプでAdd-Memberに渡してプロパティやメソッドを追加する
- 追加するときにSelect-Objectを指定すると表示される順番を決められる
特にAdd-Memberはオプションが多くてややこしい。
あんまりわかってないけど、とりあえず以下の2つだけわかってれば使えると思う。
- 静的なプロパティを定義したい場合
Add-Member -NotePropertyMembers 配列
#※Powershell 3.0以上なら「[PSCustomObject] 配列」でも可
#※プロパティが一つだけなら、以下と同じく-Nameと-Valueで指定しても可
- 静的なプロパティを使って加工したプロパティを定義したい場合
Add-Member -MemberType ScriptProperty -Name プロパティ名 -Value {スクリプト}
#※{ }の中で、$thisを使って静的プロパティの値を参照できる
実行結果の例
テスト用のコードの結果は以下のようになる。
オブジェクトになっているから、特定のプロパティ名だけ抜き出したり、Format-Tableに渡して表示したりってことが通常のオブジェクトを扱うのと同じようにできる。
CSVやHTMLへのエクスポートもできる。
##### $test ###############
Index : 1
Name : foo
Width : 1
Height : 6
TriangleArea : 3
Index : 2
Name : bar
Width : 5
Height : 9
TriangleArea : 22.5
Index : 3
Name : hoge
Width : 1
Height : 6
TriangleArea : 3
Index : 4
Name : fuga
Width : 4
Height : 9
TriangleArea : 18
Index : 5
Name : fuga
Width : 4
Height : 7
TriangleArea : 14
##### $test | ft ###############
Index Name Width Height TriangleArea
----- ---- ----- ------ ------------
1 foo 1 6 3
2 bar 5 9 22.5
3 hoge 1 6 3
4 fuga 4 9 18
5 fuga 4 7 14
##### $test | Get-Member ###############
TypeName: Selected.System.Management.Automation.PSCustomObject
Name MemberType Definition
---- ---------- ----------
Equals Method bool Equals(System.Object obj)
GetHashCode Method int GetHashCode()
GetType Method type GetType()
ToString Method string ToString()
Height NoteProperty int Height=6
Index NoteProperty int Index=1
Name NoteProperty string Name=foo
TriangleArea NoteProperty System.Int32 TriangleArea=3
Width NoteProperty int Width=1
Search ScriptMethod System.Object Search();
SearchForIndex ScriptMethod System.Object SearchForIndex();
##### ($test).name ###############
foo
bar
hoge
fuga
fuga
##### ($test).SearchForIndex(1) | ft ###############
Index Name Width Height TriangleArea
----- ---- ----- ------ ------------
1 foo 1 6 3
##### ($test).Search("Name", "fuga") | ft ###############
Index Name Width Height TriangleArea
----- ---- ----- ------ ------------
4 fuga 4 9 18
5 fuga 4 7 14
##### $test | Where-Object { $_.TriangleArea -gt 10 } | ft ###############
Index Name Width Height TriangleArea
----- ---- ----- ------ ------------
2 bar 5 9 22.5
4 fuga 4 9 18
5 fuga 4 7 14
####################
おまけ(特殊フォルダの一覧を取得)
デスクトップとかマイドキュメントとか、環境変数でパスが定義されている特殊なフォルダのパスをすべて取得する。
特殊フォルダすべての名前とパスは元々同じオブジェクトに入っていないため、上手く文字列を結合して表示しないと見づらいものになってしまう。
こんなときオブジェクトを使うと、コードも表示結果も見やすくて扱いやすいスマートな書き方ができる。
function Get-SpecialFolders{
$obj_ary = @()
$specialfolders = ([environment+specialfolder] | Get-Member -MemberType Properties -static)
foreach($item in $specialfolders){
$obj = New-Object PSCustomObject
$obj | Add-Member -NotePropertyMembers @{
Name = ($item.Name)
Path = ([environment]::GetFolderPath($item.Name))
}
$obj_ary += ($obj | Select-Object Name, Path)
}
$obj_ary
}
結果はこんな感じ。
> Get-SpecialFolders
Name Path
---- ----
AdminTools C:\Users\Owner\AppData\Roaming\Microsoft\Windows\Start Menu\Programs\Administrative Tools
ApplicationData C:\Users\Owner\AppData\Roaming
CDBurning C:\Users\Owner\AppData\Local\Microsoft\Windows\Burn\Burn
CommonAdminTools C:\ProgramData\Microsoft\Windows\Start Menu\Programs\Administrative Tools
︙
また、例えばDドライブのフォルダだけを取得したい場合はPowershellの基本通り、
Get-SpecialFolders | Where-Object { $_.Path -match "^D" }
と書けばよい。
一度必要な情報だけでオブジェクトを作ってしまえば、後は余計な変数やプロパティを気にせずに扱えてとても便利。
参考ページ
カスタムオブジェクトの使い方などの解説
powershell チートシート
PowerShellのカスタムオブジェクト(PSCustomObject)の使い方
PowerShell再入門:11. PSObjectとは
Add-Memberの詳細な解説
Add-Member を極める
特殊フォルダの取得コード
PowerShell: ◆特殊フォルダーの取得