Antworten:
Dies ist eine Möglichkeit, dies mit dem Namen zu tun:
Process[] pname = Process.GetProcessesByName("notepad");
if (pname.Length == 0)
MessageBox.Show("nothing");
else
MessageBox.Show("run");
Sie können alle Prozesse in einer Schleife ausführen, um die ID für eine spätere Bearbeitung zu erhalten:
Process[] processlist = Process.GetProcesses();
foreach(Process theprocess in processlist){
Console.WriteLine("Process: {0} ID: {1}", theprocess.ProcessName, theprocess.Id);
}
if/else
, die nur eine Zeile lang sind, müssen keine geschweiften Klammern haben, um die Blockanweisung anzugeben. Dies gilt auch für foreach
und for
Aussagen. Es läuft auf den Codierungsstil hinaus.
for
Informationen nicht gesehen . Jahre von c # .net dev und ich haben diesen Stil noch nie gesehen. Wie sie sagen: "Du lernst jeden Tag etwas Neues". Vielen Dank für den Beitrag und die Antwort ..
Dies ist der einfachste Weg, den ich nach der Verwendung eines Reflektors gefunden habe. Ich habe dafür eine Erweiterungsmethode erstellt:
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;
}
}
Die Process.GetProcessById(processId)
Methode ruft die ProcessManager.IsProcessRunning(processId)
Methode auf und ArgumentException
löst aus, falls der Prozess nicht existiert. Aus irgendeinem Grund ist die ProcessManager
Klasse intern ...
Synchrone Lösung:
void DisplayProcessStatus(Process process)
{
process.Refresh(); // Important
if(process.HasExited)
{
Console.WriteLine("Exited.");
}
else
{
Console.WriteLine("Running.");
}
}
Asynchrone Lösung:
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 hatte eine ziemlich nette Antwort; Es berücksichtigt jedoch keine Situation, in der der Prozess nie begonnen hat.
Hier ist eine modifizierte Version von dem, was er gepostet hat.
public static bool IsRunning(this Process process)
{
try {Process.GetProcessById(process.Id);}
catch (InvalidOperationException) { return false; }
catch (ArgumentException){return false;}
return true;
}
Ich habe seine ArgumentNullException entfernt, da es sich tatsächlich um eine Nullreferenzausnahme handelt und sie trotzdem vom System ausgelöst wird. Außerdem habe ich die Situation berücksichtigt, in der der Prozess nie gestartet wurde oder die Methode close () zum Schließen der verwendet wurde Prozess.
Dies hängt davon ab, wie zuverlässig diese Funktion sein soll. Wenn Sie wissen möchten, ob die von Ihnen verwendete Prozessinstanz noch ausgeführt wird und mit 100% iger Genauigkeit verfügbar ist, haben Sie kein Glück. Der Grund dafür ist, dass es vom verwalteten Prozessobjekt aus nur zwei Möglichkeiten gibt, den Prozess zu identifizieren.
Die erste ist die Prozess-ID. Leider sind Prozess-IDs nicht eindeutig und können recycelt werden. Wenn Sie die Prozessliste nach einer passenden ID durchsuchen, werden Sie nur darüber informiert, dass ein Prozess mit derselben ID ausgeführt wird, dies ist jedoch nicht unbedingt Ihr Prozess.
Der zweite Punkt ist der Prozessgriff. Es hat jedoch das gleiche Problem wie die ID und es ist schwieriger, damit zu arbeiten.
Wenn Sie eine mittlere Zuverlässigkeit suchen, ist es ausreichend, die aktuelle Prozessliste auf einen Prozess mit derselben ID zu überprüfen.
Process.GetProcesses()
ist der Weg zu gehen. Je nachdem, wie er ausgeführt wird, müssen Sie möglicherweise ein oder mehrere unterschiedliche Kriterien verwenden, um Ihren Prozess zu finden (dh als Dienst oder normale App, unabhängig davon, ob er über eine Titelleiste verfügt oder nicht).
Vielleicht (wahrscheinlich) lese ich die Frage falsch, aber suchen Sie nach der HasExited-Eigenschaft, die Ihnen mitteilt, dass der von Ihrem Process-Objekt dargestellte Prozess beendet wurde (entweder normal oder nicht).
Wenn der Prozess, auf den Sie verweisen, eine Benutzeroberfläche hat, können Sie mithilfe der Eigenschaft "Antworten" bestimmen, ob die Benutzeroberfläche derzeit auf Benutzereingaben reagiert oder nicht.
Sie können auch EnableRaisingEvents festlegen und das Ereignis Exited (das asychron gesendet wird) behandeln oder WaitForExit () aufrufen, wenn Sie blockieren möchten.
Sie können eine Prozessinstanz einmal für den gewünschten Prozess instanziieren und den Prozess mit diesem .NET-Prozessobjekt weiter verfolgen (es wird so lange verfolgt, bis Sie Close für dieses .NET-Objekt explizit aufrufen, selbst wenn der Prozess, den es verfolgt hat, abgestorben ist [Dies soll Ihnen Zeit geben, den Prozess zu beenden, auch bekannt als ExitTime usw.])
Zitieren von http://msdn.microsoft.com/en-us/library/fb4aw7b8.aspx :
Wenn ein zugeordneter Prozess beendet wird (dh wenn er vom Betriebssystem durch eine normale oder abnormale Beendigung heruntergefahren wird), speichert das System Verwaltungsinformationen über den Prozess und kehrt zu der Komponente zurück, die WaitForExit aufgerufen hat. Die Prozesskomponente kann dann auf die Informationen zugreifen, einschließlich der ExitTime, indem sie das Handle für den beendeten Prozess verwendet.
Da der zugeordnete Prozess beendet wurde, verweist die Handle-Eigenschaft der Komponente nicht mehr auf eine vorhandene Prozessressource. Stattdessen kann das Handle nur verwendet werden, um auf die Informationen des Betriebssystems über die Prozessressource zuzugreifen. Das System kennt Handles für beendet Prozesse, die nicht von Prozesskomponenten freigegeben wurden, und speichert daher die ExitTime- und Handle-Informationen im Speicher, bis die Prozesskomponente die Ressourcen spezifisch freigibt. Aus diesem Grund rufen Sie jedes Mal, wenn Sie Start für eine Prozessinstanz aufrufen, Close auf, wenn der zugehörige Prozess beendet wurde und Sie keine administrativen Informationen mehr dazu benötigen. Durch Schließen wird der dem beendeten Prozess zugewiesene Speicher freigegeben.
Ich habe die Lösung von Coincoin ausprobiert:
Bevor ich eine Datei verarbeite, kopiere ich sie als temporäre Datei und öffne sie.
Wenn ich fertig bin, schließe ich die Anwendung, wenn sie noch geöffnet ist, und lösche die temporäre Datei:
Ich verwende einfach eine Prozessvariable und überprüfe sie anschließend:
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 );
}
Später schließe ich die Anwendung:
...
openApplication.Refresh();
// close application if it is still open
if ( !openApplication.HasExited() ) {
openApplication.Kill();
}
// delete temporary file
System.IO.File.Delete( fileCache );
Es funktioniert (soweit)
openApplication.HasExited()
ist HasExited keine Funktion. Der richtige Weg wäre openApplication.HasExited
.
Trotz der unterstützten API von .Net-Frameworks zur Überprüfung des vorhandenen Prozesses anhand der Prozess-ID sind diese Funktionen sehr langsam. Die Ausführung von Process.GetProcesses () oder Process.GetProcessById / Name () kostet sehr viele CPU-Zyklen.
Eine viel schnellere Methode zum Überprüfen eines laufenden Prozesses anhand der ID ist die Verwendung der nativen API OpenProcess () . Wenn das Rückgabehandle 0 ist, ist der Prozess nicht vorhanden. Wenn sich das Handle von 0 unterscheidet, wird der Prozess ausgeführt. Es gibt keine Garantie dafür, dass diese Methode aufgrund der Erlaubnis jederzeit zu 100% funktioniert.
Damit sind viele Probleme verbunden, wie andere anscheinend teilweise angesprochen haben:
Unabhängig davon, ob die von anderen genannten Eigenschaften intern sind oder nicht, können Sie Informationen durch Reflexion erhalten, wenn die Erlaubnis dies zulässt.
var x = obj.GetType().GetProperty("Name", BindingFlags.NonPublic | BindingFlags.Instance);
Sie können Win32-Code für Snapshot aufrufen oder WMI verwenden, das langsamer ist.
HANDLE CreateToolhelp32Snapshot(
DWORD dwFlags,
DWORD th32ProcessID
);
Eine andere Option wäre OpenProcess / CloseProcess, aber Sie werden immer noch auf dieselben Probleme stoßen, mit Ausnahmen, die wie zuvor ausgelöst werden.
Für WMI - OnNewEvent.Properties ["?"]:
string process = "notepad";
if (Process.GetProcessesByName(process).Length == 0)
{
MessageBox.Show("Working");
}
else
{
MessageBox.Show("Not Working");
}
Sie können auch einen Timer verwenden, um den Vorgang jedes Mal zu überprüfen
length == 0
sollte angezeigt werden Not Working
), erledigt aber trotzdem die Arbeit.