2009-04-14 10 views
5

Używam WMI to start a process on a remote machine. Wywołanie procesu jest natychmiastowe, a ja otrzymuję identyfikator procesu na zdalnym komputerze.WaitForExit dla procesu na zdalnym komputerze

Chciałbym czekać na zakończenie procesu zdalnego. Jedną opcją byłoby zbadanie, czy proces na zdalnym komputerze o podanym identyfikatorze nadal istnieje.

Jednak zastanawiałem się, czy istnieje lepszy sposób, aby to osiągnąć, może używając natywnych funkcji WinAPI?

Wystarczy uzyskać dodatkowe informacje, jest to kod, który Obecnie używam, aby uruchomić zdalny proces:

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); 

Odpowiedz

4

Nie wiem, jak skuteczne może to być, możesz użyć ManagementEventWatcher, aby obejrzeć zapytanie.

Oto coś, co znalazłem w sieci.

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(); 
} 
+0

Powinieneś owinąć wWatcher i MBOobj w "przy użyciu" statysty – Simon

2

Natywna Win32 sposobem osiągnięcia tego celu byłoby przeprowadzić WaitForSingleObject() na proces uchwyt zwrócony przez CreateProcess(), ale nie sądzę, aby uchwyt ten był dostępny dla Ciebie z WMI.

This article oferuje inną opcję można rozważyć - zamiast odpytywania listę procesów i czeka na swój proces zniknąć, to wielokrotnie pyta o wydarzeniach skreślenie proces dopasowania proces 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 

mogłeś popraw to również za pomocą obiektu ManagementEventWatcher i jego metody WaitForNextEvent, aby uniknąć konieczności odpytywania o zdarzenia usuwania.

1

Jeśli proces na zdalnej maszynie jest Twój kod następnie można otworzyć gniazdo na maszynie wywołującego i niech zdalnym „ping”, kiedy to zakończyła.

Jeśli chcesz użyć tej metody dla dowolnego zdalnego procesu, możesz mieć aplikację/usługę pomocniczą na zdalnym komputerze, która monitoruje twój proces i zwraca zakończony ping.

+0

To niezły pomysł, dzięki. Byłoby to prawdopodobnie najbardziej wydajne i całkiem proste. Chciałbym jednak, aby było to jak najbardziej ogólne, więc mogę uruchomić każdy proces zdalnie. –

0

I miałaś miał okazję sprawdzić to jeszcze

int pid = (int) managementBaseObject [ "ProcessID"];

Proces remPrc = Process.GetProcessById (pid, RemoteMachine);

remPrc.WaitForExit();

+0

Nie działa Unfortunatley – Derek

Powiązane problemy