Entwickeln einer C # .NET 2.0 WinForm-Anwendung. Die Anwendung muss geschlossen und neu gestartet werden.
Application.Restart();
Das obige Verfahren hat sich als unzuverlässig erwiesen .
Was ist ein besserer Weg, um die Anwendung neu zu starten?
Antworten:
Leider können Sie Process.Start () nicht verwenden, um eine Instanz des aktuell ausgeführten Prozesses zu starten. In den Process.Start () -Dokumenten heißt es: "Wenn der Prozess bereits ausgeführt wird, wird keine zusätzliche Prozessressource gestartet ..."
Diese Technik funktioniert unter dem VS-Debugger einwandfrei (da VS eine Art Magie ausführt, die Process.Start zu der Annahme veranlasst, dass der Prozess noch nicht ausgeführt wird), schlägt jedoch fehl, wenn er nicht unter dem Debugger ausgeführt wird. (Beachten Sie, dass dies möglicherweise betriebssystemspezifisch ist. Ich erinnere mich anscheinend, dass es bei einigen meiner Tests entweder unter XP oder Vista funktioniert hat, aber ich erinnere mich möglicherweise nur daran, es unter dem Debugger ausgeführt zu haben.)
Diese Technik ist genau die, die der letzte Programmierer in dem Projekt verwendet, an dem ich gerade arbeite, und ich habe seit einiger Zeit versucht, eine Problemumgehung dafür zu finden. Bisher habe ich nur eine Lösung gefunden, und es fühlt sich für mich nur schmutzig und klobig an: Starten Sie eine zweite Anwendung, die im Hintergrund darauf wartet, dass die erste Anwendung beendet wird, und startet dann die erste Anwendung neu. Ich bin sicher, es würde funktionieren, aber igitt.
Bearbeiten: Die Verwendung einer zweiten Anwendung funktioniert. Alles was ich in der zweiten App gemacht habe war:
(Dies ist ein sehr vereinfachtes Beispiel. Der echte Code enthält viele Informationen zur Überprüfung der geistigen Gesundheit, zur Fehlerbehandlung usw.)
quelle
Process.Start
Die Liste der ausgeführten Betriebssystemprozesse wird nicht angezeigt. Diese Dokumentationsanweisung bezieht sich nur auf diese Objektinstanz derProcess
Klasse. DieProcess
Klasse kann an einen laufenden Prozess angehängt werden, sie kann sich jedoch auch in einem nicht gestarteten Zustand befinden. Meiner Meinung nach ist dies ein Designfehler. Die beste Vorgehensweise, IMO, besteht darin, eineProcess
Instanz niemals wiederzuverwenden und sofort nach der Erstellung zu starten. Verwenden Sie im Idealfall die statischeProcess.Start
Methode. Dann kommt dieser Dokumentations- und Konstruktionsfehler nie ins Spiel.WaitForExit(1000)
. Das gesamte Warten ist jedoch nicht erforderlich, um einen neuen Prozess zu starten. Möglicherweise möchten Sie zusätzliches Verhalten, aber es ist nicht erforderlich, einen neuen Prozess zu starten.Ein viel einfacherer Ansatz, der für mich funktioniert hat, ist:
Dies behält die Befehlszeilenargumente bei und funktioniert trotz Ereignishandlern, die normalerweise das Schließen der Anwendung verhindern würden.
Der Restart () -Aufruf versucht zu beenden, startet trotzdem eine neue Instanz und kehrt zurück. Der Aufruf von Exit () beendet dann den Prozess, ohne dass Ereignishandler die Möglichkeit haben, ausgeführt zu werden. Es gibt einen sehr kurzen Zeitraum, in dem beide Prozesse ausgeführt werden, was in meinem Fall kein Problem darstellt, aber möglicherweise in anderen Fällen.
Der Exit-Code 0 in
Environment.Exit(0);
gibt ein sauberes Herunterfahren an. Sie können auch mit 1 beenden, um anzugeben, dass ein Fehler aufgetreten ist.quelle
Wenn Sie sich in der Haupt-App-Form befinden, versuchen Sie es
quelle
Enviorment.Exit(0)
wird auch den Job machen.Enviorment.Exit
ist ein schmutziger und ziemlich invasiver Exit, da er verhindert, dass Anwendungsbereinigungscode ausgeführt wird. Meistens nicht die richtige Wahl.Ich komme vielleicht zu spät zur Party, aber hier ist meine einfache Lösung, die bei jeder Anwendung, die ich habe, wie ein Zauber wirkt:
quelle
Ich hatte genau das gleiche Problem und musste auch doppelte Instanzen verhindern - ich schlage eine alternative Lösung zu der von HiredMind vorgeschlagenen vor (die gut funktionieren wird).
Ich starte den neuen Prozess mit der processId des alten Prozesses (der den Neustart auslöst) als cmd-Zeilenargument:
Wenn die neue App gestartet wird, analysiere ich zuerst die cm-Zeilenargumente und überprüfe, ob das Neustart-Flag mit einer processId vorhanden ist. Warten Sie dann, bis dieser Prozess beendet ist:
Ich zeige offensichtlich nicht alle Sicherheitsüberprüfungen, die ich durchgeführt habe usw.
Auch wenn dies nicht ideal ist - ich finde, dass dies eine gültige Alternative ist, sodass Sie keine separate App benötigen, um den Neustart durchzuführen.
quelle
/allowMultipleInstances
Flagge "finden" als die ziemlich seltsame/restart
.Start / Exit-Methode
Dies scheint besser zu funktionieren als Application.Restart ();
Sie sind sich nicht sicher, wie dies funktioniert, wenn Ihr Programm vor mehreren Instanzen schützt. Ich vermute, Sie sollten besser eine zweite EXE-Datei starten, die pausiert und dann Ihre Hauptanwendung für Sie startet.
quelle
Es ist einfach, Sie müssen nur die
Application.Restart()
Methoden aufrufen , die dazu neigen, Ihre Anwendung zum Neustart aufzurufen. Sie müssen jedoch die lokale Umgebung mit ihren Fehlercodes verlassen:Sie können eine Aufzählung von Fehlercodes erstellen, damit Sie diese effektiv verwenden können.
Eine andere Methode besteht darin, die Anwendung zu beenden und den Prozess mit dem ausführbaren Pfad zu starten:
quelle
Versuchen Sie diesen Code:
Dieser Code muss auch in der Funktion enthalten sein:
quelle
Ich habe eine andere Lösung gefunden, vielleicht kann sie auch jeder verwenden.
Code ist vereinfacht, also kümmere dich um Ausnahmen und so;)
quelle
Sie vergessen die Befehlszeilenoptionen / -parameter, die an Ihre aktuell ausgeführte Instanz übergeben wurden. Wenn Sie diese nicht übergeben, führen Sie keinen echten Neustart durch. Stellen Sie die
Process.StartInfo
mit einem Klon der Prozessparameter ein und starten Sie dann.Wenn Ihr Prozess beispielsweise als gestartet wurde
myexe -f -nosplash myfile.txt
, wird Ihre Methode nurmyexe
ohne all diese Flags und Parameter ausgeführt.quelle
Ich wollte, dass die neue Anwendung gestartet wird, nachdem die alte heruntergefahren wurde.
Die Verwendung von process.WaitForExit () zum Warten auf das Herunterfahren Ihres eigenen Prozesses macht keinen Sinn. Es wird immer eine Auszeit geben.
Mein Ansatz ist es also, Application.Exit () zu verwenden und dann zu warten, aber die Verarbeitung von Ereignissen für einen bestimmten Zeitraum zuzulassen. Starten Sie dann eine neue Anwendung mit denselben Argumenten wie die alte.
quelle
Sie können auch Restarter verwenden .
quelle
Application.ExecutablePath gibt Ihren .exe-Dateipfad für Anwendungen zurück. Befolgen Sie die Reihenfolge der Aufrufe. Möglicherweise möchten Sie es in eine try-catch-Klausel einfügen.
quelle
Wie wäre es, wenn Sie eine Bat-Datei erstellen, die Batch-Datei vor dem Schließen ausführen und dann die aktuelle Instanz schließen.
Die Batch-Datei führt Folgendes aus:
quelle
Hier sind meine 2 Cent:
Die Sequenz Neue Instanz starten-> Aktuelle Instanz schließen sollte auch für Anwendungen funktionieren, bei denen nicht mehrere Kopien gleichzeitig ausgeführt werden können. In diesem Fall wird der neuen Instanz möglicherweise ein Befehlszeilenargument übergeben, das angibt, dass ein Neustart ausgeführt wird Daher ist es nicht erforderlich, nach anderen laufenden Instanzen zu suchen. Warten Sie, bis die erste Instanz tatsächlich abgeschlossen ist, und implementieren Sie sie, wenn es unbedingt erforderlich ist, dass keine zwei Instanzen parallel ausgeführt werden.
quelle
Ich befürchte, dass ein Neustart der gesamten Anwendung mit Process Ihr Problem falsch angeht.
Eine einfachere Möglichkeit besteht darin, die Datei Program.cs so zu ändern, dass sie neu gestartet wird:
quelle
Ich hatte ein ähnliches Problem, aber mein Problem hing mit einem nicht verwaltbaren Speicherverlust zusammen, den ich in einer App, die rund um die Uhr ausgeführt werden muss, nicht finden konnte. Mit dem Kunden stimmte ich zu, dass die sichere Zeit für den Neustart der App 03:00 Uhr war, wenn der Speicherverbrauch über dem definierten Wert lag.
Ich habe es versucht
Application.Restart
, aber da es einen Mechanismus zu verwenden scheint, der eine neue Instanz startet, während sie bereits ausgeführt wird, habe ich mich für ein anderes Schema entschieden. Ich habe den Trick verwendet, den Dateisystem-Handles beibehalten, bis der Prozess, der sie erstellt hat, stirbt. Also habe ich aus der Anwendung die Datei auf die Festplatte gelegt und nichtDispose()
das Handle nicht ausgeführt. Ich habe die Datei verwendet, um die ausführbare Datei und das Startverzeichnis von "mir" zu senden (um die Flexibilität zu erhöhen).Code:
Close()
Am Ende würde das Herunterfahren der App eingeleitet, und dasStreamWriter
hier verwendete Dateihandle würde offen gehalten, bis der Prozess wirklich stirbt. Dann...Restarter.exe wird aktiv. Es wird versucht, die Datei im exklusiven Modus zu lesen, um zu verhindern, dass sie Zugriff erhält, bis die Haupt-App nicht tot ist. Anschließend wird die Haupt-App gestartet, die Datei gelöscht und existiert. Einfacher geht es wohl nicht:
quelle
Ich benutze das Folgende und es macht genau das, wonach Sie suchen:
quelle
Für die Verwendung als Abmeldung müssen Sie alle Apps aus dem Ram-Cache beenden. Schließen Sie daher zuerst die Anwendung und führen Sie sie erneut aus
// beim Klicken auf die Schaltfläche Abmelden
quelle
Das Problem bei der Verwendung von Application.Restart () besteht darin, dass ein neuer Prozess gestartet wird, der "alte" jedoch noch vorhanden ist. Aus diesem Grund habe ich beschlossen, den alten Prozess mit dem folgenden Codeausschnitt zu beenden:
Und es funktioniert richtig gut. In meinem Fall verwenden MATLAB und eine C # -Anwendung dieselbe SQLite-Datenbank. Wenn MATLAB die Datenbank verwendet, sollte die Form-App erneut gestartet werden (+ Countdown), bis MATLAB sein Besetztbit in der Datenbank zurückgesetzt hat. (Nur zur Information)
quelle
Sie können Ihren Code in eine Funktion einschließen, und wenn ein Neustart erforderlich ist, können Sie die Funktion einfach aufrufen.
quelle