Come posso sapere se un processo è in esecuzione?

Quando ottengo un riferimento a un System.Diagnostics.Process , come posso sapere se un processo è attualmente in esecuzione?

Questo è un modo per farlo con il nome:

 Process[] pname = Process.GetProcessesByName("notepad"); if (pname.Length == 0) MessageBox.Show("nothing"); else MessageBox.Show("run"); 

È ansible eseguire il ciclo di tutto il processo per ottenere l’ID per la successiva manipolazione:

 Process[] processlist = Process.GetProcesses(); foreach(Process theprocess in processlist){ Console.WriteLine("Process: {0} ID: {1}", theprocess.ProcessName, theprocess.Id); } 

Questo è il modo più semplice che ho trovato dopo aver usato il riflettore. Ho creato un metodo di estensione per questo:

 public static class ProcessExtensions { public static bool IsRunning(this Process process) { if (process == null) throw new ArgumentNullException("process"); try { Process.GetProcessById(process.Id); } catch (ArgumentException) { return false; } return true; } } 

Il metodo Process.GetProcessById(processId) chiama il metodo ProcessManager.IsProcessRunning(processId) e genera ArgumentException nel caso in cui il processo non esista. Per qualche motivo la class ProcessManager è interna …

Soluzione sincrona:

 void DisplayProcessStatus(Process process) { process.Refresh(); // Important if(process.HasExited) { Console.WriteLine("Exited."); } else { Console.WriteLine("Running."); } } 

Soluzione asincrona:

 void RegisterProcessExit(Process process) { // NOTE there will be a race condition with the caller here // how to fix it is left as an exercise process.Exited += process_Exited; } static void process_Exited(object sender, EventArgs e) { Console.WriteLine("Process has exited."); } 

reshefm ha avuto una bella risposta; tuttavia, non tiene conto di una situazione in cui il processo non è mai stato avviato.

Ecco una versione modificata di ciò che ha pubblicato.

  public static bool IsRunning(this Process process) { try {Process.GetProcessById(process.Id);} catch (InvalidOperationException) { return false; } catch (ArgumentException){return false;} return true; } 

Ho rimosso la sua ArgumentNullException perché in realtà suppone di essere un’eccezione di riferimento null e viene comunque lanciata dal sistema e ho anche considerato la situazione in cui il processo non è mai iniziato o il metodo close () è stato utilizzato per chiudere il processi.

Questo dovrebbe essere un one-liner:

 public static class ProcessHelpers { public static bool IsRunning (string name) => Process.GetProcessesByName(name).Length > 0; } 

Dipende da quanto affidabile vuoi che questa funzione sia. Se vuoi sapere se la particolare istanza di processo che hai è ancora in esecuzione e disponibile con una precisione del 100%, non sei fortunato. Il motivo è che dall’object del processo gestito ci sono solo 2 modi per identificare il processo.

Il primo è l’ID processo. Sfortunatamente, gli ID di processo non sono unici e possono essere riciclati. La ricerca nell’elenco dei processi per un ID corrispondente ti dirà solo che esiste un processo con lo stesso id in esecuzione, ma non è necessariamente il tuo processo.

Il secondo elemento è Process Handle. Ha lo stesso problema però come l’ID ed è più difficile da lavorare.

Se stai cercando un’affidabilità di medio livello, è sufficiente controllare l’attuale elenco dei processi per un processo con lo stesso ID.

Process.GetProcesses() è la strada da percorrere. Ma potrebbe essere necessario utilizzare uno o più criteri diversi per trovare il processo, a seconda di come è in esecuzione (vale a dire come un servizio o un’app normale, indipendentemente dal fatto che abbia o meno una barra del titolo).

Forse (probabilmente) sto leggendo la domanda in modo errato, ma stai cercando la proprietà HasExited che ti dirà che il processo rappresentato dall’object Process è uscito (normalmente o no).

Se il processo a cui si ha un riferimento ha un’interfaccia utente, è ansible utilizzare la proprietà Responding per determinare se l’interfaccia utente sta rispondendo all’input dell’utente o meno.

È inoltre ansible impostare EnableRaisingEvents e gestire l’evento Exited (che viene inviato in modo asincrono) o chiamare WaitForExit () se si desidera bloccare.

È ansible istanziare un’istanza di processo una volta per il processo desiderato e continuare a tracciare il processo utilizzando tale object .NET Process (continuerà a essere rintracciato finché non si chiama Chiudi su tale object .NET in modo esplicito, anche se il processo di tracciamento è morto [questo è per essere in grado di darti il ​​tempo di chiusura, aka ExitTime ecc.])

Citando http://msdn.microsoft.com/en-us/library/fb4aw7b8.aspx :

Quando un processo associato termina (ovvero, quando viene arrestato dal sistema operativo tramite una terminazione normale o anormale), il sistema memorizza le informazioni amministrative sul processo e ritorna al componente che aveva chiamato WaitForExit. Il componente Processo può quindi accedere alle informazioni, che include ExitTime, utilizzando l’handle per il processo chiuso.

Poiché il processo associato è terminato, la proprietà Handle del componente non punta più a una risorsa di processo esistente. Invece, l’handle può essere utilizzato solo per accedere alle informazioni del sistema operativo sulla risorsa di processo. Il sistema è a conoscenza delle maniglie per i processi che non sono stati rilasciati dai componenti di processo, pertanto conserva le informazioni ExitTime e Handle in memoria fino a quando il componente Process libera le risorse in modo specifico. Per questo motivo, ogni volta che chiami Start per un’istanza di processo, chiama Chiudi quando il processo associato è terminato e non hai più bisogno di informazioni amministrative su di esso. Chiudi libera la memoria allocata al processo terminato.

Ho provato la soluzione di Coincoin:
Prima di elaborare un file, lo copio come un file temporaneo e lo apro.
Quando ho finito, chiudo l’applicazione se è ancora aperta ed elimina il file temporaneo:
Io uso solo una variabile di processo e la controllo in seguito:

 private Process openApplication; private void btnOpenFile_Click(object sender, EventArgs e) { ... // copy current file to fileCache ... // open fileCache with proper application openApplication = System.Diagnostics.Process.Start( fileCache ); } 

Più tardi chiudo l’applicazione:

  ... openApplication.Refresh(); // close application if it is still open if ( !openApplication.HasExited() ) { openApplication.Kill(); } // delete temporary file System.IO.File.Delete( fileCache ); 

Funziona (finora)

  string process="notepad"; if (Process.GetProcessesByName(process).Length == 0) { MessageBox.Show("Working"); } else { MessageBox.Show("Not Working"); } 

inoltre puoi usare un timer per controllare il processo ogni volta

Nonostante l’API supportata dai framework .Net per quanto riguarda il controllo del processo esistente per ID processo, tali funzioni sono molto lente. Il costo di una quantità enorme di cicli della CPU per eseguire Process.GetProcesses () o Process.GetProcessById / Name ().

Un metodo molto più rapido per verificare un processo in esecuzione per ID è utilizzare l’API nativa OpenProcess () . Se l’handle di ritorno è 0, il processo non esiste. Se l’handle è diverso da 0, il processo è in esecuzione. Non c’è alcuna garanzia che questo metodo funzioni al 100% in ogni momento a causa del permesso.