2012-11-26 14 views
11

Io uso Process.Kill() per terminare un processo. Come questo:Come uccidere un processo senza ottenere un'eccezione di "processo terminato"?

if(!process.WaitForExit(5000)) { 
    process.Kill(); 
} 

e, talvolta, il processo uscirà proprio tra le righe, quindi il controllo otterrà all'interno if e poi Kill produrrà un'eccezione:

System.InvalidOperationException 
Cannot process request because the process (ProcessIdHere) has exited. 
at System.Diagnostics.Process.GetProcessHandle(Int32 access, Boolean throwIfExited) 
at System.Diagnostics.Process.Kill() 
//my code here 

Ora avvolgendo il codice in try- catch non sembra essere una buona idea perché InvalidOperationException può essere chiamato per altri motivi.

C'è un modo per terminare un processo senza ottenere un'eccezione nello scenario descritto?

+0

Hai provato a verificare l'eccezione interna? Potrebbe darti un'eccezione esatta da gestire. – Yahya

+0

@Yahya: Yeap, l'eccezione interna è nullo in ogni momento. – sharptooth

risposta

9

Si potrebbe P/Invoke TerminateProcess passarlo Process.Handle. Quindi valutare manualmente la causa (GetLastError()). Che è approssimativamente, che cosa fa internamente Process.Kill().

Tuttavia, notare che TerminateProcess è asincrono. Quindi dovresti aspettare l'handle del processo per essere sicuro che sia fatto. L'utilizzo di Process.Kill() lo fa per il tuo.

Aggiornamento: Correzione, Process.Kill() anche in modo asincrono. Dovrai quindi utilizzare WaitForExit() per attendere il termine del completamento, se ti interessa.

Francamente, non mi preoccuperei. Ovviamente c'è sempre la (remota?) Possibilità che alcuni "arbitrari" InvalidOperationExcepion si aprano da quella riga di codice, che non sia correlato al processo che non è più lì o che l'oggetto Process non sia in uno stato non valido, ma in la realtà penso che tu possa semplicemente andare con il try/aggirare lo Kill.

Inoltre, a seconda dell'applicazione, è possibile prendere in considerazione la registrazione di questo kill in ogni caso, poiché sembra una sorta di misura di ultima istanza. In tal caso, registrare l'effettivo InvalidOperationException con esso. Se le cose si fanno strane, almeno hai i tuoi registri per verificare perché il Kill non è riuscito.

Avendo tutto ciò che detto, si potrebbe anche prendere in considerazione prendere/gestire Win32Exception per gli stessi motivi.

+0

+1 per un approccio sensato al mondo reale. – tomfanning

3

è necessario utilizzare HasExited:

if(!process.WaitForExit(5000)) 
{ 
    if (!process.HasExited) 
    { 
     process.Kill(); 
    } 
} 

vedere qui:

http://msdn.microsoft.com/en-us/library/system.diagnostics.process.hasexited.aspx

+4

Che ha ancora una condizione di gara. 'HasExited' può restituire' false', ma al momento dell'esecuzione di 'Kill', il processo potrebbe essere interrotto - risultando in un' InvalidOperationException' ancora. –

+1

Stiamo parlando di frazioni di un nanosecondo così sembra improbabile, ma se questo è il caso non puoi fermarlo, il meglio che puoi fare è cogliere l'eccezione. – Lloyd

+0

"Frazioni di nanosecondi" sembra un'esagerazione, ad essere onesti. Il tuo processo potrebbe essere pre-impostato, ad esempio, tra le due chiamate, diamine, la scatola potrebbe anche ibernare tra tornare su "uno sfortunato ordine" ;-) Ma sono d'accordo, che l'eccezione è l'unica "robusta" soluzione - se ti interessa. YMMV naturalmente. –

Problemi correlati