正如 Anders 所指出的,您需要实现伪多线程策略,因为只要执行 JScript 代码(任何函数),您的 GUI 就不会对任何用户输入做出反应。
出于此处给出的原因,我使用了 setInterval() 而不是 setTimeout() 。
这个.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 将打开一个 shell 窗口(对于某些人来说,这是不合格的)
- .hta 将开始拾取 ping 输出行,在该过程终止之前
- 在进程运行时单击按钮将在消息中穿插 ping 输出(尽管反应感觉迟缓)
生产版本将不得不花费更多的精力来处理 .Exec 的可能状态和错误处理。
为此,请在此处开始您的研究并在 Google 上搜索“WshScriptExec 对象”。