コマンドレットのパラメータを列挙してみる。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間隔でクエリを発行する方法になってしまい、低コストで行う方法がちょっと思いつきませんでした。“ほげ”}みたいなコードを書いてゴリ押しすることもできるかと思います。感想というわけで、なんだか微妙な成果になって恐縮ですが、なんで無いんだろうと思っていた関数を実際に書いてみると、無い理由が分かったりするものなんだなあ、と思ったりした次第です。スクリプトの解説を何もしてないですが、あえて解説する程のものでもないこともないですが、まあ長くなるのでやめときます。入力オブジェクトを一旦全部取得してから、後続パイプラインに流し込む例としていくらか参考になるかもしれません。スクリプトブロックを二重にして$_に対象オブジェクトがきちんと格納されるようにする方法、若干トリッキーな気もしますが正式にはどう書くのが良いのか不明なのでこうしてみました。|TweetJScriptは言語単体ではSafeArrayを作ることができません。そこでJScriptでSafeArrayが必要な場合、VBScriptを併用しVBScriptの配列(これはSafeArrayです)をJScriptに取り込む方法や、Scripting.DictionaryのItems()メソッドを使う方法などが使われているようです。これらの方法で多次元のSafeArrayを作るサンプルをあまり見かけませんでした。Dictionaryの方法ではそもそも1次元しか無理ですしね。プログラマとSEのあいだこの記事の二つ目の例ではExcelを使用しRegionオブジェクトが二次元配列を返す点を利用しています。これはなかなか盲点というかアイデアものではありますが、実行速度にやや難があるかな?と思いました。この記事の方法は、もともとExcelで二次元配列が必要な場合があったから考案されたもののようで、その用途においてはExcelを起動するコストは考慮しなくてよいのかもしれません。一つ目の方法ではVBScriptを併用していますが、.wsfファイルを使用してJScriptとVBScriptを混在させる形式をとっています。この方法はWSHでは問題ありませんが、複数のスクリプトエンジンを混在できないホスト環境では問題があります。ASPなどほとんどの環境では大丈夫そうです。私が最近はまっているJScript実行環境であるところのAzureaでは無理ですね。WSHでも.jsファイルにこだわるのであれば。そこで考えたのが、ScriptControlを使用してJScriptのコードの中でVBScriptのコードを実行させる方法です。以下のような感じになります。sc.Run("ConvertArray",jsArray2d);}まあやっていることは本当にJScriptの配列をバラしてVBScriptの二次元配列に詰め直しているだけです。いくつかポイントがあって、まずVBScriptからはJScriptのオブジェクトメンバーにドット演算子でアクセスができます。JScriptの配列はオブジェクトと同一であり、配列はオブジェクトに0,1,2...という名前のプロパティが存在することになります。VBScriptで数字のメンバ名はそのままではドット演算子でアクセスできないので、[]でくくる必要があります(これ、予約語なんかもそうですね。あとVB6でもVB.NETでも同じなので覚えておくといいかも)。次元数2の配列の長さを調べるのにjsArray.[0]でまず内側の配列オブジェクトを取得しているわけです。Next構文が使えます。Nextを使ってインデックスアクセスはできません。いうのもjsArray.[3]とかはあくまでjsArrayオブジェクトの3プロパティの値を参照しているにすぎず、jsArray.[I]という書き方ができないからです(これだと単にIプロパティの値を見てることになる)。Eval関数を併用すれば可能ではありますが、コードの中にコードを含ませさらにその中にまたコードを含ませるのも微妙なのでここでは使ってません。あとは紹介した記事の関数部分だけ置き換えればJScriptのVBArrayオブジェクトを用いたテストもできるかと思います。注意点はExcelオブジェクトは配列添え字が1から始まるのに対し、VBScriptの配列は0から始まる点です。LBound関数を使えばその差違は吸収できるかな、と思います。最初は多次元配列というかn次元配列に拡張した関数を書いてやろうと企んでましたが挫折しました。ネストしたループではなく再帰呼び出しである必要がありますし、ReDimは次元数を動的に指定することができないので実行するVBScript自体を動的生成しなければいけません。興味がある方はチャレンジしてみてください。|Tweetご無沙汰してます。mixiついったーブログその他などを。最近、spamコメントが鬱陶しくて色々対策を考えてるんですが、手っ取り早く効果的なのはBBQを使うことですね。某巨大掲示板群サイトで荒らしに使われた、おもに公開プロキシのリストをDNSを引いて持ってくるというものです。Perlの実装はこのページにあります。PHPの実装も見かけました。意外と.NET,C#な実装を見かけないので、最近覚えたC#でさくっとかいてみました。}}使い方はコードを見てください。これは単に引数のホストをBBQにかけ、結果を標準出力に出すコンソールアプリですが、メソッド化してもaspxに組み込んでもWebサービスにしてもまぁ好きなように使ってくださいませ。BBQは万能選手じゃありません。本来書き込めるべき人が書き込めないことも多々あります。BBQをまず通してOKならOK、NGならCAPTCHA認証をやってもらう、とかがいいと思います。トラックバックspam対策もいろいろ考えたんですが、まだ国産のは少ないので、送信データが英字のみをはじく、でも効果は結構あります。このへんmixiでメモったのでコピペ。トラックバックって2008年10月11日20:04黒歴史になるんだろうかオートディスカバリーはないと微妙だしあるとspamの温床になるし。20:18excerpt,titleなどの文字列で弾くのはよくある対策だけど根治法じゃないいたちごっこだーBBQは使えない。理由は少し考えれば分かりますので略。urlの先をまず見に行って、そこにこちらへのリンクがなければまず速効NG。あとはお好みで、引用がなければNGとか。これって莫大なコストがかかるし送り元を見に行くというのがそもそもなんか根本的にどうなんっておもう。21:08送り元を見に行く方式の問題はまだあって、A→Bにトラックバックを送信された場合、B→Aに「AにBのURLが存在するか」を確認しに行く。合理的だけど、このトラックバックって誰でも送れるんだよねー。Aを書いた人じゃなくても。AともBとも関係ない悪意を持つxがいて、A→Bへのトラックバックを乱射した場合どうなるか。B→AのDoS攻撃みたいなんが成立しちゃう。同ドメインへの確認間隔を制御する必要がでてくる。それはもちろん正しくサービスを利用する人にとっては不便になるわけで。21:28送信元を見に行く方式で、トラックバックを送った人のリモートホストと、urlに指定されたWebサイトのドメインが一致するかまず調べるという方法もあるけど(たぶんはてなではこれをやっている)、これは正しい使い方をしていても一致しないことも当然あるわけで(手動でトラックバック打つときとかね)。この辺が確かに手の打ちどころではあるようには思う。手動で打つ時はオートディスカバリー関係ないしな。私のようにDNSの逆引きができないというか正逆で結果が異なるようなサーバーの場合は泣いてもらうしかないかなー。前者は、トラックバックを送った人のリモートホストと、urlに指定されたWebサイトのドメインが一致するかまず調べ、一致しない場合ははじく。一致した場合は送信元を見に行って、こちらへのリンクがある場合は通す。URLを用意するがあるところまではコピペできるが、それに数文字、画像にかかれた文字をつけたすようにする(認証の代わり)。この辺が落としどころかなー。21:35追加文字列は定期的に変わるようにする。21:37オートディスカバリーのほうはチェック間隔に制限を設ける。22:38SPAM温床はメールと同じようなもんじゃないだろか。Server側とClient側で共通のアドレス作れるけど、直接ファイル読み込んでJavaScript実行してないと正しいURLがない。22:54いえねー、トラックバックってわりと新しい規格なのになんでspam温床になることを考えて規格作らなかったのかと。eメールは昔々作られたものだから仕方ないとして。JavaScriptいいですねー。22:55BBQについてはこちらhttp://bbq.uso800.net/JZ5さん事後承諾でごめんなさいだけどコピペさせていただきました。あと、BBXを使うのも一つの案かな。こっちは広告爆撃ブラックリストなので近いものがあるかと。@mutaguchiBooks書籍版。