本編に入れられなかった微妙なトピックをいくつか解説します。
三部作の最後を締めくくるにふさわしくない、雑多な記事ですが、ご勘弁ください。
パラメーターの検証属性について/前編
PowerShell では、関数のパラメーターに特定の属性をつけることで、内容に宣言的に制限をかけることができます。
宣言的にというのが重要で、つまり、パラメーターの内容をチェックするためのコードを書かなくてもよいということです。
本記事では、そうした属性についてまとめます。
Add-Member を極める
この記事は PowerShell Advent Calendar 2013 の 23 日目です。
昨日は @ichiohta さんの「New-Module を用いてカスタムオブジェクトを生成する」、明日は @oota_ken さんです。
いやー、一年ぶりでございます。
結局前回の記事は「前編」と銘打っておきながら、後編を書かずに終わってしまいました。
いつか整理してまとめたいものです。
さて、本日のお題は Add-Member について。
PowerShell 3.0 から、カスタムオブジェクトを組み立てるのが
[PSCustomObject] @{ x = 1; y = 2 }
といった簡易な記述で可能になったので、影が薄くなったコマンドです(昔はどう書いていたかは後述)。
かなりの長編となりますが、前後編に分けたりするとまた尻切れで終わる可能性がありますのでどうか最後までお付き合いください。
こいつの大きな謎は、MemberType パラメーターの多彩さです。
ヘルプによると、以下の値が指定できるようです(実は他にもあります)。
- NoteProperty
- AliasProperty
- ScriptProperty
- CodeProperty
- ScriptMethod
- CodeMethod
しかしながら、カスタムオブジェクトを組み立てるという用途では、使うのはせいぜい NoteProperty か AliasProperty くらいだったのではないでしょうか。
では、他のタイプはどのように利用するのか。
MemberType に上記の値を指定し、Value と SecondValue に適切な値を指定してやればよいのですが、その「適切な値」とは何なのか。
これが、ドキュメントもロクに無いのです。
また、このパラメーターの型は PSMemberTypes なのですが、定義されているものの中には、上記のリストにないものがあります(ParameterizedProperty とか)。
では、それらの中で MemberType パラメーターの値として使えるものと使えないものの違いは何なのか。
というわけで今回は、手探りで突き止めた MemberType 全解説ということをやってみたいと思います。
続きを読むいろいろな方法で PowerShell スクリプトを実行してみる【前編】
※本記事は PowerShell Advent Calendar 2012 の 11 日目です。
どういうわけかお誘いを頂いたので書いてみることにします。
本当は先週末にやろうと思っていたんですが WiiU に夢中になってすっかり忘れていました。
PowerShell、便利ですよね。何が便利って .NET Framework をそのまま使えるのがいい。
もうスクリプトを JavaScript とか MS-DOS バッチファイルなんかで書く気にはなれません。
というわけで、様々なタスクの自動処理に使われるわけですが、しばしば、よくわからないポイントでハマります。
PowerShell コンソールを立ち上げて、その中だけで完結する処理であればいいのですが、他のアプリから PowerShell を実行して処理をさせたい場合とかに困ります。
具体的にどういう場合かというと…やっぱりここで言うのはやめておきます。お察しください。
なお、俺は PowerShell を日頃からゴリゴリいじっているわけでもないので、詳しくありません。はっきり言って素人です。
そのため、「こんなことでハマりました」というのは書いているものの、「ハマらないためにはどうしたらいいか」はわかりません。
きっと、日々PowerShell を操っている諸兄から見ると、当然の挙動なのやもしれません。
教えてエロい人。
というわけで、以下、本編(前編)です。
こんなスクリプトを用意します。単純に引数を1つずつ表示するだけです。
test1.ps1
'Length: ' + $args.Length for ($i = 0; $i -lt $args.Length; ++$i) { "[{0}]: {1}" -f $i, $args[$i] }
まずはこれを、PowerShell コンソールから実行してみます。
call1.ps1
'(1) -----' .\test1.ps1 a b c '(2) -----' .\test1.ps1 'a b' c '(3) -----' .\test1.ps1 "a b" c
結果はこうなります。当然ですね。
call1.ps1 結果
(1) ----- Length: 3 [0]: a [1]: b [2]: c (2) ----- Length: 2 [0]: a b [1]: c (3) ----- Length: 2 [0]: a b [1]: c
何も疑問を挟む余地はありません。
次にこれを、別の powershell.exe プロセスを立ち上げて実行してみます。
fork1.ps1 (A)
'(1) -----' powershell.exe .\test1.ps1 a b c '(2) -----' powershell.exe .\test1.ps1 'a b' c '(3) -----' powershell.exe .\test1.ps1 "a b" c
結果はこうなります。…どうしたことでしょう。
fork1.ps1 (A) 結果
(1) ----- Length: 3 [0]: a [1]: b [2]: c (2) ----- Length: 3 [0]: a [1]: b [2]: c (3) ----- Length: 3 [0]: a [1]: b [2]: c
他にもいろいろ試してみましょう。
fork1.ps1 (B)
'(4) -----' powershell.exe .\test1.ps1 'a b c' '(5) -----' powershell.exe .\test1.ps1 "a b c" '(6) -----' powershell.exe .\test1.ps1 "'a b' c" '(7) -----' powershell.exe .\test1.ps1 '"a b" c'
結果はこうなります。
fork1.ps1 (B) 結果
(4) ----- Length: 3 [0]: a [1]: b [2]: c (5) ----- Length: 3 [0]: a [1]: b [2]: c (6) ----- Length: 2 [0]: a b [1]: c (7) ----- Length: 3 [0]: a [1]: b [2]: c
(6)だけ差が出ました。
ちなみに(6)は
powershell.exe ".\test1.ps1 'a b' c"
としても、同じ結果になりました。
powershell.exe のコマンドラインオプションには -File というものもあります。
これをつけてみましょう。
fork1.ps1 (C)
'(8) -----' powershell.exe -File .\test1.ps1 a b c '(9) -----' powershell.exe -File .\test1.ps1 'a b' c '(10) -----' powershell.exe -File .\test1.ps1 "a b" c '(11) -----' powershell.exe -File .\test1.ps1 'a b c' '(12) -----' powershell.exe -File .\test1.ps1 "a b c" '(13) -----' powershell.exe -File .\test1.ps1 "'a b' c" '(14) -----' powershell.exe -File .\test1.ps1 '"a b" c'
結果はこうなりました。
fork1.ps1 (C) 結果
(8) ----- Length: 3 [0]: a [1]: b [2]: c (9) ----- Length: 2 [0]: a b [1]: c (10) ----- Length: 2 [0]: a b [1]: c (11) ----- Length: 1 [0]: a b c (12) ----- Length: 1 [0]: a b c (13) ----- Length: 1 [0]: 'a b' c (14) ----- Length: 2 [0]: a b [1]: c
-File のありなしで結果が全然違いますね。参った…。
とはいえ、概ね、そうなるだろうと(素人考えで)期待したように実行されているように思われます。
一点、(13) と (14) の結果が非対称なのが気になるところですね…。
最後に、MS-DOS のバッチ (.cmd) ファイルから実行した場合の結果も載せておきます。
call1.cmd
@echo off echo (1) ----- powershell.exe .\test1.ps1 a b c echo (2) ----- powershell.exe .\test1.ps1 "a b" c echo (3) ----- powershell.exe .\test1.ps1 'a b' c echo (4) ----- powershell.exe -File .\test1.ps1 a b c echo (5) ----- powershell.exe -File .\test1.ps1 "a b" c echo (6) ----- powershell.exe -File .\test1.ps1 'a b' c
こいつの結果は、今までのどれとも異なります。
call1.cmd 結果
(1) ----- Length: 3 [0]: a [1]: b [2]: c (2) ----- Length: 3 [0]: a [1]: b [2]: c (3) ----- Length: 2 [0]: a b [1]: c (4) ----- Length: 3 [0]: a [1]: b [2]: c (5) ----- Length: 2 [0]: a b [1]: c (6) ----- Length: 3 [0]: 'a [1]: b' [2]: c
本記事はひとまず、ここでおしまいです。
が、実はまだ本題に入っていなかったりします。
しかしながら、アドベントカレンダーという性質上、日付が変わる前に掲載しないといけませんので、一旦区切らせて頂きます。
後編は、param を使ってパラメーターを宣言したファイルを外部から呼び出したりしてみます。配列型の引数とか使います。
WiiU とペーパーマリオに気を取られていなければ、きっと今週中には書くはずです。
# はてなブログって PowerShell のシンタックスハイライトには対応してないんですかね…