JS-WMI (1)

cuzic です。

さて、前回、IronRuby-WMI を作ってみましたが、本来の趣旨としては WMI を JavaScript で操作するライブラリの作成を目標としていたのですが、脱線してできあがったものでした。

前回の記事を書いたあと、プロパティを実現する方法は JScript にはないと書いておりましたが、ふと Windows には Windows Script Component (以下、WSC)という技術があることを思い出しました。

WSC というのは、JScript または VBScript のような ActiveScript に対応した言語を利用して、COMクライアントから再利用可能にする技術です。

超簡単な例を書くと increment.wsc というファイルを下記のとおり作成すると、



 test wsc
 
 
  
   
  
 
 
 

increment_client.js というファイルで、

var comobj = GetObject("script:increment.wsc");
WScript.Echo(comobj.increment(1));

とすると、さきほど作成したコンポーネントを利用することができます。

このコンポーネントでは、上記の method の代わりに などとすることで、プロパティを定義できます。

しかしながら、利用する、WMI のクラスやオブジェクトとして、何を使うかは分かりません。WMI のクラスの数は数百個存在しているので、事前に作るのは困難です。

というわけで、JScript で利用するクラスごとに、動的に WMIクラスをラップする WSC を自動生成して、その WSC を読み込んで、WMIオブジェクトをラップしたものを順に渡すことができようなスクリプトを作成してみました。

githubJS-WMI という名前で公開してみました。

JScript には Ruby の require に相当する機能がなく、WSF(Windows スクリプトファイル)を利用することが一般的ですので、WSF で今回作成した wmi.js を利用した例を書くと、


  

というスクリプトで、「メモ帳」を起動して、すぐに終了することができます。
終了するときに、その終了したプログラムの名称(notepad.exe)とそのプログラムが動いていたコンピュータの名称とそのユーザを表示させています。

ポイントとしては、

  • WMIクラス「Win32_Process」の Create メソッドを、process.Create のように呼び出し可能
  • ExecQuery メソッドは非同期な呼び出しを行うようにラップしており、返ってきたオブジェクトを1個づつ、OnObjectReady コールバック関数に委譲。
  • ExecQuery メソッドでは、where 句だけを書けば、内部で WQL クエリを自動生成。

上記の場合は、下記の WQL を生成。

SELECT * FROM Win32_Process WHERE caption = "notepad.exe"
  • instance.Caption のように自然に WMI のプロパティにアクセスが可能
  • OutParameter を返り値として表現。GetOwner メソッドのように複数 OutParameterが存在する場合は、返り値を配列とする。

といった特徴があります。

WSC を利用している点がかなりズルをしている気がしなくもありませんが、JavaScript で WMI を利用する処理を書きやすくするという目標を達成できて満足しています。