it-swarm.com.de

C # - Einen Prozess durchführen.Starten Sie, bis der Prozess gestartet ist

Ich muss sicherstellen, dass ein Prozess läuft, bevor ich mit einer Methode fortfahre.

Die Aussage lautet:

Process.Start("popup.exe");

Können Sie einen WAIT-Befehl ausführen oder eine Verzögerung für diesen Wert einstellen?

61
Tom

Meinen Sie damit, bis es fertig ist? Dann benutze Process.WaitForExit:

var process = new Process {
    StartInfo = new ProcessStartInfo {
        FileName = "popup.exe"
    }
};
process.Start();
process.WaitForExit();

Wenn es sich um eine Anwendung mit einer Benutzeroberfläche handelt, auf die Sie warten, um in eine Nachrichtenschleife einzutreten, können Sie Folgendes sagen:

process.Start();
process.WaitForInputIdle();

Wenn keine dieser Bedingungen zutrifft, nur Thread.Sleep für einen angemessenen Zeitraum:

process.Start();
Thread.Sleep(1000); // sleep for one second
115
jason

Ich brauchte dies auch einmal und überprüfte den Fenstertitel des Prozesses. Wenn dies der Fall ist, können Sie sicher sein, dass die Anwendung ausgeführt wird. Die Anwendung, die ich überprüfte, brauchte einige Zeit für die Inbetriebnahme.

var process = Process.Start("popup.exe");
while(process.MainWindowTitle != "Title")
{
    Thread.Sleep(10);
}
14
ChrisG

Die Antwort von 'ChrisG' ist korrekt, aber MainWindowTitle muss jedes Mal aktualisiert werden.

var proc = Process.Start("popup.exe");
while (string.IsNullOrEmpty(proc.MainWindowTitle))
{
    System.Threading.Thread.Sleep(100);
    proc.Refresh();
}
10

Wie andere bereits gesagt haben, ist es nicht sofort offensichtlich, was Sie fragen. Ich gehe davon aus, dass Sie einen Prozess starten und dann eine weitere Aktion ausführen möchten, wenn der Prozess "fertig ist". 

Natürlich ist das "ist bereit" das knifflige Bit. Je nachdem, was Sie brauchen, können Sie feststellen, dass das Warten ausreichend ist. Wenn Sie jedoch eine robustere Lösung benötigen, können Sie die Verwendung eines benannten Mutex zur Steuerung des Kontrollflusses zwischen Ihren beiden Prozessen in Betracht ziehen.

Beispielsweise können Sie in Ihrem Hauptprozess einen benannten Mutex erstellen und einen Thread oder eine Task starten, die warten wird. Dann können Sie den 2. Prozess starten. Wenn dieser Prozess entscheidet, dass "es fertig ist", kann er den benannten Mutex öffnen (natürlich muss derselbe Name verwendet werden) und dem ersten Prozess signalisieren.

7
Matt

Zunächst einmal: Ich weiß, dass dies ziemlich alt ist, aber es gibt immer noch keine akzeptierte Antwort. Vielleicht hilft mein Ansatz jemand anderen. :) 

Was ich getan habe, um das zu lösen, ist:

process.Start();

while (true)
{
    try
    {
        var time = process.StartTime;
        break;
    }
    catch (Exception) {}
}

Die Zuordnung var time = process.StartTime löst eine Ausnahme aus, solange der Prozess nicht gestartet wurde. Sobald es passiert ist, kann man davon ausgehen, dass der Prozess läuft und mit ihm weiter arbeitet. Ich verwende dies, um auf den Start des Java-Prozesses zu warten, da es einige Zeit dauert. Auf diese Weise sollte es unabhängig von der Maschine sein, auf der die Anwendung ausgeführt wird, anstatt Thread.Sleep() zu verwenden.

Ich verstehe, dass dies keine sehr saubere Lösung ist, aber die einzige, die leistungsunabhängig sein sollte, könnte ich mir vorstellen.

5
RhodryCZ

Ich stimme mit Tom überein. Um die Prozesse während der Ausführung von Thread.Sleep zu überprüfen, überprüfen Sie außerdem die laufenden Prozesse. So etwas wie:

bool found = 0;
while (!found)
{
    foreach (Process clsProcess in Process.GetProcesses())
        if (clsProcess.Name == Name)
            found = true;

    Thread.CurrentThread.Sleep(1000);
}
4
Frank Pearson

Sind Sie sicher, dass die Start-Methode zurückgegeben wird, bevor der untergeordnete Prozess startet? Ich hatte immer den Eindruck, dass Start den Kindprozess synchron startet.

Wenn Sie warten möchten, bis Ihr untergeordneter Prozess eine Art Initialisierung abgeschlossen hat, benötigen Sie eine Kommunikation zwischen Prozessen - siehe Interprozesskommunikation für Windows in C # (.NET 2.0).

2
Jakub Konecki

Um die Idee von @ ChrisG ein wenig zu erweitern, sollten Sie die Verwendung von process.MainWindowHandle in Betracht ziehen und prüfen, ob die Fensterschleife reagiert. Verwenden Sie p/invoke diese Win32-API: SendMessageTimeout . Über diesen Link:

Wenn die Funktion erfolgreich ist, wird der Rückgabewert Wert ist ungleich Null. SendMessageTimeout liefert keine Informationen über Zeitüberschreitung einzelner Fenster, wenn HWND_BROADCAST wird verwendet.

Wenn die Funktion ausfällt oder abgelaufen ist, ist der Rückgabewert 0. Um .__ zu erhalten. erweiterte Fehlerinformation, Aufruf GetLastError. Wenn GetLastError .__ zurückgibt. ERROR_TIMEOUT, dann wurde die Funktion zeitlich festgelegt aus.

1
agent-j

Hier eine Implementierung, die einen System.Threading.Timer verwendet. Vielleicht ein bisschen viel für seinen Zweck.

    private static bool StartProcess(string filePath, string processName)
    {
        if (!File.Exists(filePath))
            throw new InvalidOperationException($"Unknown filepath: {(string.IsNullOrEmpty(filePath) ? "EMPTY PATH" : filePath)}");

        var isRunning = false;

        using (var resetEvent = new ManualResetEvent(false))
        {

            void Callback(object state)
            {
                if (!IsProcessActive(processName)) return;
                isRunning = true;
                // ReSharper disable once AccessToDisposedClosure
                resetEvent.Set();
            }

            using (new Timer(Callback, null, 0, TimeSpan.FromSeconds(0.5).Milliseconds))
            {
                Process.Start(filePath);
                WaitHandle.WaitAny(new WaitHandle[] { resetEvent }, TimeSpan.FromSeconds(9));
            }
        }

        return isRunning;
    }

    private static bool StopProcess(string processName)
    {
        if (!IsProcessActive(processName)) return true;

        var isRunning = true;

        using (var resetEvent = new ManualResetEvent(false))
        {

            void Callback(object state)
            {
                if (IsProcessActive(processName)) return;
                isRunning = false;
                // ReSharper disable once AccessToDisposedClosure
                resetEvent.Set();
            }

            using (new Timer(Callback, null, 0, TimeSpan.FromSeconds(0.5).Milliseconds))
            {
                foreach (var process in Process.GetProcessesByName(processName))
                    process.Kill();
                WaitHandle.WaitAny(new WaitHandle[] { resetEvent }, TimeSpan.FromSeconds(9));
            }
        }

        return isRunning;
    }

    private static bool IsProcessActive(string processName)
    {
        return Process.GetProcessesByName(processName).Any();
    }
0
Peter