Risposte:
Questo è un modo per farlo con il nome:
Process[] pname = Process.GetProcessesByName("notepad");
if (pname.Length == 0)
MessageBox.Show("nothing");
else
MessageBox.Show("run");
È possibile eseguire il ciclo di tutto il processo per ottenere l'ID per successive manipolazioni:
Process[] processlist = Process.GetProcesses();
foreach(Process theprocess in processlist){
Console.WriteLine("Process: {0} ID: {1}", theprocess.ProcessName, theprocess.Id);
}
if/else
istruzioni C # che sono lunghe solo una riga non devono avere parentesi graffe per indicare l'istruzione di blocco. Questo vale anche per foreach
e for
dichiarazioni. Si riduce allo stile di programmazione.
for
. Anni di sviluppo di c # .net e non ho mai visto questo stile. Come si suol dire, "impari qualcosa di nuovo ogni giorno". Grazie per il post e la risposta ..
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 Process.GetProcessById(processId)
metodo chiama il ProcessManager.IsProcessRunning(processId)
metodo e genera ArgumentException
nel caso in cui il processo non esista. Per qualche motivo la ProcessManager
classe è 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 ebbe 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à si suppone che sia un'eccezione di riferimento null e viene comunque generata dal sistema e ho anche tenuto conto della situazione in cui il processo non è mai stato avviato o il metodo close () è stato utilizzato per chiudere il processi.
Dipende da quanto affidabile vuoi che questa funzione sia. Se vuoi sapere se la particolare istanza del processo che hai è ancora in esecuzione e disponibile con un'accuratezza del 100%, sei sfortunato. Il motivo è che dall'oggetto processo gestito ci sono solo 2 modi per identificare il processo.
Il primo è l'ID processo. Sfortunatamente, gli ID di processo non sono univoci e possono essere riciclati. La ricerca nell'elenco di 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 è la maniglia di processo. Ha lo stesso problema dell'ID ed è più complicato lavorare con lui.
Se stai cercando un'affidabilità di livello medio, è sufficiente controllare l'elenco dei processi corrente 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 (ad esempio come servizio o 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 dal tuo oggetto Process è uscito (normalmente o no).
Se il processo a cui si fa riferimento ha un'interfaccia utente, è possibile utilizzare la proprietà Responding per determinare se l'interfaccia utente sta attualmente rispondendo all'input dell'utente o meno.
È inoltre possibile impostare EnableRaisingEvents e gestire l'evento Exited (che viene inviato in modo asincrono) o chiamare WaitForExit () se si desidera bloccare.
È possibile creare un'istanza di un'istanza di processo una volta per il processo desiderato e continuare a tenere traccia del processo utilizzando l'oggetto .NET Process (continuerà a monitorare fino a quando non si chiama esplicitamente Chiudi su quell'oggetto .NET, anche se il processo che stava monitorando è morto [questo per darti il tempo di chiudere il processo, ovvero ExitTime ecc.])
citando http://msdn.microsoft.com/en-us/library/fb4aw7b8.aspx :
All'uscita di un processo associato (vale a dire quando viene arrestato dal sistema operativo attraverso 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 uscito.
Poiché il processo associato è terminato, la proprietà Handle del componente non punta più a una risorsa di processo esistente. Al contrario, l'handle può essere utilizzato solo per accedere alle informazioni del sistema operativo sulla risorsa di processo. Il sistema è a conoscenza degli handle ai processi usciti che non sono stati rilasciati dai componenti Process, quindi mantiene le informazioni ExitTime e Handle in memoria fino a quando il componente Process non libera specificamente le risorse. Per questo motivo, ogni volta che si chiama Avvia per un'istanza di processo, chiamare Chiudi quando il processo associato è terminato e non sono più necessarie informazioni amministrative su di esso. Chiudi libera la memoria allocata al processo uscito.
Ho provato la soluzione di Coincoin:
prima di elaborare un file, lo copio come file temporaneo e lo apro.
Quando ho finito, chiudo l'applicazione se è ancora aperta ed elimino il file temporaneo:
utilizzo semplicemente 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)
openApplication.HasExited()
, HasExited non è una funzione. Il modo corretto sarebbe openApplication.HasExited
.
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 per l'esecuzione di Process.GetProcesses () o Process.GetProcessById / Name () è enorme.
Un metodo molto più rapido per controllare un processo in esecuzione tramite ID è utilizzare l'API nativa OpenProcess () . Se l'handle di ritorno è 0, il processo non esiste. Se handle è diverso da 0, il processo è in esecuzione. Non è garantito che questo metodo funzioni sempre al 100% a causa dell'autorizzazione.
Ci sono molti problemi associati a questo, come altri sembrano aver affrontato parzialmente:
Se le proprietà menzionate da altri sono interne o meno, è comunque possibile ottenere informazioni da esse tramite la riflessione se l'autorizzazione lo consente.
var x = obj.GetType().GetProperty("Name", BindingFlags.NonPublic | BindingFlags.Instance);
È possibile inserire il codice Win32 per Snapshot oppure utilizzare WMI che è più lento.
HANDLE CreateToolhelp32Snapshot(
DWORD dwFlags,
DWORD th32ProcessID
);
Un'altra opzione sarebbe OpenProcess / CloseProcess, ma continuerai gli stessi problemi con le eccezioni generate come prima.
Per WMI - OnNewEvent.Properties ["?"]:
string process = "notepad";
if (Process.GetProcessesByName(process).Length == 0)
{
MessageBox.Show("Working");
}
else
{
MessageBox.Show("Not Working");
}
inoltre è possibile utilizzare un timer per controllare il processo ogni volta
length == 0
dovrebbe essere visualizzato Not Working
), ma ottiene comunque il lavoro svolto.