views:

97

answers:

1

I have an HTML Application that I am using to build a kiosk environment. At the end of every session (when the user clicks "Logout" or after a timeout) I want the HTA to close itself and restart*. I was wondering how I would go about achieving this programatically with VBScript.

The process should go something like this

  • User clicks "logout" or if there has been no input for 5 minutes
  • Delete temporary internet files
  • Close HTA
  • Reopen HTA

It's the reopening part I'm having trouble with.

One thing I did consider is; before closing the application, set a once-only scheduled task to run the HTA again. I don't think this is a very elegant solution though :(

Thanks for your help guys!

Cheers

Iain


.* The reason I want the HTA to restart itself is that after extended use, strange things start to happen that I think are related to bugs in mshta.exe or the IE engine. My HTA relys quite heavily on dynamically created IFRAMEs and for some reason the HTA doesn't clean them up properly once they're closed. It's kind of hard to explain the bug in detail but an example of the weirdness is; I spawn a new IFRAME and when I interrogate the DOM everything looks like it should, but what the browser renders is whatever was in the previously focussed IFRAME.

+1  A: 

When logging off or timing out, the HTA runs a restart script, then exits. The restart script waits for the MSHTA process to go away, then restarts it and exits itself.

This can be done by using WMI to scan running processes and look for an instance of MSHTA.EXE who's command line parameter contains the name of the HTA.

Here is a little example that demonstrates this.

This is a barebones HTA, save it as RestartTest.hta:

<html> <!-- RestartTest.hta -->
<head>
<title>Self Restarting HTA Test</title>

<script language="VBScript">
sub RunApp(sApp)
  CreateObject("WScript.Shell").Run(sApp)
end sub
sub LogOff()
  RunApp "cscript.exe RestartHTA.vbs"
  MsgBox "simulating delayed exit - click to close"
  window.close()
end sub
</script>
</head>

<body >
<input type="button" value="Log off" onClick="LogOff()" />
</body>
</html>

This is the restart script, save as RestartHTA.vbs:

' RestartHTA.vbs'
' wait until RestartTest.hta is not running and restart it.'

MSHTA = "mshta.exe"
sHTA = "RestartTest.hta"

say "waiting for process " & MSHTA & " with param " & sHTA & " to end"
secs = 2000

bRunning = vbTrue
do while bRunning
  if ProcessRunning(MSHTA, sHTA) then
    say "still running, wait a few seconds"
    WScript.Sleep secs
  else
    bRunning = vbFalse
  end if
loop

say "HTA not found, proceding to restart"
WScript.Sleep secs

CreateObject("WScript.Shell").Run(sHTA)
WScript.Quit

'---'

function ProcessRunning(sProcess, sParam)
  set oWMI = GetObject( _
    "winmgmts:{impersonationLevel=impersonate}!\\.\root\cimv2")
  set cProcs = oWMI.ExecQuery( _
    "select * from Win32_Process where Name = '" & sProcess & "'")

  bFound = vbFalse
  for each oProc in cProcs
    say oProc.Name & ": " & oProc.CommandLine
    if (InStr(oProc.CommandLine, sParam) > 0) then
      say "found"
      bFound = vbTrue
    else
      say "wrong param"
    end if
  next

  ProcessRunning = bFound
end function

sub Say(s)
  WScript.Echo s
end sub

'==='

You can run either one to start the cycle, then just close the HTA with it's X button to break it. Note that I run the restart script with CScript explicitly. This is just to show it's console output for demo purposes (and because I have trouble setting and keeping CScript as the default on my machine for some reason).

Todd