Reputation: 127
I'm not sure why but my sub function isn't working. I thought I'd followed how it should work but it just causes an error claiming my function is undefined.
<!DOCTYPE html>
<html>
<head>
<meta http-equiv="x-ua-compatible" content="IE=edge">
<title>Remote Registry</title>
<HTA:APPLICATION
APPLICATIONNAME="Remote Registry"
ID="RemReg"
VERSION="1.0.0.0"
SCROLL="no"
SINGLEINSTANCE="yes"
CONTEXTMENU="no"
NAVIGABLE="yes"
SELECTION="no"
/>
<style type="text/css">
body
{
margin: 0;
width: 130px;
height: 180px;
overflow: hidden;
font-family: arial;
font-weight: bold;
font-size: 12px;
}
</style>
</head>
<SCRIPT LANGUAGE="VBScript">
Sub CheckService
strComputer = txtBox.value
Set objWMIService = GetObject("winmgmts:" _
& "{impersonationLevel=impersonate}!\\" & strComputer & "\root\cimv2")
Set colRunningServices = objWMIService.ExecQuery _
("Select * from Win32_Service Where Name=""RemoteRegistry""")
For Each objService in colRunningServices
Output = objService.DisplayName & " is " & objService.State
Next
End Sub
</script>
<body>
<input type="text" name="TxTbox" size="30" value=DTP-> Computer to check<br />
<input id=checkservice type="button" value="Add Button" onClick="CheckService">
<div id="strComputer"></div>
</body>
</html>
What am I missing? Something really simple? I've tried alternate names for the function, moving where the VBScript is. Nothing works :sRem
Upvotes: 2
Views: 5211
Reputation: 87
Use parenthesis '()' function definition as below, it solves your issue.
Sub CheckService ()
//Your code
End Sub
Upvotes: 1
Reputation: 1995
The "[Subroutine name] is undefined" error occurs when the HTA document mode is 9 or higher and a subroutine is called from the HTML code without parentheses.
In this particular case, the code onClick="CheckService"
should have been: onClick="CheckService()"
Note that the document mode of this HTA is ambiguous because it is declared as:
<meta http-equiv="x-ua-compatible" content="IE=edge">
This causes the HTML code within the HTA to be rendered using the highest document mode provided by MSHTML.dll. It has nothing to do with the edge browser.
Someone testing this HTA on a machine that has MSHTML 8 or lower will not see an error. On any machine with MSHTML 9 or higher, the error will occur. Please note that MSHTML 9 corresponds to Internet Explorer 9, which was released in 2011. So, by 2013, when this question was posted, most machines would get an error with the posted script.
The unofficially accepted answer eliminated the error by removing the meta line, causing the HTA to run in IE 7 mode, which does not require parentheses when calling a subroutine within the HTML code. Downgrading the HTA document mode probably had no negative effects in this case, but can result in HTML/CSS code that produces different results than expected.
Further background information on HTA document modes:
HTAs should target a specific document mode to ensure that the HTML/CSS code always works as expected. The ie=edge option should only ever have been used by expert coders who include multiple HTML code sections for different MSHTML versions. This is now obsolete as any machine in production should have MSHTML 11, which came out in 2013 and will never have any further upgrades. (Note: Windows 11 includes MSHTML 11, so HTAs still work.) Typically, an HTA should target IE=9, IE=10, or IE=11. There are some specific reasons to choose one of those three document modes, but that's a whole other discussion.
HTAs should generally start with code like this:
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8" http-equiv="X-UA-Compatible" content="IE=9">
<hta:application id=oHTA>
</head>
If your HTA has no DOCTYPE or X-UA-Compatible declaration, it will run in IE 5 mode by default. If it has only the DOCTYPE declaration, it will run in IE 7 mode by default. However, if there is a FEATURE_BROWSER_EMULATION registry setting for mshta.exe, then the default mode will be whatever has been set in that registry value.
If your HTA has an X-UA-Compatible declaration, it will run in that mode regardless of any registry setting (assuming the machine doesn't have an ancient version of MSHTML), so be sure to include the meta line as shown above (Note: the UTF-8 part is optional, but helpful for using special characters).
Upvotes: 3
Reputation: 1
A little basic HTML formatting of the Services list results makes it easier to read.
<!DOCTYPE html>
<html>
<head>
<title>Remote Registry</title>
<hta:application
applicationname="Remote Registry"
id="RemReg"
version="1.0.0.0"
scroll="YES"
singleinstance="yes"
contextmenu="no"
navigable="yes"
selection="no"
/>
<style type="text/css">
body
{
margin: 0;
width: 100%;
height: 100%;
overflow: hidden;
font-family: arial;
font-weight: bold;
font-size: 12px;
}
</style>
<script type="text/vbscript" id="EnumMyServices">
' <!--
Sub EnumMyServices()
dim WMI, objs, obj
'
set WMI = GetObject("WinMgmts:")
on error resume next
set objs = WMI.InstancesOf("Win32_Service")
if err = 0 Then
if objs.count > 0 then
strHTML="<table border=1 align=left cellpadding=4 cellspacing=0>"
strHTML=strHTML & "<tr>"
strHTML=strHTML & "<th>DisplayName</th>"
strHTML=strHTML & "<th>State</th>"
strHTML=strHTML & "<th>StartMode</th>"
strHTML=strHTML & "</tr>"
for each obj in objs
ObName = obj.DisplayName
ObState = obj.State
ObStartMode = obj.StartMode
strHTML=strHTML & "<tr>"
strHTML=strHTML & "<td>" & ObName & "</td>"
strHTML=strHTML & "<td>" & ObState & "</td>"
strHTML=strHTML & "<td>" & ObStartMode & "</td>"
strHTML=strHTML & "</tr>"
next
else
strHTML="<table border=1 align=left cellpadding=4 cellspacing=0>"
strHTML=strHTML & "<tr>"
strHTML=strHTML & "<th>Attention</th>"
strHTML=strHTML & "</tr>"
strHTML=strHTML & "<tr>"
strHTML=strHTML & "<td>no services found!</td>"
strHTML=strHTML & "</tr>"
end if
else
strHTML="<table border=1 align=left cellpadding=4 cellspacing=0>"
strHTML=strHTML & "<tr>"
strHTML=strHTML & "<th>Error!</th>"
strHTML=strHTML & "</tr>"
strHTML=strHTML & "<tr>"
strHTML=strHTML & "<td>An error occurred whilst trying to enum services!</td>"
strHTML=strHTML & "</tr>"
end if
set WMI=nothing
set objs = nothing
set obj = nothing
on error goto 0
strHTML=strHTML & "</table>"
strHTML=strHTML & "<p>"
Results.InnerHTML=strHTML
end sub
' -->
</script>
<script type="text/vbscript" id="EnumMyPrinters">
' <!--
Sub EnumMyPrinters()
dim WMI, objs, obj
'
set WMI = GetObject("WinMgmts:")
on error resume next
set objs = WMI.InstancesOf("Win32_Printer")
if err = 0 Then
if objs.count > 0 then
window.document.getElementById("Results").innerText = "PRINTERS" & chr(13)
for each obj in objs
window.document.getElementById("Results").innerText = window.document.getElementById("Results").innerText & obj.Description & chr(13)
next
else
window.document.getElementById("Results").innerText = "PRINTERS" & chr(13)
window.document.getElementById("Results").innerText = "no printers found!" & chr(13)
end if
else
window.document.getElementById("Results").innerText = "PRINTERS" & chr(13)
window.document.getElementById("Results").innerText = "An error occurred whilst trying to enum printers!" & chr(13)
end if
set WMI=nothing
set objs = nothing
set obj = nothing
on error goto 0
end sub
' -->
</script>
<script type="text/vbscript" id="EnumMyProcesses">
' <!--
Sub EnumMyProcesses()
dim WMI, objs, obj
'
set WMI = GetObject("WinMgmts:")
on error resume next
set objs = WMI.InstancesOf("Win32_Process")
if err = 0 Then
if objs.count > 0 then
window.document.getElementById("Results").innerText = "PROCESSES" & chr(13)
for each obj in objs
window.document.getElementById("Results").innerText = window.document.getElementById("Results").innerText & obj.Description & chr(13)
next
else
window.document.getElementById("Results").innerText = "PROCESSES" & chr(13)
window.document.getElementById("Results").innerText = "no processes found!" & chr(13)
end if
else
window.document.getElementById("Results").innerText = "PROCESSES" & chr(13)
window.document.getElementById("Results").innerText = "An error occurred whilst trying to enum processes!" & chr(13)
end if
set WMI=nothing
set objs = nothing
set obj = nothing
on error goto 0
end sub
' -->
</script>
<script type="text/vbscript" id="EnumMyProcessors">
' <!--
Sub EnumMyProcessors()
dim WMI, objs, obj
'
set WMI = GetObject("WinMgmts:")
on error resume next
set objs = WMI.InstancesOf("Win32_Processor")
if err = 0 Then
if objs.count > 0 then
window.document.getElementById("Results").innerText = "PROCESSORS" & chr(13)
for each obj in objs
window.document.getElementById("Results").innerText = window.document.getElementById("Results").innerText & obj.Description & chr(13)
next
else
window.document.getElementById("Results").innerText = "PROCESSORS" & chr(13)
window.document.getElementById("Results").innerText = "no processors found!" & chr(13)
end if
else
window.document.getElementById("Results").innerText = "PROCESSORS" & chr(13)
window.document.getElementById("Results").innerText = "An error occurred whilst trying to enum processors!" & chr(13)
end if
set WMI=nothing
set objs = nothing
set obj = nothing
on error goto 0
end sub
' -->
</script>
</head>
<body>
<input id="btnServices" name="btnServices" type="button" value="Services" onclick="EnumMyServices" />
<input id="btnPrinters" name="btnPrinters" type="button" value="Printers" onclick="EnumMyPrinters" />
<input id="btnProcesses" name="btnProcesses" type="button" value="Processes" onclick="EnumMyProcesses" />
<input id="btnProcessors" name="btnProcessors" type="button" value="Processors" onclick="EnumMyProcessors" />
<p>
<Font size="3" face="Tahoma"><h3>Results:</Font><hr></h3>
<div id="Results"> </div>
</body>
</html>
Upvotes: 0
Reputation: 2089
Change your code to the below and use the reference link above for your WMI call and you should be fine.
<!DOCTYPE html>
<html>
<head>
<meta http-equiv="x-ua-compatible" content="IE=edge" />
<title>Remote Registry</title>
<hta:application
applicationname="Remote Registry"
id="RemReg"
version="1.0.0.0"
scroll="no"
singleinstance="yes"
contextmenu="no"
navigable="yes"
selection="no"
/>
<style type="text/css">
body
{
margin: 0;
width: 130px;
height: 180px;
overflow: hidden;
font-family: arial;
font-weight: bold;
font-size: 12px;
}
</style>
</head>
<script type="text/vbscript" id="CheckService">
Sub CheckService()
'
dim strComputer
'
strComputer = window.document.getElementById("txtComputer").value
' PLACE YOUR CALL TO WMI HERE - (I'm not sure mine is correct!)
'Set objServices = GetObject( _
"winmgmts:{impersonationLevel=impersonate," _
& "authenticationLevel=pktPrivacy}!\\" _
& strcomputer & "/root/cimv2")
'
Set colRunningServices = objWMIService.ExecQuery ("Select * from Win32_Service Where Name=" & chr(34) & "RemoteRegistry" & chr(34))
if colRunningServices.items.count - 1 > 0 Then
For Each objService in colRunningServices
window.document.getElementById("Results").innerText = window.document.getElementById("Results").innerText & objService.DisplayName & " is " & objService.State & chr(13)
Next
else
window.document.getElementById("Results").innerText = "No running services found at this time!"
end if
'
End Sub
</script>
<body>
<input type="text" id="txtComputer" name="txtComputer" size="30" value="Dtp-"/> Computer to check<br />
<input id="btnCheckService" name="btnCheckService" type="button" value="Add Button" onclick="CheckService" />
<div id="Results"></div>
</body>
</html>
I've modified the code to remove the META tag and add some sample subroutines for you.
What I did was saved the HTA to my desktop and executed from there, by double clicking on it.
<!DOCTYPE html>
<html>
<head>
<title>Remote Registry</title>
<hta:application
applicationname="Remote Registry"
id="RemReg"
version="1.0.0.0"
scroll="no"
singleinstance="yes"
contextmenu="no"
navigable="yes"
selection="no"
/>
<style type="text/css">
body
{
margin: 0;
width: 130px;
height: 180px;
overflow: hidden;
font-family: arial;
font-weight: bold;
font-size: 12px;
}
</style>
</head>
<script type="text/vbscript" id="EnumMyServices">
' <!--
Sub EnumMyServices()
dim WMI, objs, obj
'
set WMI = GetObject("WinMgmts:")
on error resume next
set objs = WMI.InstancesOf("Win32_Service")
if err = 0 Then
if objs.count > 0 then
window.document.getElementById("Results").innerText = "SERVICES" & chr(13)
for each obj in objs
window.document.getElementById("Results").innerText = window.document.getElementById("Results").innerText & obj.Description & chr(13)
next
else
window.document.getElementById("Results").innerText = "SERVICES" & chr(13)
window.document.getElementById("Results").innerText = "no services found!" & chr(13)
end if
else
window.document.getElementById("Results").innerText = "SERVICES" & chr(13)
window.document.getElementById("Results").innerText = "An error occurred whilst trying to enum services!" & chr(13)
end if
set WMI=nothing
set objs = nothing
set obj = nothing
on error goto 0
end sub
' -->
</script>
<script type="text/vbscript" id="EnumMyPrinters">
' <!--
Sub EnumMyPrinters()
dim WMI, objs, obj
'
set WMI = GetObject("WinMgmts:")
on error resume next
set objs = WMI.InstancesOf("Win32_Printer")
if err = 0 Then
if objs.count > 0 then
window.document.getElementById("Results").innerText = "PRINTERS" & chr(13)
for each obj in objs
window.document.getElementById("Results").innerText = window.document.getElementById("Results").innerText & obj.Description & chr(13)
next
else
window.document.getElementById("Results").innerText = "PRINTERS" & chr(13)
window.document.getElementById("Results").innerText = "no printers found!" & chr(13)
end if
else
window.document.getElementById("Results").innerText = "PRINTERS" & chr(13)
window.document.getElementById("Results").innerText = "An error occurred whilst trying to enum printers!" & chr(13)
end if
set WMI=nothing
set objs = nothing
set obj = nothing
on error goto 0
end sub
' -->
</script>
<script type="text/vbscript" id="EnumMyProcesses">
' <!--
Sub EnumMyProcesses()
dim WMI, objs, obj
'
set WMI = GetObject("WinMgmts:")
on error resume next
set objs = WMI.InstancesOf("Win32_Process")
if err = 0 Then
if objs.count > 0 then
window.document.getElementById("Results").innerText = "PROCESSES" & chr(13)
for each obj in objs
window.document.getElementById("Results").innerText = window.document.getElementById("Results").innerText & obj.Description & chr(13)
next
else
window.document.getElementById("Results").innerText = "PROCESSES" & chr(13)
window.document.getElementById("Results").innerText = "no processes found!" & chr(13)
end if
else
window.document.getElementById("Results").innerText = "PROCESSES" & chr(13)
window.document.getElementById("Results").innerText = "An error occurred whilst trying to enum processes!" & chr(13)
end if
set WMI=nothing
set objs = nothing
set obj = nothing
on error goto 0
end sub
' -->
</script>
<script type="text/vbscript" id="EnumMyProcessors">
' <!--
Sub EnumMyProcessors()
dim WMI, objs, obj
'
set WMI = GetObject("WinMgmts:")
on error resume next
set objs = WMI.InstancesOf("Win32_Processor")
if err = 0 Then
if objs.count > 0 then
window.document.getElementById("Results").innerText = "PROCESSORS" & chr(13)
for each obj in objs
window.document.getElementById("Results").innerText = window.document.getElementById("Results").innerText & obj.Description & chr(13)
next
else
window.document.getElementById("Results").innerText = "PROCESSORS" & chr(13)
window.document.getElementById("Results").innerText = "no processors found!" & chr(13)
end if
else
window.document.getElementById("Results").innerText = "PROCESSORS" & chr(13)
window.document.getElementById("Results").innerText = "An error occurred whilst trying to enum processors!" & chr(13)
end if
set WMI=nothing
set objs = nothing
set obj = nothing
on error goto 0
end sub
' -->
</script>
<body>
<div id="mycontainer">
Results:<br />
<div id="Results"></div>
</div><br /><br />
<input id="btnServices" name="btnServices" type="button" value="Services" onclick="EnumMyServices" />
<input id="btnPrinters" name="btnPrinters" type="button" value="Printers" onclick="EnumMyPrinters" />
<input id="btnProcesses" name="btnProcesses" type="button" value="Processes" onclick="EnumMyProcesses" />
<input id="btnProcessors" name="btnProcessors" type="button" value="Processors" onclick="EnumMyProcessors" />
</body>
</html>
Upvotes: 1