Reputation: 176259
I'm using WMI to start a process on a remote machine. The call to create the process returns immediately and I also get the id of the process on the remote machine.
I would like to wait for the remote process to be completed. One option would be to poll whether a process on the remote machine with the given id still exists.
However, I was wondering whether there is a better way to achieve this, maybe using native WinAPI functions?
Just for additional information, this is the code that I am currently using to start the remote process:
ConnectionOptions connOptions = new ConnectionOptions();
connOptions.Impersonation = ImpersonationLevel.Impersonate;
connOptions.EnablePrivileges = true;
connOptions.Username = domainUserName;
connOptions.Password = password;
ManagementScope manScope = new ManagementScope(String.Format(@"\\{0}\ROOT\CIMV2", host), connOptions);
manScope.Connect();
ObjectGetOptions objectGetOptions = new ObjectGetOptions();
ManagementPath managementPath = new ManagementPath("Win32_Process");
ManagementClass processClass = new ManagementClass(manScope, managementPath, objectGetOptions);
ManagementBaseObject inParams = processClass.GetMethodParameters("Create");
inParams["CommandLine"] = commandLine;
ManagementBaseObject outParams = processClass.InvokeMethod("Create", inParams, null);
Upvotes: 5
Views: 4445
Reputation: 8630
I havent had chance to check this yet,
int pid = (int)managementBaseObject["processId"];
Process remPrc = Process.GetProcessById(pid, RemoteMachine);
remPrc.WaitForExit();
Upvotes: -1
Reputation: 31928
I don't know how effective this can be, you can use ManagementEventWatcher to watch a query.
Here is something I found on the net.
WqlEventQuery wQuery =
new WqlEventQuery("Select * From __InstanceDeletionEvent Within 1 Where TargetInstance ISA 'Win32_Process'");
using (ManagementEventWatcher wWatcher = new ManagementEventWatcher(scope, wQuery))
{
bool stopped = false;
while (stopped == false)
{
using (ManagementBaseObject MBOobj = wWatcher.WaitForNextEvent())
{
if (((ManagementBaseObject)MBOobj["TargetInstance"])["ProcessID"].ToString() == ProcID)
{
// the process has stopped
stopped = true;
}
}
}
wWatcher.Stop();
}
Upvotes: 4
Reputation: 57558
If the process on the remote machine is your code then you could open up a socket on the calling machine and let the remote machine 'ping' it when it has finished.
If you want to use this method for any remote process you could have a helper app/service on the remote computer that monitors your process and returns the completed ping.
Upvotes: 1
Reputation: 4814
The native Win32 way of achieving this would be to perform a WaitForSingleObject()
on the process handle returned by CreateProcess()
, however I don't think this handle is made available to you from WMI.
This article offers another option you could consider - instead of polling the process list and waiting for your process to disappear, it repeatedly queries for process deletion events matching your process ID:
strComputer = "."
Set objWMIService = GetObject("winmgmts:\\" & strComputer & "\root\cimv2:Win32_Process")
objWMIService.Create "notepad.exe", null, null, intProcessID
Set objWMIService = GetObject("winmgmts:\\" & strComputer & "\root\cimv2")
Set colMonitoredProcesses = objWMIService.ExecNotificationQuery _
("Select * From __InstanceDeletionEvent Within 1 Where TargetInstance ISA 'Win32_Process'")
Do Until i = 1
Set objLatestProcess = colMonitoredProcesses.NextEvent
If objLatestProcess.TargetInstance.ProcessID = intProcessID Then
i = 1
End If
Loop
You could also improve on this by using a ManagementEventWatcher
object and its WaitForNextEvent
method to avoid having to poll for the deletion events.
Upvotes: 2