1

.hta ファイル内から JScript (VBScript とほぼ同じ) を使用して、新しいシェル コマンドを開き、その出力を取得しています。少しグーグルした後、これまでに得たものは次のとおりです。

var shell = new ActiveXObject("WScript.Shell")
var e = shell.Exec("%comspec% /c ping google.com 2>&1 ") 
while(!e.StdOut.AtEndofStream) {
    var line = e.StdOut.ReadLine()
    document.getElementById('log').value = line
}

これは機能します。ただし、非同期ではありません。while ループにより、シェル コマンドが終了するまで .hta インターフェイスがブロックされます (UI が使用できなくなります)。を削除するwhile loopと、shell.Execコマンドがブロックされないように見えるため、問題はループ内のどこかにあります。

ブロッキングの問題は、.hta 環境にいるためにのみ発生すると思います。を使用してコマンドラインからスクリプトを実行すると、発生しないようですcscript.exe

ブロック動作を回避し、コマンドの出力にリアルタイムでアクセスするにはどうすればよいですか?

4

2 に答える 2

1

おそらく、タイマーコールバックで繰り返し呼び出して少量の作業のみを行うことにより、バックグラウンドスレッドを偽造する必要があります...setTimeOut

于 2012-06-16T14:07:59.313 に答える
0

Anders が指摘したように、疑似マルチスレッド戦略を実装する必要があります。なぜなら、JScript コード (任意の関数) が実行されている限り、GUI はユーザー入力に反応しないからです。

ここに示す理由により、setTimeout() の代わりに setInterval() を使用しました。

この .hta

<html>
 <head>
  <title>Ping HTA (JScript)</title>
  <HTA:APPLICATION
    APPLICATIONNAME="PingHTA"
  >
  <SCRIPT Language="JScript" src="ping.js"></SCRIPT>
 </head>
 <body onload="onLoadBody()">
  <form name="anonymous">
   <h2>Ping HTA (JScript)</h2>
   <hr>
   <input id="bttStartPing" type="BUTTON" value="StartPing" onclick="startPing()">
   <hr>
   <textarea id="taDisplay" rows="25" cols="80"></textarea>
  </form>
 </body>
</html>

および.js

//= app globals
g_sCmd      = '%comspec% /c ping.exe /n 8 google.com 2>&1';
g_taDisplay = null;
g_PSIHandle = 0;
g_PSILock   = false;
g_oExec     = null;

//= prep for log
function onLoadBody() {
  g_taDisplay = window.document.getElementById("taDisplay");
  log("OnLoadBody() done.");
}

//= log
function log(msg) {
  g_taDisplay.value = new Date().toString() + "\n   " + msg + "\n" + g_taDisplay.value;
}

//= start job
function startPing() {
  if (0 == g_PSIHandle) {
     g_PSIHandle = setInterval(stepPing, 100);
     log('setInterval(stepPing, 100)');
     g_oExec = new ActiveXObject("WScript.Shell").Exec(g_sCmd);
     log("started " + g_sCmd);
  } else {
     log('***** Ping is running!');
  }
}

//= one step of job
function stepPing() {
  if (! g_PSILock) {
     g_PSILock = true;
     if (null !== g_oExec) {
        if (g_oExec.StdOut.AtEndofStream) {
           clearInterval(g_PSIHandle);
           g_PSIHandle = 0;
           log('StdOut.AtEndofStream, terminate ping');
           g_oExec.Terminate();
           g_oExec = null;
        } else {
           log(g_oExec.StdOut.ReadLine());
        }
     }
     g_PSILock = false;
  }
}

以下を示す必要があります。

  1. .hta で .Exec を使用すると、シェル ウィンドウが開きます (不適格な人もいます)。
  2. .hta は、そのプロセスが終了する前に、ping 出力の行を取得し始めます。
  3. プロセスの実行中にボタンをクリックすると、メッセージがping出力に散在します(ただし、反応は鈍く感じられます)

製品バージョンでは、.Exec の可能な状態の処理とエラー処理により多くの労力を費やす必要があります。

そのためには、ここで調査を開始し、「WshScriptExec Object」をグーグルで検索してください。

于 2012-06-16T22:00:40.653 に答える