<head>
<title>WMI NotificationQuery・テスト - HTA</title>
<object classid="clsid:75718C9A-F029-11D1-A1AC-00C04FB6C223" id="SWbemSink"></object>
<script type="text/javascript">
// 最後に、少しメモあり。

//・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・
var SWbemServices
function サービスの取得(){
      try{  var ele, str = (ele= document.getElementById('text0')).value // 入力欄
            SWbemServices = GetObject(str)
            ele.parentNode.innerHTML = '<small>'+str+'</small>' ; return true;
      }catch(e){ alert(e.description); return }
}///
var 実行中;
function 開始する(strQuery){  if(実行中)return
      if(!SWbemServices) if( !サービスの取得()) return
      try{  SWbemServices.ExecNotificationQueryAsync(SWbemSink, strQuery)
            実行中 = true;
      }catch(e){ alert(e.description); return }
      document.getElementById('jikkouP').innerHTML +=
            '<table id="genjikkou" class="genjikkou"><tr><td style="text-align:right;padding-right:1em">'+ strQuery
            + '<td style="line-height:1.8em;" nowrap>&nbsp;<span onclick="中止する();" class="btn" '
            + 'style="font-size:smaller;">中止</span></table>'
}///
function 中止する(){
      SWbemSink.Cancel();  実行中 = false;
      document.getElementById('jikkouP').removeChild( document.getElementById('genjikkou') )//表示の戻し
}///
onunload = function(){ if(実行中) SWbemSink.Cancel(); }///
//・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・
// イベントが起きた時に呼ばれる関数
function SWbemSink::OnObjectReady( objWbemObject, objWbemAsyncContext ){
      if(document.getElementById('chkOnce').checked) 中止する()
      var str = 詳細のHTML作文(objWbemObject)
      if(objWbemAsyncContext) str += AsyncContext作文() // 不明
      document.getElementById('disp0').innerHTML = str
}///
function SWbemSink::OnCompleted( iHResult, objWbemErrorObject, objWbemAsyncContext ){
      //alert('OnCompleted'); 実行中 = false; // SWbemSink.Cancel() の時ここに来る。
}///
function SWbemSink::OnProgress( iUpperBound, iCurrent, strMessage, objWbemAsyncContext ){
      alert( 'OnProgress\n'+ strMessage ); //中止する();
}///
function SWbemSink::OnObjectPut( objWbemObjectPath, objWbemAsyncContext ){
      alert( 'OnObjectPut\n'+ objWbemObjectPath.RelPath )
}///
//・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・
function 詳細のHTML作文(obj){
      return 詳細を作文(obj).replace(/</g,'&lt;').replace(/ /g,'&nbsp;')
            .replace(/\t/g,'&nbsp;&nbsp;&nbsp;&nbsp;').replace(/\n/g,'<br>\n')
}///
function 詳細を作文(obj){
      var str ='', n, s ;
      str += 'Properties_ '+ (obj.Properties_ ? (n= obj.Properties_.Count): ' -') +'\n'
      if(n){  var 集 = new Enumerator(obj.Properties_)
            for(; ! 集.atEnd(); 集.moveNext()) str += '\t'+ 集.item().Name +'\n'
            // 集.item().Value は空?。また、typeof(集.item()) は object だが
      }///      その .Properties_  .Path_  .ObjectText などはないらしい。
      if( s = obj.GetObjectText_() ) str += s
      return str
      // イベントから受取ったオブジェクト。クラスやインスタンスの{SWbemObject}とは異なり、
      //  中身が乏しい?。 .Properties_ と .ObjectText くらい。.Path_ の中のプロパティーは殆ど、undefined 。
      // .Properties_ で出てくるのは例えば、TargetInstance なのだが、
      //  それをイベント元のインスタンスの{SWbemObject}としては扱えない?。
}///
function AsyncContext作文(SWbemNamedValueSet){ // 不明。Async関数を使う時、自分で入れて使うものか?
      var iCount = SWbemNamedValueSet.Count
      var str = '<div>AsyncContext〈NamedValueSet〉Count:  '+ iCount +'<br>\n'
      if(iCount){  var 集 = new Enumerator(SWbemNamedValueSet)
            for(; ! 集.atEnd(); 集.moveNext())
                  str += 集.item().Name +'  :  '+ 集.item().Value +'<br>\n'
      }return str +'</div>\n'
}///
//・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・
function 入力欄へ(str){ textArea1.value += ' '+ str +' ' }///
</script>
<!--・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・-->
<style type="text/css">
body{ margin-top:0; overflow:auto;
      background-color:window; color:windowtext; }
#ctrl0{ line-height:; }
.inputText{ font-weight:bolder; font-family:monospace; } /* 1行入力欄 */
#textArea1{ font-weight:bolder; font-family:monospace; /* テキスト入力欄 */
      line-height:1.5; font-size:small;/*中にする為*/  }
.btn{  font-weight:bolder; white-space:nowrap; /* ボタン */
      border-style:outset;  border-color:threedlightshadow; cursor:pointer; 
      padding-left:2px; padding-top:2px;  }
