views:

1185

answers:

3

I have a setup executable that I need to install. When I run it, it launches a msi to do the actual install and then dies immediately. The side effect of this is it will return control back to any console you call it from before the install finishes. Depending on what machine I run it on, it can take from three to ten minutes so having the calling script sleep is undesirable. I would launch the msi directly but it complains about missing components.

I have a WSH script that uses WMI to start a process and then watch until it's pid is no longer running. Is there some way to determine the pid of the MSI the initial executable is executing, and then watch for that pid to end using WMI? Is the launching process information even associated with a process?

+1  A: 

Would doing a WMI lookup of processes that have the initial setup as the parent process do the trick? For example, if I launch an MSI from a command prompt with process id 4000, I can execute the following command line to find information about msiexec process:

c:\>wmic PROCESS WHERE ParentProcessId=4000 GET CommandLine, ProcessId 
CommandLine                                                 ProcessId
"C:\Windows\System32\msiexec.exe" /i "C:\blahblahblah.msi"  2752

That may be one way to find the information you need. Here is a demo of looking up that information in vbs:

Set objWMIService = GetObject("winmgmts:{impersonationLevel=impersonate}!\\.\root\cimv2")
Set colProcesses = objWMIService.ExecQuery("select * from Win32_Process where ParentProcessId = 4000")
For Each objProcess in colProcesses
    Wscript.Echo "Process ID: " & objProcess.ProcessId
Next

I hope this helps.

Jim Olsen
A: 

If you're using a .NET language (you can do it in Win32, but waaaay easier in .NET) you can enumerate all the Processes in the system (after your initial call to Setup.exe completes) and find all the processes which parent's PID equal to the PID of the Setup.exe - and then monitor all those processes. When they will complete - setup is complete. Make sure that they don't spawn any more child processes as well.

IgorM
A: 

This should do it.

$p1 = [diagnostics.process]::start($pathToExecutable) # this way we know the PID of the initial exe
$p2 = get-wmiobject win32_process -filter "ParentProcessId = $($p1.Id)" # using Jim Olsen's tip
(get-process -id $p2.ProcessId).WaitForExit() # voila--no messy sleeping

Unfortunately, the .NET object doesn't have a ParentProcessId property, and the WMI object doesn't have the WaitForExit() method, so we have to go back and forth.

Props to Jeffrey Snover (always) for this article.

halr9000