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;
}
}
以下を示す必要があります。
- .hta で .Exec を使用すると、シェル ウィンドウが開きます (不適格な人もいます)。
- .hta は、そのプロセスが終了する前に、ping 出力の行を取得し始めます。
- プロセスの実行中にボタンをクリックすると、メッセージがping出力に散在します(ただし、反応は鈍く感じられます)
製品バージョンでは、.Exec の可能な状態の処理とエラー処理により多くの労力を費やす必要があります。
そのためには、ここで調査を開始し、「WshScriptExec Object」をグーグルで検索してください。