How to get an HTA to restart itself?
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.
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).
Take a look at the below code:
<html>
<title>HTA Restart</title>
<head>
<HTA:APPLICATION
Id="oHTA"
Border="thick"
InnerBorder="no"
Scroll="no"/>
</head>
<script language="vbscript">
Sub Restart()
CreateObject("WScript.Shell").Run "mshta " & oHTA.commandLine
window.close
End Sub
</script>
<body style="background-color: buttonface;">
<input type="button" value="Logout" onclick="Restart()" />
</body>
</html>
精彩评论