これうっかりしてるとスルーしてしまいそうです。具体例たとえば、こんなデータがあったとします。名前や生年月日が書かれたデータで、一応、法則性はあるようです。これをまともにパースしようと思うと、2行ごとに切り出して、正規表現を書いて...と、ちょっと面倒ですね。ちなみにこのダミーデータ作成にはなんちゃって個人情報を使わせていただきました。CSVで出力した後、以下のようなスクリプトでわざわざ醜く変形しました。Parsingで用いるテンプレートを書いてやりましょう。以下のように適当に3件(ここでは3〜5個目のレコード)抜き出して、プロパティ名をつけてやります。赤字が、手動で元データに付与した文字列です。({Age:45}歳)、{Sexuality:女}性みて頂ければ分かると思いますが、基本は、各データ項目に対して、{プロパティ名:データ}のように指定してやるだけです。主キーとなるデータ項目にはプロパティ名の後に「*」をつけてやります。やって作ったテンプレートをtemplate.txtと名前を付けて保存しましょう。元データとテンプレートが揃ったので、あとは以下のようにしてConvertFrom-Stringコマンドレットを実行するだけです。テンプレートを元に、元テキストに含まれるすべてのデータが、プロパティ値を持ったオブジェクトデータに変換されていることが分かるかと思います。Parsingは個人的には、非常に面白い機能だと感じています。コンピュータに対して、「手本見せるよ、これはこう、これはこう。あとは同じようにまとめといてね!」というのができるようになったわけで、ちょっと未来を感じました。研究所レベルの研究成果を、製品として実装した初の例が、PowerShellだったというのも面白味を感じます。CSVでもJSONでもXMLでもない、わけのわからない謎フォーマットで保存されたテキストデータを解析しなきゃならない事態というのは、そもそも不幸な状況であることも、また事実かと思います。ConvertFrom-Stringは、そんな訳の分からないものを撲滅して、今度こそまともなフォーマットのデータに変換して保存するための、最終兵器のようなものかもしれません。Parsingでは他にもプロパティに型を指定したり、部分的に正規表現を用いたり、階層構造を持つデータにも対応してたりと、かなり色々なことができるようになっています。v5環境を整えて、ConvertFrom-Stringを試してみてください。ご参加いただけると幸いです。|Tweet昨日10/11のPowerShell勉強会#4にお越しいただいた方、どうもありがとうございました。スタッフ一同、これからも定期的に開催していこうと考えておりますので、ぜひともよろしくお願い致します。私のセッション資料を公開します。くま横浜で行ったものとほとんど同じですが、v5関係のスライドを少しだけ修正しています。今回は高度な関数とコマンドレットの作り方を主に取り上げていますが、要するに、PowerShellコマンドはPowerShellスクリプトでもC#でもほぼ同じようにして同じようなものが書ける、ということなのです。基本を押さえればどちらにも対応可能です。両者は状況に応じて使い分ければOKかと思います。PowerShellよりC#が得意、というならばコマンドレットを書くと良いですし、スクリプト的なお手軽なコードで書きたい場合は高度な関数、とかですね。速度が求められる部分とか、.NETアセンブリを多用する部分だけコマンドレットにして、他を高度な関数にする、あるいは、主要部はコマンドレットにして、その他はコマンドレットのラッパー的な高度な関数を用意する、のように両者を組み合わせたモジュールもよくあります。以下はデモ用のサンプルスクリプトです。高度な関数の雛型的なものになります。使い方はスライド本文を参照してください。}}以下はデモで用いたC#のコードです。コマンドレットクラスの雛型的なものになっています。ビルドの際はSDKに含まれるPowerShell関係のdllを参照設定してください(詳しくはスライド)。実行してインポートして下さい。以下の例だとGet-Baz、Set-Bazの2コマンドレットがインポートされます。|Tweet8/23わんくま横浜勉強会で、PowerShellコマンドの書き方というセッションをしたのですが、その際、株式会社Codeerさんが公開されているFriendlyというライブラリを使ったコマンドレットを動作させるデモを行いました。準備の時間がなくて、突貫工事で作ったサンプルで恐縮ですが、公開することにします。2010以降でC#のクラスライブラリを新規作成する。ある.dllを参照設定する。4.5、対象プラットフォームをx64にする。上記のコードを貼り付ける。NuGetでFriendlyおよびFriendly.Windowsを追加する。上記をビルドして生成したDLLにはGet-FormControlTextと、Set-FormControlTextの2つのコマンドレットが含まれます。6制限事項フォーム直下に配置されたコントロールしか取得できない(と思います)。Formアプリケーションにしか対応していない(と思います)。x64アプリしか操作できない(と思います。x86用はアセンブリを分ける必要がある??)。sensitiveでワイルドカード不可です。(この辺ただの手抜きですが)今後の方針?上のコードをみてもらえればわかると思いますが、ちょっと触ってみたら一応動くものができるくらい、Friendlyは分かりやすいです。皆さんもぜひ使ってみてください。本来は、テキストじゃなくてコントロールそのものをGetしたりSetしたりInvoke(クリックとか)したりできるようにしたかったんですが、Controlはシリアル化できないオブジェクトなので、Friendlyで実物を持ってきてコマンドレットに出力する、というのは無理でした。何らかのプロキシオブジェクトみたいなのでラップしたりすれば良いかと思います。それにしてもPowerShellとFriendlyの組み合わせはものすごい可能性を秘めている予感がします。システム管理方面では...セッションでもやりましたが、PowerShellコマンドレットベースのアプリケーションを作ると、GUIとCUIのいいところどりが出来る、とはいうものの、コマンドインターフェースがなくGUIオンリーのアプリケーションはまだまだたくさんあるのが現実かと思います。いうアプリケーションも、PowerShellデフォルトの機能のみではつらいですが、上記のようにFriendlyを併用すれば、GUI操作の自動化が容易になると思います。開発方面では...C#でFriendlyを使ったGUIのテストコードを書く以外に、上記のようなFriendlyの機能をラップしたコマンドレットを用意することで、PowerShellスクリプトでもテストコードを書くことができるようになると思います。その際、Pester等のPowerShell用テストフレームワークを併用すると、より一貫したテストコードが記述できるようになるんじゃないかと思います。|Tweet2014/08/23わんくま横浜#06にお越しいただいた方、どうもありがとうございました。私の「PowerShellコマンドの書き方」というセッションの資料を公開します。以下、セッション概要の再掲です。PowerShellのコマンドを記述する方法としては、大きく分けて、.NET言語で記述する「コマンドレット」と、スクリプトで記述する「高度な関数」があります。他言語の関数などと異なり、PowerShellのコマンドは他コマンドと連携させるためには、パイプラインの動作をきちんと把握して作成する必要があります。今回はPowerShellのパイプラインの挙動と、それを踏まえたコマンドレットと高度な関数の書き方を解説します。デモのお題としては、Friendlyを使ったUI操作自動化コマンドなんていかがですかね?ところで、同内容のセッションを今度は関西でもやる予定です。詳細が決まり次第、ここで告知します。http://winscript.jp/powershell/282に、本セッションで行ったデモ用のサンプルコードを公開しました。2013の5日目の記事です。PowerShellにはJobが完了するまで待機するWait-Jobコマンドレットというのがあります。これはその名の通り、パイプラインから入力したJobオブジェクトがすべて(あるいはどれか一つが)完了状態になるまでスクリプトの実行を待機する効果があります。当然ながらWait-JobはJobオブジェクトにしか利用できませんが、任意の入力オブジェクトに対して待機条件を指定してやれば、その条件を満たすまで実行を停止するコマンドがあると便利なんじゃないかな?と常々思っていたので書いてみました。[<CommonParameters>]パラメータ-InputObject:入力オブジェクト。-Property:変更を確認するプロパティ名。-Value:-Propertyで指定のプロパティ値が、このパラメータに指定する値になるまで待機する。-FilterScript:プロパティを指定する代わりに待機条件をスクリプトブロックで指定する。-Any:入力のどれか一つが条件を満たすまで待機するようにする。(省略時は入力が全部条件を満たすまで待機)-PassThru:入力オブジェクトが待機条件を満たした時点で、そのオブジェクトを出力する。-IgnoreImmutable:最初から条件を満たしている場合は出力しない。-PassThruと併用。-AllOutput:タイムアウトした場合や-Any指定時に一部のオブジェクトしか出力していない場合でも、最終的に未出力のすべてのオブジェクトを出力してから終了する。-PassThruと併用。-IntervalSec:プロパティ値のチェック、もしくは待機条件スクリプトの実行の間隔秒数を指定。-TimeoutSec:最大待機秒数。この時間を過ぎると条件を満たしていなくても待機を終了する。停止しているサービスがすべて開始するまで待機する。上記と同じだが、開始したサービスを逐次表示する。停止しているサービスが少なくとも1つ開始するまで待機する。プロセスのワーキングセットが100MBを超えた段階で逐次表示する。上記と同じだが、最初から100MBを超えてるものは出力しない。ディレクトリ内のファイル容量がすべて50KBを超えるまで待機し、出力のFileInfo配列を変数に代入。3600問題点プロパティ値を取得するときにリアルタイムに値が反映されないオブジェクト(要するにGetした時点のプロパティ値がずっと固定されてるもの)に対しては正しく動作しません。いうか、PowerShellで扱うオブジェクトはほとんどそうなんじゃないかと思います(汗ServiceControllerオブジェクト、Processオブジェクト、FileInfoオブジェクト、DirectoryInfoオブジェクトについては、Refreshメソッドを実行すると、プロパティ値を現在の値に更新してくれるので、それを利用してプロパティ値を監視できるようにはしています。それ以外についても監視できるようにするには、たぶんそれぞれのオブジェクトに応じた監視方法を地道に調査して実装していくしかないんじゃないかなあと思います。INotifyPropertyChangedインターフェースを実装したクラスについては、PropertyChangedイベントをSubscribeしてプロパティ値の変更を追跡できるようにしてみようとちょっと思ったんですが、PowerShellで扱うオブジェクトにINotifyPropertyChangedを実装したクラスのものってそんなにあるんだろうか?と疑問を覚えたのでやめました。WMIオブジェクトについては何か共通の方法でプロパティ値変更を監視できないかなあと思ったんですが、結局IntervalSec間隔でクエリを発行する方法になってしまい、低コストで行う方法がちょっと思いつきませんでした。“ほげ”}みたいなコードを書いてゴリ押しすることもできるかと思います。感想というわけで、なんだか微妙な成果になって恐縮ですが、なんで無いんだろうと思っていた関数を実際に書いてみると、無い理由が分かったりするものなんだなあ、と思ったりした次第です。スクリプトの解説を何もしてないですが、あえて解説する程のものでもないこともないですが、まあ長くなるのでやめときます。入力オブジェクトを一旦全部取得してから、後続パイプラインに流し込む例としていくらか参考になるかもしれません。スクリプトブロックを二重にして$_に対象オブジェクトがきちんと格納されるようにする方法、若干トリッキーな気もしますが正式にはどう書くのが良いのか不明なのでこうしてみました。@mutaguchiBooks書籍版。