2010-08-17 9 views
5

Unsere Anwendung einen Hintergrund-Thread aufweist, der einen Prozess durch System.Diagnostics.Process laicht:Prozess erzeugt durch Process.Start in .NET hängt der Faden

Process.Start(
    new ProcessStartInfo 
    { 
     FileName = url, 
     UseShellExecute = true 
    } 
); 

dies überhaupt keine Probleme zu haben, verwendet. Aber jetzt stirbt der Hintergrundfaden still; es kommt nie von dem Anruf zu Process.Start zurück. Der catch-Block für diesen Code, der System.Exception behandelt, wird ebenfalls nicht erreicht. Selbst wenn ich die Behandlung von Exceptions bei der Ausführung im Visual Studio-Debugger aktiviere, sehe ich keine Ausnahmen. Seltsamerweise wird der Prozess gut gemacht; Der Standardbrowser für den Benutzer wird mit der erwarteten URL gestartet.

Unser Prozess der Einstiegspunkt mit [STAThread] markiert als empfohlen.

Was könnte unser Thread verursachen beenden zu leise? Gibt es Techniken, mit denen ich debuggen kann, was während der Thread-Beendigung passiert?

Update:

Es sieht aus wie der Faden, nachdem alle am Leben ist; es kommt einfach nicht von dem Anruf zurück. Hier ist seine Stack-Trace:!

  • [In einem Schlaf warten oder sich]
  • System.dll System.Diagnostics.ShellExecuteHelper.ShellExecuteOnSTAThread() + 0x63 Bytes
  • System.dll System.Diagnostics.Process .StartWithShellExecuteEx (System.Diagnostics.ProcessStartInfo Startinfo) + 0x19d Bytes
  • System.dll! System.Diagnostics.Process.Start() + 0x39 Bytes
  • System.dll! System.Diagnostics.Process.Start (System.Diagnostics .ProcessStartInfo Startinfo) + 0x32 Bytes
  • Meine Methode

Update 2:

Launching cmd.exe ohne die Schale mit Werken als Behelfslösung auszuführen. Vielen Dank! Allerdings würde ich noch gerne wissen, warum der Anruf nicht zurückkehrt.

Update 3:

Shell Haken wie eine logische Erklärung klingt für das, was den Anruf verursachen könnte Rückkehr nicht. Ich konnte den Schurken Modul nicht gefunden, aber nach dem letzten Versuch der Dinge durch Shell Ausführung zu laufen, wird der Anruf tat Rückkehr.

In jedem Fall ist es möglich, dass Benutzer Shell-Erweiterungen geladen haben, die den Start des Prozesses stören könnten und meinen Code nicht zurückgeben. Wir können nichts über , tun, also ist die richtige Antwort, die Problemumgehung des Startens eines cmd.exe-Prozesses zu verwenden.

Antwort

4

Wie von Hans Passant erwähnt, könnte ein hängender Process.Start Anruf der Grund sein. Bei Verwendung von Process.Start mit UseShellExecute auf true wird die Windows-API-Funktion ShellExecuteEx unter der Haube aufgerufen, die unter bestimmten Umständen möglicherweise nicht zurückkehrt.

können Sie prüfen, ob dies der Fall ist durch Hinzufügen von Trace-Nachrichten an Ihrem Code:

System.Diagnostics.Trace.WriteLine("About to start process."); 
Process.Start(
    new ProcessStartInfo 
    { 
     FileName = url, 
     UseShellExecute = true 
    } 
); 
System.Diagnostics.Trace.WriteLine("Process started."); 

auf die Trace-Nachrichten zu hören, können Sie entweder eine TraceListener verwenden, aktivieren Sie das Ausgabefenster von Visual Studio oder ein verwenden Werkzeug wie DebugView.

Als Workaround können Sie den start Befehl verwenden. Der folgende Code startet ein verstecktes Shell-Fenster, das „beginnt“ die url:

Process.Start(
    new ProcessStartInfo() 
    { 
     FileName = "cmd.exe", 
     Arguments = "/c start http://www.google.com", 
     WindowStyle = ProcessWindowStyle.Hidden, 
     UseShellExecute = false 
    }); 
+0

Keine Überraschungen mit den 'Trace.WriteLine' Ergänzungen; der "Prozess begann". Linie wird nicht erreicht. – Jacob

+0

Beim Starten von cmd.exe wird der Aufruf immer noch nicht zurückgegeben. – Jacob

+0

Bah, aber es tut, wenn ich UseShellExecute auf false drehen. – Jacob

4

Nö, Fäden nicht still beenden, machen sie einen lauten kaboom Sound. Zumindest sehen Sie die Benachrichtigung zum Thread-Exit im Ausgabefenster. Das Blockieren der Process.Start() -Methode wäre eine andere Erklärung, obwohl es dafür keine Erklärung gibt. Ihr Schnipsel ist viel zu kurz, um eine anständige Diagnose zu erstellen. Irgendwas Umwelt vielleicht.


Ihr Stack-Trace hilft, ShellExecuteOnSTAThread() gibt in der Tat eine Sperr Thread.Join() auf einem kleinen Helfer-Thread ausführen. Dieser Thread ist erforderlich, um die systemeigene ShellExecuteEx() - API-Funktion aufzurufen. Sie kann nur aus einem STA-Thread aufgerufen werden. Es hat jedoch einen Fehler, ein STA-Thread muss auch eine Nachrichtenschleife pumpen. Dieser kleine Helfer tut es nicht.

Dass dies zu einem Problem auf Ihrem Computer führt, weist nach wie vor auf ein Umweltproblem hin, eine Art System-Add-on, das den ShellExecuteEx() -Aufruf hijackt. Und zählt auf einen echten STA-Thread. Sie sollten in der Lage sein, diesen Helper-Thread im Fenster "Debug + Windows + Threads" wiederzufinden. Es sollte "ShellExecuteFunction" auf dem Stapel enthalten. Die Art von "System-Add-On", die Stunts wie diese zieht, sind zum Beispiel Virenscanner. Sie sollten diese Alienware wieder im Fenster "Debug + Windows + Module" finden, nachdem Sie auf der Registerkarte "Debugging" des Projekts das Kontrollkästchen "Enable unmanaged debugging" aktiviert haben.

Die Problemumgehung, UseShellExecute = false zu verwenden, ist hier durchaus annehmbar. Allein die Tatsache, dass Ihre Maschine irgendwie durcheinander ist, ist nicht selbstverständlich.

+0

ich das Ausgabefenster in Visual Studio überprüft, und nichts war ausgegeben, nachdem 'Process.Start' starten. Ich hatte die Möglichkeit in Betracht gezogen, dass der Anruf blockiert wurde, aber selbst nach dem Beenden aller Instanzen von Chrome wurde der Anruf nie zurückgegeben (obwohl 'UseShellExecute' keine Ahnung hatte, warum der Anruf blockiert werden würde) – Jacob

+0

Nun, verwenden Sie den Debugger. Sehen Sie sich den Call-Stack an. Ein unmanaged Debugger mit dem konfigurierten Microsoft Symbol Server wäre wahrscheinlich der beste. –

+0

Großer Rat, @ Hans. Mehr Informationen gefunden. Siehe das Update zu meiner Frage. – Jacob

Verwandte Themen