jscripthtaactivexobject

How to close a HTA window from another HTA?


I've tried to implement my own modal dialogs (Why?). I open a new window using WScript.Shell:

dlg = shell.Run(dlgPath, 1, true);

The line above creates a "semi-modal" HTA window. The script execution is stopped at this line, but the main window is still responsive. This issue is tackled within onfocusin eventhandler, which returns focus back to the new HTA window using shell.AppActivate(). This prevents even "Close Window" button to close the main window. However, in Windows7 there's a back gate to close the main window, the icon in Windows Task Bar.

If the main window is closed, a decent modal dialog should be closed as well. In this case it is not closed, since the opened HTA window is not a real child window of the main.

I can close this dialog emulator within main window's onbeforeunload handler function below.

beforeTopClose = function () {
    var wmiLocator = new ActiveXObject('WbemScripting.SWbemLocator'),
        wmiService = wmiLocator.ConnectServer('.', 'root\\CIMV2'),
        htas = new Enumerator(wmiService.ExecQuery("Select * from Win32_Process Where name = 'mshta.exe'"));
    while (!htas.atEnd()) {
        if (htas.item().CommandLine.indexOf('_tools\\dlgbase') > -1) {
            htas.item().Terminate(0);
        }
        htas.moveNext();
    }
    return;
}

Now everything looks good, there are no windows of my app left on the screen. However, when I open Windows Task Manager Processes -tab, I can see the process of the main window still running.

Why the main window is still running? Is it waiting for the end of the shell-process? What should I do in onbeforeunload handler to get the main window closed totally? If I need a different approach to this, please let me know.


Solution

  • I just realized, that I can terminate the main window as well in beforeTopClose(). Fixed code below.

    beforeTopClose = function () {
        var thisHta = {},
            thisHtaPath = lib.shell.currentDirectory + '\\index.hta', // Path to current HTA
            htas = new Enumerator(lib.wmiService.ExecQuery("Select * from Win32_Process Where name = 'mshta.exe'"));
        while (!htas.atEnd()) {
            if (htas.item().CommandLine.indexOf('_tools\\dlgbase') > -1) {
                htas.item().Terminate();
            }
            if (htas.item().CommandLine.indexOf(thisHtaPath) > -1) {
                thisHta = htas.item();
            }
            htas.moveNext();
        }
        thisHta.Terminate();
        return;
    }