2009-04-14 18 views
5

Sto usando WMI to start a process on a remote machine. La chiamata per creare il processo ritorna immediatamente e ottengo anche l'id del processo sulla macchina remota.WaitForExit per un processo su un computer remoto

Desidero attendere il completamento del processo remoto. Un'opzione consisterebbe nel sondare se esiste ancora un processo sulla macchina remota con l'ID specificato.

Tuttavia, mi chiedevo se c'è un modo migliore per raggiungere questo obiettivo, magari utilizzando le funzioni native di WinAPI?

Solo per ulteriori informazioni, questo è il codice che sono attualmente in uso per avviare il processo remoto:

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

risposta

4

Non so quanto possa essere efficace, è possibile utilizzare ManagementEventWatcher per guardare una query.

Ecco qualcosa che ho trovato in rete.

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

Si dovrebbe includere wWatcher e MBOobj in uno statista "using" – Simon

2

Il modo nativo Win32 del raggiungimento di questo sarebbe quello di eseguire un WaitForSingleObject() sul processo handle restituito da CreateProcess(), tuttavia non penso che questo handle sia reso disponibile all'utente da WMI.

This article offre un'altra opzione che si potrebbe prendere in considerazione - invece di polling lista dei processi e di attesa per il processo a scomparire, interroga ripetutamente per eventi processo di eliminazione corrispondente alla vostra ID del processo:

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 

Si potrebbe anche migliorare su questo utilizzando un oggetto e il suo metodo WaitForNextEvent per evitare di dover eseguire il polling per gli eventi di eliminazione.

1

Se il processo sulla macchina remota è il codice allora si potrebbe aprire un socket sulla macchina chiamata e lasciare che la macchina remota 'ping' che quando ha finito.

Se si desidera utilizzare questo metodo per qualsiasi processo remoto, è possibile avere un'app/servizio di supporto sul computer remoto che monitora il processo e restituisce il ping completato.

+0

Questa è una buona idea, grazie. Questo sarebbe probabilmente il più efficiente e abbastanza semplice. Tuttavia, vorrei mantenerlo il più generico possibile in modo da poter avviare qualsiasi processo da remoto. –

0

io ho mai avuto possibilità di controllare questo ancora,

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

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

remPrc.WaitForExit();

+0

non funziona sfortunatamente – Derek

Problemi correlati