在我的HTA应用程序中,有一些操作正在服务器上执行一些非常耗时的任务。例如,一个操作使用一个旧的ActiveX组件来读取特定文件夹(文件夹中0- ~200个文件)中文件的一些文件属性(如主题和注释)。
最初,这是通过设置间隔并逐个文件读取fileproperties来实现的。当使用快速本地连接连接到服务器时,应用程序的速度减慢是可以接受的。但现在,随着远程工作的显著增加,以及远程连接比内部网连接慢很多,该间隔不再适合该任务。
为了使应用程序在文件安全搜索过程中速度更快,我将代码外包给了wsh工作。结果存储在一个文件中,该文件存在一个间隔(5秒)。然而,一些用户仍然体验到应用程序的显著减速,即使在以上述5秒的间隔轮询文件存在的情况下也是如此。
现在我想知道,是否存在事件或其他内部机制,我可以使用它们来检测wsh脚本何时完成了它的工作?如果可能,甚至可能有一种方法可以将结果直接从wsh作业发送到HTA,而根本不使用中间临时文件?
以下是在wsh文件和HTA应用程序中执行的实际任务的一些简化代码。HTA有HTML5 DTD,它使用IE11在边缘模式下运行。ui是一个实用程序库,引用的属性名希望能够足够准确地描述用法。
WSF:
<package>
<job id="getFileProps">
<script language="JScript">
(function () {
var topRoot = WScript.Arguments(0), // The starting folder <String>
fso = WScript.CreateObject('Scripting.FileSystemObject'), // Filesystem object <ActiveXObject>
fileProps = readProps(topRoot), // Fileprops, the result <Array>
file; // The result file to read in HTA <FileObject>
function readProps (root) {
var fileProperties = [];
// A bunch of code reading the fileproperties on a disk
return fileProperties;
}
file = fso.openTextFile(topRoot + '\\$fileprops$.txt', 2, true);
file.Write(fileProps.join(',');
file.Close();
WScript.Quit();
)());
</script>
</job>
</package>JSCRIPT:
ui.winShell.Exec('WScript //Job:getFileProps ' + '"' + ui.appRoot + '"');
function fpCheck () {
var file, fileProps;
try {
file = ui.fileIO.OpenTextFile('$fileprops$.txt', 1, false);
} catch (err) {
file && file.Close();
setTimeout(fpCheck, 5000);
return;
}
// Write the fileprops to the view
}如果有人对文件属性读取器感兴趣,它的名称是DSOFile.OleDocumentProperties。它起源于深度互联网档案的某个地方,但我想不起来我是从哪里加载的。
发布于 2020-12-16 04:04:36
最终,您需要的是进程间通信。
HTA和WSH都没有为IPC提供内置的东西。
因此,我将分享一个我很少使用的解决方案。
诀窍是在两端使用一个共享对象,就像客户端-服务器场景一样。
我们将使用Internet Explorer object作为IPC服务器,我们将使用的方法是GetProperty和PutProperty。
由于可以使用Shell objects的Windows()方法枚举Internet Explorer窗口,因此可以从另一个应用程序访问在HTA中创建的对象。
检查并创建以下两个文件,然后启动test.hta并单击Start WSF按钮。
test.hta
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<meta http-equiv="X-UA-Compatible" content="IE=Edge">
<title>IPC</title>
<script>
sharedObject = {
sendData: function(data){
// blocking here is not a good idea
// so we process the data within another callback
// leaving the method as soon as possible
var receivedData = data;
setTimeout(function(){alert("Data received: " + receivedData)}, 50);
}
};
shareName = "ipcShare";
serverId = createIPCServer(shareName);
function createIPCServer(shareName){
var ie = new ActiveXObject("InternetExplorer.Application");
ie.PutProperty(shareName, sharedObject);
window.onbeforeunload = function(){ ie.Quit(); };
return ie.HWND; // window handle
}
function starWSFJob() {
alert("please wait about 5 seconds...");
var wshShell = new ActiveXObject("Wscript.Shell");
wshShell.Run('wscript.exe test.wsf //Job:TestIPC /serverId:"' + serverId + '" /shareName:"' + shareName + '"');
}
</script>
</head>
<body>
<button onclick="starWSFJob()">Start WSF</button>
</body>
</html>test.wsf
<package>
<job id="TestIPC">
<script language="JScript">
function getSharedObject(serverId, shareName){
var shellApp = new ActiveXObject("Shell.Application");
var windows = new Enumerator(shellApp.Windows());
for (;!windows.atEnd();windows.moveNext()){
var window = windows.item();
if(window.HWND == serverId) {
return window.GetProperty(shareName);
}
}
}
function App() {
var serverId = Number(WScript.Arguments.Named("serverId"));
var shareName = WScript.Arguments.Named("shareName");
var sharedObject = getSharedObject(serverId, shareName);
if(!sharedObject){
WScript.Echo("shared object not found.");
return 1;
}
// simulate long running job
WScript.Sleep(5000);
// send data
sharedObject.sendData("Hello from WSF Job!");
return 0;
}
WScript.Quit(App());
</script>
</job>
</package>发布于 2020-12-15 05:39:57
您的场景是否支持使用字典对象或数组列表来仅存储文件名和lastupdated,以及仅检索新的或更改的文件(和删除)的完整属性集(放入第二个列表中)。我猜这取决于文件的来去和更新的频率。如果大多数详细信息在轮询之间没有更改,这可能比生成整个文件属性数据集更快。
https://stackoverflow.com/questions/65291636
复制相似问题