Link to home
Start Free TrialLog in
Avatar of tighec
tighec

asked on

How can I get the process id of a currently running HTA applicaiton?

If I know the commandline exactly then I can search WIN32_Process and get it that way however if more than one insance running then it would not return the current process, but a collection with all the instances.
One (ugly) way to do it is the code below, essentially using exec to launch a new process, then get the parentprocessid of that process.
Dim oExec
Set oExec = objShell.exec("%comspec% /c dir")
Set colItems = objWMIService.ExecQuery("SELECT * FROM Win32_Process Where ProcessId = " & oExec.processid , "WQL", wbemFlagReturnImmediately + wbemFlagForwardOnly)
For Each objItem In colItems
	iHTAProcessID = objItem.ParentProcessId
Next

Open in new window

Avatar of TakedaT
TakedaT
Flag of United States of America image

Is this what you are looking for?  It builds an array of which each element is a different process ID for a given running process.  At the bottom, I have it set to echo each process id, but you can do whatever you would like with it.
strComputer="."
Dim arrProcID()
 
Set objWMIService = GetObject("winmgmts:" _
& "{impersonationLevel=impersonate}!\\" _
& strComputer & "\root\cimv2")
 
 
CheckProcess("mshta.exe")
Function CheckProcess(strProcessToCheck)
	iCount=0
 
	Set colProcess = objWMIService.ExecQuery _
	("Select * from Win32_Process Where Name = '"&strProcessToCheck&"'")
	For Each objProcess in colProcess
		iCount=iCount+1
	Next
	redim arrProcID(iCount-1)
	i=0
	For Each objProcess in colProcess
		arrProcID(i) = objProcess.ProcessId
		i=i+1
	Next
End Function
n=0
Do until n=ubound(arrProcID)+1
	wscript.echo arrProcID(n)
	n=n+1
Loop

Open in new window

Avatar of tighec
tighec

ASKER

No that will only give an array of processids for all the mshta.exe processes, not the pid of the current process (runing as an mshta).  Essentially I need to know the process of the hta that is running so I can see if I have any child processes outstanding. select * from win32_process where parentprocessid = me.processid...  i
the last PID should always be the last one to get executed, which at the time will be the HTA whne you run it.
Dim strPID
Set objSWbemServices = GetObject ("WinMgmts:Root\Cimv2")
Set colProcess = objSWbemServices.ExecQuery ("Select * From Win32_Process")
 
For Each objProcess In colProcess
If InStr (objProcess.CommandLine, WScript.ScriptName) <> 0 Then
'WScript.Echo objProcess.Name, objProcess.ProcessId, objProcess.CommandLine
strPID = objProcess.ProcessId
End If
Next
 
Msgbox strPID

Open in new window

Avatar of tighec

ASKER

Can't depend on that working in every case.
The below code is a sample of a non singel instance hta.
If you double click it twice in quick succession, then the msgbox that pops up will show the same processid for each instance whcih is obviously wrong.  It takes almost a second for an hta instance to initiate leading to this potential error.
By switching out the comments in the "MasterSub" routine it goes back to the way I currently have it working, which returns the correct id.
I guess I was just hoping there was some easy way to retrieve the process of the running hta but maybe not :(
<html>
<head>
<script language="vbscript"></script>
 
 
<title>Superstation launch script v1.0</title>
 
 
<HTA:APPLICATION
	ID="App_ID"
	ApplicationName="App"
	SingleInstance="No"
>
 
 
<script language="vbscript">
Option Explicit
'Define global script objects
Const wbemFlagReturnImmediately = &h10
Const wbemFlagForwardOnly = &h20
 
Dim objWMIService,objShell
Set objWMIService = GetObject("winmgmts:\\.\root\CIMV2")
Set objShell = CreateObject("WScript.Shell")
 
Sub MasterSub
	'GetPID_By_Executing
	GetPID_By_LastInstance
	Self.Close
End Sub
 
Sub  GetPID_By_Executing
Dim oExec, colItems, objItem, iHTAProcessID
	Set oExec = objShell.exec("%comspec% /c dir")
	Set colItems = objWMIService.ExecQuery("SELECT * FROM Win32_Process Where ProcessId = " & oExec.processid , "WQL", wbemFlagReturnImmediately + wbemFlagForwardOnly)
	For Each objItem In colItems
		iHTAProcessID = objItem.ParentProcessId
	Next
	msgbox iHTAProcessID 
End Sub
 
Sub  GetPID_By_LastInstance
Dim strPID, objProcess, colProcess
	Set colProcess = objWMIService.ExecQuery ("Select * From Win32_Process")
	For Each objProcess In colProcess
		If InStr (objProcess.CommandLine, app_id.commandline) <> 0 Then
			strPID = objProcess.ProcessId
		End If
	Next
	Msgbox strPID
End Sub
</script>
 
</head>
<body onload="MasterSub"></body>
</html>

Open in new window

yes, i see. If i double click as fast as i can, the same happens with the .vbs. What about putting a small 200ms delay in there? will you be double clicking the HTA that fast, or you just trying to make this %100 fool proof
Avatar of tighec

ASKER

A 200ms in where? The problem is the user could launch the applciiation numerous times, nothing in the code can prevent that. I think the way I currently have it will have to suffice. For the most part, grabbing the last ocurance should work but I'd rather go with something that is as foolproof as possible.
Can't you just set the SINGLEINSTANCE = yes in the HTA:APPLICATION tag
I thought about that, but after testing it on my pc, I noticed that even with one window open after singleinstance=yes, there are still multiple mshta.exe process generated.  
ya, i just did some tests, and if i double click as fast as i can, i can easily open up several differen windows. I get a few access denied errors, but the processing seems slow. When I removed my onload function, it worked fine, no errors and only 1 instance. So, this problem just may suffer from poor implimentation/speed of how the HTA loads.
Avatar of tighec

ASKER

One instance isn't an option.  For the most part that might work for what we are trying to do but not in all.. already tried that.
Doesn't matter if it is called in the onload event or anywhere else, so long as a new instance opens up after the first one that is what will be picked up by enumerating through win32_process
HTA in general takes about 1 second just to instantiate (and that is on a super fast machine)... mega drawback to using hta's in the first place.
One dirty way you can maybe do it is to have the code of the hta dumped into a randomly named file and then to run said file from vbscript.  Then each running program will have a different filename to check for in the wmi.  Just an idea, but it might work.
ASKER CERTIFIED SOLUTION
Avatar of tighec
tighec

Link to home
membership
This solution is only available to members.
To access this solution, you must be a member of Experts Exchange.
Start Free Trial