wake-up-neo.com

Woher weiß ich, ob ein Prozess läuft?

Wie kann ich feststellen, ob ein Prozess gerade läuft, wenn ich einen Verweis auf einen System.Diagnostics.Process erhalte?

130
reshefm

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 den gesamten Prozess in einer Schleife ausführen, um die ID zur späteren Bearbeitung zu erhalten:

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

Dies ist der einfachste Weg, den ich nach der Verwendung von Reflektor ... gefunden habe. Dazu habe ich 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 gibt ArgumentException aus, falls der Prozess nicht vorhanden ist. Aus irgendeinem Grund ist die ProcessManager-Klasse intern ...

24
reshefm

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.");
}
14
Coincoin

reshefm hatte eine ziemlich schöne Antwort; Es berücksichtigt jedoch nicht eine Situation, in der der Prozess nie begonnen hat.

Hier ist eine modifizierte Version dessen, 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, weil es sich tatsächlich um eine Nullreferenzausnahme handelt, die vom System trotzdem geworfen wird, und ich habe auch die Situation berücksichtigt, in der der Prozess nie begonnen hat oder die close () -Methode zum Schließen der Methode verwendet wurde verarbeiten.

9
Aelphaeis

Dies sollte ein Einzeiler sein:

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

Es hängt davon ab, wie zuverlässig diese Funktion sein soll. Wenn Sie wissen möchten, ob die betreffende Prozessinstanz noch läuft und mit 100% Genauigkeit verfügbar ist, haben Sie kein Glück. Der Grund dafür ist, dass es vom verwalteten Prozessobjekt nur zwei Möglichkeiten gibt, den Prozess zu identifizieren.

Die erste ist die Prozess-ID. Leider sind Prozess-IDs nicht eindeutig und können wiederverwendet werden. Wenn Sie in der Prozessliste nach einer übereinstimmenden ID suchen, erfahren Sie nur, dass ein Prozess mit derselben ID ausgeführt wird. Dies ist jedoch nicht unbedingt Ihr Prozess.

Der zweite Punkt ist das Prozess-Handle. Es hat jedoch das gleiche Problem wie die Id und es ist schwieriger, damit zu arbeiten.

Wenn Sie eine mittlere Zuverlässigkeit suchen, reicht es aus, die aktuelle Prozessliste auf einen Prozess mit derselben ID zu überprüfen. 

3
JaredPar

Process.GetProcesses() ist der Weg zu gehen. Möglicherweise müssen Sie jedoch ein oder mehrere unterschiedliche Kriterien verwenden, um Ihren Prozess zu finden, je nachdem, wie er ausgeführt wird (d. H. Als Dienst oder normale App, ob er über eine Titelleiste verfügt oder nicht).

1
Jeff Kotula

Trotz der unterstützten API von .Net-Frameworks hinsichtlich der Überprüfung vorhandener Prozesse anhand der Prozess-ID sind diese Funktionen sehr langsam. Die Ausführung von Process.GetProcesses () oder Process.GetProcessById/Name () kostet sehr viel CPU-Zyklen.

Eine viel schnellere Methode zum Überprüfen eines laufenden Prozesses nach ID ist die Verwendung der nativen API OpenProcess () . Wenn der Rückgabe-Handle 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 zu 100% aufgrund von Erlaubnis funktioniert.

0
Hao Nguyen

Vielleicht (wahrscheinlich) lese ich die Frage falsch, aber suchen Sie nach der HasExited-Eigenschaft, die Ihnen mitteilt, dass der durch Ihr Process-Objekt dargestellte Prozess beendet wurde (normalerweise oder nicht).

Wenn der Prozess, auf den Sie verweisen, über eine Benutzeroberfläche verfügt, können Sie mit der Responding-Eigenschaft feststellen, ob die Benutzeroberfläche derzeit auf Benutzereingaben reagiert oder nicht.

Sie können auch EnableRaisingEvents einstellen und das Exited-Ereignis behandeln (das asynchron gesendet wird), oder WaitForExit () aufrufen, wenn Sie blockieren möchten.

0
Ross

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 benutze 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 (bisher)

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

sie können auch jederzeit einen Timer zur Überprüfung des Prozesses verwenden

0
berkay

Sie können eine Prozessinstanz einmal für den gewünschten Prozess instanziieren und den Prozess mithilfe dieses .NET-Prozessobjekts weiter verfolgen (bis zum expliziten Aufruf von Close für dieses .NET-Objekt wird sie auch weiterhin verfolgt, auch wenn der Prozess, den es verfolgt hat, beendet wurde [Dies ist in der Lage, Ihnen Zeit für den Prozessabschluss (aka ExitTime usw.) zu geben.])

Zitieren http://msdn.Microsoft.com/de-de/library/fb4aw7b8.aspx :

Wenn ein zugehöriger Prozess beendet wird (das heißt, wenn er vom Betriebssystem durch eine normale oder abnormale Beendigung beendet wird), wird das System speichert administrative Informationen über den Prozess und kehrt zur .__ zurück. Komponente, die WaitForExit aufgerufen hatte. Die Prozesskomponente kann dann Zugriff auf die Informationen, einschließlich der ExitTime, mithilfe von Handle zu dem verlassenen Prozess. 

Da der zugeordnete Prozess beendet wurde, ist die Handle-Eigenschaft von Die Komponente verweist nicht mehr auf eine vorhandene Prozessressource. Stattdessen, Das Handle kann nur für den Zugriff auf das Betriebssystem verwendet werden Informationen über die Prozessressource. Das System kennt Handgriffe um Prozesse zu beenden, die nicht von Prozesskomponenten freigegeben wurden, So bleiben die ExitTime- und Handle-Informationen im Speicher bis zur Die Prozesskomponente setzt die Ressourcen gezielt frei. Aus diesem Grund, Immer wenn Sie Start für eine Prozessinstanz aufrufen, rufen Sie Close auf, wenn die Der zugehörige Prozess wurde beendet und Sie benötigen keine administrative Informationen darüber. Schließen gibt den zugewiesenen Speicher frei zu dem verlassenen Prozess.

0
George Birbilis

Hiermit sind viele Probleme verbunden, wie andere anscheinend teilweise angegangen haben:

  • Es wird nicht garantiert, dass Instanzmitglieder threadsicher sind. Das heißt, es gibt Rennbedingungen, die mit der Lebensdauer des Snapshots auftreten können, wenn versucht wird, die Eigenschaften des Objekts zu bewerten.
  • Das Prozesshandle löst Win32Exception für ACCESS DENIED aus, wobei Berechtigungen zum Auswerten dieser und anderer solcher Eigenschaften nicht zulässig sind.
  • Für den Status ISN'T RUNNING wird auch eine ArgumentException ausgelöst, wenn versucht wird, einige ihrer Eigenschaften auszuwerten.

Unabhängig davon, ob es sich bei den von anderen erwähnten Eigenschaften um interne Eigenschaften handelt oder nicht, können Sie bei entsprechender Erlaubnis dennoch Informationen über Reflektion erhalten.

var x = obj.GetType().GetProperty("Name", BindingFlags.NonPublic | BindingFlags.Instance);

Sie könnten Win32-Code für Snapshot abrufen oder WMI verwenden, was 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 denselben Ausnahmen wie zuvor.

Für WMI - OnNewEvent.Properties ["?"]:

  • "ParentProcessID"
  • "Prozess ID"
  • "Prozessname"
  • "SECURITY_DESCRIPTOR"
  • "Session-ID"
  • "Sid"
  • "TIME_CREATED"
0
Latency