#disp0{ padding:0.5em; overflow:auto;  }/* 結果表示 */
.word{ cursor:pointer; text-decoration:underline; }
.genjikkou{ width:90%;  }/*  */
</style>
<!--・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・-->
</head><body>
<div id="ctrl0">
      <table style="width:92%; text-align:right;"><tr>
            <td style="text-align:left;">
                  <span><input type="text" id="text0" size="40" class="inputText" value="winmgmts:root/cimv2"></span>
            <td style="text-align:right;"><input type="checkbox" id="chkOnce" checked>1回限り&nbsp;&nbsp;
            <td style="text-align:right; line-height:1.8em;">NotificationQuery
                  <span onclick="開始する( textArea1.value.replace(/\s+/g,' ') );" class="btn" title="">開始</span>
      </table>
      <textarea id="textArea1" style="width:98%; height:5em;"
            title="改行や空白の連なりは、空白一つに縮める..."></textarea><!--  -->
      <div style="font-size:x-small;">
            <span onclick="入力欄へ(this.innerHTML)" class="word">SELECT</span> *
            <span onclick="入力欄へ(this.innerHTML)" class="word">FROM</span> イベントクラス
            <span onclick="入力欄へ(this.innerHTML)" class="word">WITHIN</span> 秒数
            <span onclick="入力欄へ(this.innerHTML)" class="word">WHERE</span>
            <span onclick="入力欄へ(this.innerHTML)" class="word">TargetInstance</span>
            <span onclick="入力欄へ(this.innerHTML)" class="word">ISA</span> "クラス"
            <span onclick="入力欄へ(this.innerHTML)" class="word">AND</span> TargetInstance.プロパティー = 値
      </div>
      <div id="jikkouP" style="width:98%; text-align:right;"></div>
</div>
<div id="disp0"><!-- 結果の表示 -->
<pre style="margin:0">例の抜き書き、(この部分は削除して)
SELECT * FROM __InstanceCreationEvent WITHIN 10 WHERE TargetInstance ISA 'win32_Process'<br>
SELECT * FROM __InstanceDeletionEvent WITHIN 5 WHERE TargetInstance ISA "Win32_Process"
      AND TargetInstance.Name = "winword.exe"<br>
SELECT * FROM __InstanceModificationEvent WITHIN 600
      WHERE TargetInstance ISA "Win32_LogicalDisk"<br>
SELECT *  FROM __InstanceModificationEvent WITHIN 10 WHERE TargetInstance
      ISA "Win32_LogicalDisk"  AND TargetInstance.FreeSpace < 846000000
            AND (TargetInstance.DeviceID = "C:" OR TargetInstance.DeviceID = "D:")<br>
SELECT * FROM __InstanceModificationEvent WITHIN 20 WHERE TargetInstance
      ISA "Win32_DisplayConfiguration" AND TargetInstance.DisplayFrequency > 70
            // .DisplayFrequency は、null 、、、<br>
select * from __instancemodificationevent within 5 where targetinstance
      isa 'Win32_Processor' and targetinstance.LoadPercentage >50
            // .LoadPercentage は、null 、、、<br>
SELECT * FROM __InstanceCreationEvent WHERE TargetInstance
      ISA 'Win32_NTLogEvent' AND TargetInstance.Logfile ='Application'
            // 'Win32_NTLogEvent' は、98/Me にはない
select * from __instancecreationevent where targetinstance isa 'Win32_NTLogEvent'
SELECT * FROM __InstanceCreationEvent WHERE TargetInstance ISA 'Win32_NTLogEvent'
            AND TargetInstance.__Class = '<derived class name>'<br>
SELECT * FROM RegistryTreeChangeEvent WITHIN 10
      WHERE Hive = "HKEY_LOCAL_MACHINE" AND Rootpath = "Software"
            // winmgmts:root\default
</pre>
</div>
<!--・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・-->
<!-- ノート、
{SWbemServices}.ExecNotificationQueryAsync( {SWbemSink}, strQuery ) //の使用。

もう一つの方は、
      {SWbemEventSource} = {SWbemServices}.ExecNotificationQuery(strQuery)
      {SWbemObject} = {SWbemEventSource}.NextEvent()
この、.NextEvent() で返されるものが、
      Async() では、OnObjectReady の時に、このイベントで呼び出される関数に渡される。

{SWbemSink} を取得しておかないとならないのだが、
X SWbemSink = new ActiveXObject("WbemScripting.SWbemSink") // これでは関数の指定ができない
X <object progid="WbemScripting.SWbemSink" id="SWbemSink" ></object> // HTA じゃ progid はだめ
<object classid="clsid:75718C9A-F029-11D1-A1AC-00C04FB6C223" id="SWbemSink"></object>
      とする他ないようだが、

X SWbemSink.OnObjectReady = 関数定義; // 無効らしい
X SWbemSink::OnObjectReady = 関数定義; // 構文エラー と言われる
function SWbemSink::OnObjectReady(){ /*処理*/ } // と書かないと、だめらしい。
スクリプト要素を、イベント専用の関数の様にするやり方↓も有効。
<SCRIPT FOR="SWbemSink" EVENT="OnObjectReady(objWbemObject, objWbemAsyncContext)" type="text/javascript">
      /*処理*/
</SCRIPT>

あらかじめ、きちんとコードを書いて置かないと、ならないのか?
中途で、{SWbemSink} を追加する、呼ばれる関数を変更するなどが、難しい。
スクリプトから、object タグを作って body などに書き込むとか、
eval("function ID::OnObjectReady(){ .... }") としてしまうとか、しか思い付かない。

ちなみに、{SWbemObject}.InstancesAsync_({SWbemSink} [, ..]) などは、
      OnObjectReady の時、.Instances_()では、Set(コレクション)で返されるものが、
      一つずつ関数の引数に渡され、呼出しが繰返されるという事らしい。
      何か役に立つのだろうか。
-->