Développement d'une application WinForm C # .NET 2.0. Besoin de l'application pour se fermer et se redémarrer.
Application.Restart();
La méthode ci-dessus s'est avérée peu fiable .
Quelle est la meilleure façon de redémarrer l'application?
Développement d'une application WinForm C # .NET 2.0. Besoin de l'application pour se fermer et se redémarrer.
Application.Restart();
La méthode ci-dessus s'est avérée peu fiable .
Quelle est la meilleure façon de redémarrer l'application?
Réponses:
Malheureusement, vous ne pouvez pas utiliser Process.Start () pour démarrer une instance du processus en cours d'exécution. Selon la documentation Process.Start (): "Si le processus est déjà en cours d'exécution, aucune ressource de processus supplémentaire n'est démarrée ..."
Cette technique fonctionnera correctement sous le débogueur VS (car VS fait une sorte de magie qui fait que Process.Start pense que le processus n'est pas déjà en cours d'exécution), mais échouera s'il n'est pas exécuté sous le débogueur. (Notez que cela peut être spécifique au système d'exploitation - il me semble que je me souviens que dans certains de mes tests, cela a fonctionné sur XP ou Vista, mais je me souviens peut-être de l'avoir exécuté sous le débogueur.)
Cette technique est exactement celle utilisée par le dernier programmeur du projet sur lequel je travaille actuellement, et j'essaie de trouver une solution de contournement pour cela depuis un certain temps. Jusqu'à présent, je n'ai trouvé qu'une seule solution, et cela me semble juste sale: démarrer une 2ème application, qui attend en arrière-plan la fin de la première application, puis relance la 1ère application. Je suis sûr que ça marcherait, mais, beurk.
Edit: L'utilisation d'une 2ème application fonctionne. Tout ce que j'ai fait dans la deuxième application était:
static void RestartApp(int pid, string applicationName ) { // Wait for the process to terminate Process process = null; try { process = Process.GetProcessById(pid); process.WaitForExit(1000); } catch (ArgumentException ex) { // ArgumentException to indicate that the // process doesn't exist? LAME!! } Process.Start(applicationName, ""); }
(Ceci est un exemple très simplifié. Le vrai code a beaucoup de contrôle de cohérence, de gestion des erreurs, etc.)
la source
Process.Start
ne regarde pas la liste des processus OS en cours d'exécution. Cette déclaration de documentation ne parle que de cette instance d'objet de laProcess
classe. LaProcess
classe peut être attachée à un processus en cours d'exécution, mais elle peut également être dans un état non démarré. À mon avis, c'est une erreur de conception. La meilleure pratique, IMO, est de ne jamais réutiliser uneProcess
instance et de la démarrer immédiatement après sa création. Idéalement, utilisez laProcess.Start
méthode statique . Ensuite, ce défaut de documentation et de conception n'entre jamais en jeu.WaitForExit(1000)
. Mais toute l'attente n'est pas nécessaire pour démarrer un nouveau processus. Il peut s'agir d'un comportement supplémentaire que vous souhaitez, mais il n'est pas nécessaire de démarrer un nouveau processus.Une approche beaucoup plus simple qui a fonctionné pour moi est:
Application.Restart(); Environment.Exit(0);
Cela préserve les arguments de la ligne de commande et fonctionne malgré les gestionnaires d'événements qui empêcheraient normalement l'application de se fermer.
L'appel Restart () tente de quitter, démarre quand même une nouvelle instance et revient. L'appel Exit () met alors fin au processus sans donner à aucun gestionnaire d'événements une chance de s'exécuter. Il y a une très brève période pendant laquelle les deux processus sont en cours d'exécution, ce qui n'est pas un problème dans mon cas, mais peut-être dans d'autres cas.
Le code de sortie 0 dans
Environment.Exit(0);
spécifie un arrêt propre. Vous pouvez également quitter avec 1 pour indiquer qu'une erreur s'est produite.la source
OnClose()
événements de formulaire et autres.Si vous êtes dans le formulaire principal de l'application, essayez d'utiliser
System.Diagnostics.Process.Start( Application.ExecutablePath); // to start new instance of application this.Close(); //to turn off current app
la source
Enviorment.Exit(0)
fera également le travail.Enviorment.Exit
est une sortie sale et assez invasive car elle empêche l'exécution du code de nettoyage d'application. Pas le bon choix la plupart du temps.Je suis peut-être en retard à la fête mais voici ma solution simple et cela fonctionne comme un charme avec chaque application que j'ai:
try { //run the program again and close this one Process.Start(Application.StartupPath + "\\blabla.exe"); //or you can use Application.ExecutablePath //close this one Process.GetCurrentProcess().Kill(); } catch { }
la source
J'ai eu le même problème exact et j'avais aussi une exigence pour éviter les instances en double - je propose une solution alternative à celle que HiredMind propose (qui fonctionnera bien).
Ce que je fais, c'est démarrer le nouveau processus avec le processId de l'ancien processus (celui qui déclenche le redémarrage) comme argument de ligne cmd:
// Shut down the current app instance. Application.Exit(); // Restart the app passing "/restart [processId]" as cmd line args Process.Start(Application.ExecutablePath, "/restart" + Process.GetCurrentProcess().Id);
Ensuite, lorsque la nouvelle application démarre, j'analyse d'abord les arguments de la ligne cm et vérifie si l'indicateur de redémarrage est là avec un processId, puis j'attends que le processus se termine:
if (_isRestart) { try { // get old process and wait UP TO 5 secs then give up! Process oldProcess = Process.GetProcessById(_restartProcessId); oldProcess.WaitForExit(5000); } catch (Exception ex) { // the process did not exist - probably already closed! //TODO: --> LOG } }
Je ne montre évidemment pas tous les contrôles de sécurité que j'ai en place, etc.
Même si ce n'est pas idéal - je trouve que c'est une alternative valable pour que vous n'ayez pas à avoir en place une application séparée juste pour gérer le redémarrage.
la source
/allowMultipleInstances
drapeau plutôt qu'un drapeau plutôt étrange/restart
.Méthode Start / Exit
// Get the parameters/arguments passed to program if any string arguments = string.Empty; string[] args = Environment.GetCommandLineArgs(); for (int i = 1; i < args.Length; i++) // args[0] is always exe path/filename arguments += args[i] + " "; // Restart current application, with same arguments/parameters Application.Exit(); System.Diagnostics.Process.Start(Application.ExecutablePath, arguments);
Cela semble mieux fonctionner que Application.Restart ();
Je ne sais pas comment cela gère si votre programme protège contre plusieurs instances. Je suppose que vous feriez mieux de lancer un deuxième .exe qui met en pause puis démarre votre application principale pour vous.
la source
C'est simple, il vous suffit d'appeler les
Application.Restart()
méthodes qui ont tendance à appeler votre application pour le redémarrage. Mais vous devez avoir à quitter l'environnement local avec leurs codes d'erreur:Application.Restart(); Environment.exit(int errorcode);
vous pouvez créer une énumération de code d'erreur pour que vous puissiez l'utiliser efficacement.
Une autre méthode consiste simplement à quitter l'application et à démarrer le processus avec le chemin de l'exécutable:
la source
Essayez ce code:
bool appNotRestarted = true;
Ce code doit également être dans la fonction:
if (appNotRestarted == true) { appNotRestarted = false; Application.Restart(); Application.ExitThread(); }
la source
J'ai trouvé une autre solution, peut-être que n'importe qui peut l'utiliser aussi.
string batchContent = "/c \"@ECHO OFF & timeout /t 6 > nul & start \"\" \"$[APPPATH]$\" & exit\""; batchContent = batchContent.Replace("$[APPPATH]$", Application.ExecutablePath); Process.Start("cmd", batchContent); Application.Exit();
Le code est simplifié, alors faites attention aux exceptions et tout ça;)
la source
Vous oubliez les options / paramètres de ligne de commande qui ont été transmis à votre instance en cours d'exécution. Si vous ne les transmettez pas, vous n'effectuez pas un véritable redémarrage. Définissez le
Process.StartInfo
avec un clone des paramètres de votre processus, puis démarrez.Par exemple, si votre processus a été démarré en tant que
myexe -f -nosplash myfile.txt
, votre méthode ne s'exécuterait quemyexe
sans tous ces indicateurs et paramètres.la source
Je voulais que la nouvelle application démarre après la fermeture de l'ancienne.
Utiliser process.WaitForExit () pour attendre l'arrêt de votre propre processus n'a aucun sens. Il expirera toujours.
Donc, mon approche est d'utiliser Application.Exit () puis d'attendre, mais d'autoriser le traitement des événements, pendant un certain temps. Ensuite, démarrez une nouvelle application avec les mêmes arguments que l'ancienne.
static void restartApp() { string commandLineArgs = getCommandLineArgs(); string exePath = Application.ExecutablePath; try { Application.Exit(); wait_allowingEvents( 1000 ); } catch( ArgumentException ex ) { throw; } Process.Start( exePath, commandLineArgs ); } static string getCommandLineArgs() { Queue<string> args = new Queue<string>( Environment.GetCommandLineArgs() ); args.Dequeue(); // args[0] is always exe path/filename return string.Join( " ", args.ToArray() ); } static void wait_allowingEvents( int durationMS ) { DateTime start = DateTime.Now; do { Application.DoEvents(); } while( start.Subtract( DateTime.Now ).TotalMilliseconds > durationMS ); }
la source
Vous pouvez également utiliser Restarter .
la source
public static void appReloader() { //Start a new instance of the current program Process.Start(Application.ExecutablePath); //close the current application process Process.GetCurrentProcess().Kill(); }
Application.ExecutablePath renvoie le chemin du fichier .exe de votre application Veuillez suivre l'ordre des appels. Vous voudrez peut-être le placer dans une clause try-catch.
la source
Que diriez-vous de créer un fichier de batte, d'exécuter le fichier de commandes avant de fermer, puis de fermer l'instance actuelle.
Le fichier de commandes fait ceci:
la source
Voici mes 2 cents:
La séquence Start New Instance-> Close Current Instance devrait fonctionner même pour les applications qui ne permettent pas d'exécuter plusieurs copies simultanément, car dans ce cas, la nouvelle instance peut recevoir un argument de ligne de commande qui indiquera qu'un redémarrage est en cours il ne sera donc pas nécessaire de vérifier les autres instances en cours d'exécution. En attendant que la première instance se termine, je suis également implémenté s'il est absolument impératif qu'aucune instance ne soit exécutée en parallèle.
la source
Je crains que le redémarrage de l'ensemble de l'application à l'aide de Process n'aborde votre problème de la mauvaise manière.
Un moyen plus simple consiste à modifier le fichier Program.cs pour redémarrer:
static bool restart = true; // A variable that is accessible from program static int restartCount = 0; // Count the number of restarts static int maxRestarts = 3; // Maximum restarts before quitting the program /// <summary> /// The main entry point for the application. /// </summary> [STAThread] static void Main() { Application.EnableVisualStyles(); Application.SetCompatibleTextRenderingDefault(false); while (restart && restartCount < maxRestarts) { restart = false; // if you like.. the program can set it to true again restartCount++; // mark another restart, // if you want to limit the number of restarts // this is useful if your program is crashing on // startup and cannot close normally as it will avoid // a potential infinite loop try { Application.Run(new YourMainForm()); } catch { // Application has crashed restart = true; } } }
la source
J'ai eu un problème similaire, mais le mien était lié à une fuite de mémoire ingérable que je ne pouvais pas trouver sur une application qui doit fonctionner 24 heures sur 24, 7 jours sur 7. Avec le client, j'ai convenu que le moment sûr pour redémarrer l'application était 03h00 si la consommation de mémoire dépassait la valeur définie.
J'ai essayé
Application.Restart
, mais comme il semble utiliser un mécanisme qui démarre une nouvelle instance alors qu'elle est déjà en cours d'exécution, j'ai opté pour un autre schéma. J'ai utilisé l'astuce que le système de fichiers gère jusqu'à ce que le processus qui les a créés meurt. Donc, à partir de l'application, j'ai déposé le fichier sur le disque, et je n'ai pasDispose()
la poignée. J'ai utilisé le fichier pour envoyer l'exécutable «moi-même» et le répertoire de départ également (pour ajouter de la flexibilité).Code:
_restartInProgress = true; string dropFilename = Path.Combine(Application.StartupPath, "restart.dat"); StreamWriter sw = new StreamWriter(new FileStream(dropFilename, FileMode.Create, FileAccess.ReadWrite, FileShare.ReadWrite)); sw.WriteLine(Application.ExecutablePath); sw.WriteLine(Application.StartupPath); sw.Flush(); Process.Start(new ProcessStartInfo { FileName = Path.Combine(Application.StartupPath, "VideoPhill.Restarter.exe"), WorkingDirectory = Application.StartupPath, Arguments = string.Format("\"{0}\"", dropFilename) }); Close();
Close()
à la fin, cela déclencherait l'arrêt de l'application et le descripteur de fichier que j'utilisaisStreamWriter
ici serait maintenu ouvert jusqu'à ce que le processus meure vraiment. Ensuite...Restarter.exe entre en action. Il ESSAYE de lire le fichier en mode exclusif, l'empêchant d'accéder jusqu'à ce que l'application principale ne soit pas morte, puis démarre l'application principale, supprime le fichier et existe. Je suppose que cela ne peut pas être plus simple:
static void Main(string[] args) { string filename = args[0]; DateTime start = DateTime.Now; bool done = false; while ((DateTime.Now - start).TotalSeconds < 30 && !done) { try { StreamReader sr = new StreamReader(new FileStream(filename, FileMode.Open, FileAccess.ReadWrite, FileShare.ReadWrite)); string[] runData = new string[2]; runData[0] = sr.ReadLine(); runData[1] = sr.ReadLine(); Thread.Sleep(1000); Process.Start(new ProcessStartInfo { FileName = runData[0], WorkingDirectory = runData[1] }); sr.Dispose(); File.Delete(filename); done = true; } catch (Exception ex) { Console.WriteLine(ex.Message); } Thread.Sleep(1000); } }
la source
J'utilise ce qui suit et il fait exactement ce que vous recherchez:
ApplicationDeployment ad = ApplicationDeployment.CurrentDeployment; UpdateCheckInfo info = null; info = ad.CheckForDetailedUpdate(); if (info.IsUpdateRequired) { ad.UpdateAsync(); // I like the update dialog MessageBox.Show("Application was upgraded and will now restart."); Environment.Exit(0); }
la source
Pour utiliser En tant que déconnexion, vous devez mettre fin à toutes les applications de Ram Cache, fermez d'abord l'application, puis réexécutez-la
// en cliquant sur le bouton de déconnexion
foreach(Form frm in Application.OpenForms.Cast<Form>().ToList()) { frm.Close(); } System.Diagnostics.Process.Start(Application.ExecutablePath);
la source
Le problème de l'utilisation d' Application.Restart () est qu'il démarre un nouveau processus mais que «l'ancien» est toujours en place. C'est pourquoi j'ai décidé de tuer l'ancien processus en utilisant l'extrait de code suivant:
if(Condition){ Application.Restart(); Process.GetCurrentProcess().Kill(); }
Et cela fonctionne bien. Dans mon cas, MATLAB et une application C # partagent la même base de données SQLite. Si MATLAB utilise la base de données, le Form-App doit redémarrer (+ Compte à rebours) à nouveau, jusqu'à ce que MATLAB réinitialise son bit occupé dans la base de données. (Juste pour information secondaire)
la source
Vous pouvez inclure votre code dans une fonction et lorsque le redémarrage est nécessaire, vous pouvez simplement appeler la fonction.
la source