WMIコネタ2008年06月18日 03時12分05秒

chkconfigモドキとかpsモドキとかで久々にWMIに触ったらなんだか面白かったのでちょろちょろといじくっているのだが、そのときに見つけたりしたコネタをば。正確には前も調べたけどすっかり忘れてたってとこなんだが。

まずはEnumeratorを拡張するが吉

WQLで問い合わせた結果はいわゆる「コレクション」が返ってくる。VBSの場合は何も考えずFor Eachを使えるのだが、JScriptの場合はEnumeratorでくるんでやる必要がある。まぁWMIに限らずWSH/HTAでCOMを触る場合はそうなるのだが。

んで好みの問題だと思うけど、WMIみたいなメタデータ中心のオブジェクトを扱う場合はコレクションのループ処理を多用するハメになるので、Enumeratorでeachなんかが使えるように拡張しといたほうが便利かな、と。

最低限のサンプル。

Enumerator.prototype = function(iterator) {
	var i = 0;
	for(this.moveFirst(); ! this.atEnd(); this.moveNext()) {
		iterator( this.item(), i++ );
	}
};

このままだとprototype.jsみたいにcontinue/breakの制御ができないけど、まぁコレクションを一通りまわすことはできるのでこれだけでも結構快適になる。

後で触れるけど、WMIのデータそのままだとちょっと具合が悪い型もあるので、これにmapとtoArrayでも加えればいいんじゃないかと。

Enumerator.prototype.map = function(iterator) {
	var results = [];
	this.each( function(item, index) {
		results[ results.length ] = iterator( item, index );
	} );
	return results;
};
Enumerator.prototype.toArray = function() {
	return this.map( function(item) { return item; } );
};

datetime型

例えばWin32_ProcessクラスのCreationDateプロパティなんかがこの「datetime」型なのだが、JScriptで取り回すと次のような文字列に暗黙で変換される。

var wmi = new ActiveXObject("WbemScripting.SWbemLocator").ConnectServer();
var query = "SELECT * FROM Win32_Process WHERE Name = 'firefox.exe'";

var firefox = new Enumerator(wmi.ExecQuery(query)).toArray()[0];
if( firefox ) {
  WSH.Echo( firefox.CreationDate ); // '20080618004435.514465+540'
}

要するに「年月日時分秒.マイクロ秒GMT時差」という形式。なので、こんな感じでDateにすり合わせてやるとよいかと。
var reg = /^(\d{4})(\d{2})(\d{2})(\d{2})(\d{2})(\d{2})\.(\d+)(.\d+)$/;
var parts = reg.exec( firefox.CreationDate );
WSH.Echo( new Date(
	parts[1], parts[2], parts[3],
	parts[4], parts[5], parts[6],
	parseInt( parts[7] / 1000 )
) );
// → 'Fri Jul 18 00:44:35 UTC+0900 2008'
こんなゴミゴミした正規表現じゃなくてsubstrとかでもいいんだけども。

値が配列なプロパティの扱い方

例えばWin32_NetworkAdapterConfigurationクラスのDefaultIPGatewayプロパティやIPAddressプロパティなんかがそうなのだが、値が配列の場合がある。

こういったWMIの配列は、そのままJScriptのArrayに変換されないらしい。

query = "SELECT IPAddress FROM Win32_NetworkAdapterConfiguration";
var nics = new Enumerator(wmi.ExecQuery(query)).toArray();
// 先頭のNICにIPアドレスが割りあたってるとして、
WSH.Echo( typeof(nics[0].IPAddress) ); // → unknown

しかもこの unknownオブジェクト、Enumeratorに食わせることもできない
new Enumerator( nics[0].IPAddress );
// → 'オブジェクトがコレクションではありません'例外

こういう場合はVBArrayを使うんだそうな。

VBArrayってのはEnumerator同様JScript独特のオブジェクトで、

Visual Basic のセーフ配列へアクセスする方法を提供します。
ってなオブジェクトだそうな。幸いなことに(というか、目的考えると当たり前か)toArray()でJScriptのArrayに変換することができる。

ってわけで、

WSH.Echo( new VBArray( nics[0].IPAddress ).toArray().join("\n") );
// → IPアドレスがバインドされてる数だけ出力される

VBArrayをEnumerableにするってのもよいかも。今度やってみよう。

ちなみにProperty_で動的列挙をする場合はIsArrayプロパティがtrueになっているので、それで判別できるかと。

query = "SELECT * FROM Win32_NetworkAdapterConfiguration";
nic = new Enumerator(wmi.ExecQuery(query)).toArray()[0];

new Enumerator(nic.Properties_).each( function(prop) {
	WSH.Echo( [
		"プロパティ名:", prop.Name, "\t",
		"データ型:", prop.CIMType, "\t",
		"配列?:", prop.IsArray
	].join( "" ) );
	// 例(一部)
	// プロパティ名:MACAddress  データ型:8  配列?:false
	// プロパティ名:IPAddress   データ型:8 配列?:true
} );

ギネスに届いたのかな?2008年06月19日 02時49分04秒

ふと気がつくと、19日の午前2時を過ぎていた。つまり、Firefox 3リリースキャンペーン「Download Day」が終了したわけだ。いま見に行ったら集計締め切ってるんだかどうなんだかわかんないんだけども。

で、今しがたのダウンロード数が「7,855,019」(ななひゃくはちじゅうごまんごせんとんでじゅうきゅう)という数字になっていた。

こちらのITmediaのコラムによれば、

MozillaはFirefox 2のリリース日に200万ダウンロードの記録を達成した。MicrosoftのInternet Explorer(IE)7はリリースから3日で300万ダウンロードを記録した。
ということだから、Firefox 2の4倍弱IE7の約8日分(なんだ、この比較)となるので間違いなくものすごい数字だ。

で、これギネス記録になるの?つか、そもそもこれまでの「24時間最多ダウンロードソフト」ってどのくらいの数字なんだろうか。ひょっとしてまだその記録がない「いうたもん勝ち」状態なんだろうか。ちょっとニュアンス違うけど。

ところで、dara-jが考える「最多ダウンロード記録」を狙えるソフトの条件は

  • Windows向け(またはWinを含むクロスプラットフォーム)にリリースされていて、
  • 無償でダウンロードでき、
  • ビジネス/ホームユースを問わずに誰もが日常利用し、
  • 一部のビッグタイトルの寡占状態なジャンルのソフト
ってな感じなのだが。これを満たすとなると、メジャーなウェブブラウザ、とりわけ IE と Firefox に限られるような気がする(Opera/Safariはまだここまで届かないのでは。主観だけども)。

で、夏にはIE8のリリースが控えているのだが、やはりOSに密なソフトなだけに、ある程度枯れるまでインストールを見合わせるユーザも多かろうから、当面この記録は抜けないのではなかろうか。

それより気になったのが国別のダウンロード数。アメリカの 2,457,007 が圧倒的なのはわかるとして、その他の国と比べると日本の 391,184 ってちょっと異様な感じがする。これより多いのって、ざっと見たところドイツの 538,989 と先のアメリカくらいだし。日本人、どんだけFirefox好きなのかと。まぁdara-jも当然ダウンロードしてるわけだが。

しかしダウンロードしたはいいが、常用アドオンの対応状況が遅れてるので当面見合わせだなぁ。

追記

見合わせとかいっておいて、こちらの状況まとめ記事を見たところ大分対応が進んでたし。この記事に載ってなかったAll-in-On Gesturesも「Version 0.19 is compatible with Firefox 3.」って明記されてるのでほぼ出揃ってるのか。