2012-03-07 10 views
12

Voglio costruire la mia applicazione con la funzione per riavviarsi. Ho trovato su CodeProjectRiavviare un'applicazione da sola

ProcessStartInfo Info=new ProcessStartInfo(); 
Info.Arguments="/C choice /C Y /N /D Y /T 3 & Del "+ 
       Application.ExecutablePath; 
Info.WindowStyle=ProcessWindowStyle.Hidden; 
Info.CreateNoWindow=true; 
Info.FileName="cmd.exe"; 
Process.Start(Info); 
Application.Exit(); 

Questo non funziona affatto ... E l'altro problema è, come iniziare di nuovo come questo? Forse ci sono anche argomenti per avviare le applicazioni.

Edit:

http://www.codeproject.com/script/Articles/ArticleVersion.aspx?aid=31454&av=58703 
+0

Cosa succede, eventuali eccezioni o semplicemente niente? –

+3

"Questo non funziona affatto" è una descrizione inadeguata di un problema. Cosa non funziona? Errori? Eccezioni? Qualcos'altro? – Oded

+0

Sei sicuro che siano gli argomenti corretti? Sembra che proverà a cancellare la tua applicazione! In generale dovrai riavviare per te un altro processo - che stanno cercando di fare qui con cmd - anche se forse il processo genitore può semplicemente creare ProcessProcess stesso, o anche in qualche modo creare un nuovo AppDomain in corso e distruggere il vecchio uno? – Rup

risposta

36

Uso un codice simile al codice che hai provato al riavvio delle app. Mando un comando cmd temporizzato per riavviare l'applicazione per me in questo modo:

ProcessStartInfo Info = new ProcessStartInfo(); 
Info.Arguments = "/C ping 127.0.0.1 -n 2 && \"" + Application.ExecutablePath + "\""; 
Info.WindowStyle = ProcessWindowStyle.Hidden; 
Info.CreateNoWindow = true; 
Info.FileName = "cmd.exe"; 
Process.Start(Info); 
Application.Exit(); 

Il comando viene inviato al sistema operativo, il ping pause lo script per 2-3 secondi, quando ormai l'applicazione è uscito da Application.Exit() , quindi il comando successivo dopo il ping lo riavvia.

Nota: lo \" inserisce le virgolette sul percorso, nel caso in cui abbia spazi, che cmd non può elaborare senza virgolette.

Spero che questo aiuti!

+0

Questa soluzione è fantastica, ma usare il comando ping come un ritardo lo rende un po '"sporco" - sfortunatamente non sembra che ci sia un altro modo per farlo - Ho provato il comando "batch" (batch) e non funziona –

+0

Grazie. Sì, è un po 'hacky, ma significa che puoi riavviare in modo affidabile l'app senza dover installare altro separatamente. Penso che il comando batch 'sleep' sia un extra che devi installare manualmente. –

+1

La seconda pausa non funziona per me. Avvia immediatamente l'applicazione specificata. Nel mio caso, sto usando un'applicazione di aggiornamento che fallisce perché l'applicazione in esecuzione non si è ancora chiusa, rilasciando i suoi file. Sto usando .NET 4.5.1 su Windows 10. – kraeg

9

Perché non solo il seguente?

Process.Start(Application.ExecutablePath); 
Application.Exit(); 

Se si vuole essere sicuri l'applicazione non viene eseguito due volte sia per uso Environment.Exit(-1) che uccide il processo istantaneamente (non proprio il modo bello) o qualcosa di simile iniziare una seconda app, che controlla per il processo dei principali app e la avvia nuovamente non appena il processo è finito.

+0

Ho dimenticato, non voglio, che questa app sia aperta due volte allo stesso tempo. – Noli

+1

@Noli La seconda linea si occupa di ciò. – Stijn

+0

Quindi prova '"/C scelta/CY/N/DY/T 3 & "+ Application.ExecutablePath;' poiché "Del" cancellerà l'applicazione, ma può ancora succedere che l'app venga eseguita due volte se la chiusura richiede più lungo poi 3s ... – ChrFin

24

Perché non utilizzare

Application.Restart(); 

??

Altro su Restart

+0

Non conoscevo questo metodo e penso che questo sia il modo migliore per andare ... – ChrFin

+0

Per favore, mi serve un altro modo ... – Noli

+0

@Noli: Perché? Questo fa esattamente quello che hai chiesto: 'Arresta l'applicazione e avvia immediatamente una nuova istanza. – ChrFin

3

WinForms ha il metodo Application.Restart(), che fa proprio questo. Se utilizzi WPF, puoi semplicemente aggiungere un riferimento a System.Windows.Forms e chiamarlo.

+0

Application.Restart non funziona. Raramente chiude l'applicazione chiamando la funzione. È molto inaffidabile – JeremyK

+0

Ha funzionato bene per me finora, in un'applicazione WPF. –

+0

non funziona per un'app WPF – Sandepku

6

Si ha l'applicazione iniziale A, si desidera riavviare. Così, quando si vuole uccidere A, una piccola applicazione B è stato avviato, B uccidere A, poi B Avvio A, e uccidere B.

Per avviare un processo:

Process.Start("A.exe"); 

Per uccidere un processo , è qualcosa di simile

Process[] procs = Process.GetProcessesByName("B"); 

foreach (Process proc in procs) 
    proc.Kill(); 
+0

Sì! Ecco perché ho usato il comando sopra, app. B è "CMD". Voglio lasciarlo ricominciare, è ovvio che verrà cancellato. Dimmi come: D – Noli

+0

Migliore utilizzo [Process.ID] (https://msdn.microsoft.com/en-us/library/system.diagnostics.process.id%28v=vs.110%29.aspx) e [Process.GetProcessById] (https://msdn.microsoft.com/en-us/library/76fkb36k%28v=vs.110%29.aspx) – Brettetete

+0

Mi piace molto. Chiamerei il programma B "Terminator". La cosa bella è che Terminator può aspettare che A.exe finisca per quanto tempo ha bisogno di – henon

2

Un sacco di persone suggeriscono di utilizzare Application.Restart. In realtà, questa funzione si comporta raramente come previsto. Non l'ho mai fatto chiudere l'applicazione da cui lo chiamo. Ho sempre dovuto chiudere l'applicazione con altri metodi, come la chiusura del modulo principale.

Hai due modi per gestirlo. O si dispone di un programma esterno che chiude il processo chiamante e inizia uno nuovo,

o,

avete l'inizio del nuovo software di uccidere altre istanze della stessa applicazione, se un argomento viene passato come il riavvio.

 private void Application_Startup(object sender, StartupEventArgs e) 
     { 
      try 
      { 
       if (e.Args.Length > 0) 
       { 
        foreach (string arg in e.Args) 
        { 
         if (arg == "-restart") 
         { 
          // WaitForConnection.exe 
          foreach (Process p in Process.GetProcesses()) 
          { 
           // In case we get Access Denied 
           try 
           { 
            if (p.MainModule.FileName.ToLower().EndsWith("yourapp.exe")) 
            { 
             p.Kill(); 
             p.WaitForExit(); 
             break; 
            } 
           } 
           catch 
           { } 
          } 
         } 
        } 
       } 
      } 
      catch 
      { 
      } 
     } 
+0

Tutto ciò che ignorava le eccezioni con blocchi 'catch' vuoti ... Ewww .... – jeuxjeux20

+0

Le dichiarazioni di debug sono soggettive. Chiunque usi il codice può gestirlo come preferisce. – JeremyK

1

Un altro modo per fare ciò che si sente un po 'più pulito di queste soluzioni è eseguire un file batch che include un ritardo specifico per attendere la chiusura dell'applicazione corrente. Questo ha il vantaggio aggiuntivo di impedire l'apertura simultanea delle due istanze dell'applicazione.

Esempio file di finestre batch ("Restart.bat"):

sleep 5 
start "" "C:\Dev\MyApplication.exe" 

Nell'applicazione, aggiungere questo codice:

// Launch the restart batch file 
Process.Start(@"C:\Dev\restart.bat"); 

// Close the current application (for WPF case) 
Application.Current.MainWindow.Close(); 

// Close the current application (for WinForms case) 
Application.Exit(); 
1

La mia soluzione:

 private static bool _exiting; 
    private static readonly object SynchObj = new object(); 

     public static void ApplicationRestart(params string[] commandLine) 
    { 
     lock (SynchObj) 
     { 
      if (Assembly.GetEntryAssembly() == null) 
      { 
       throw new NotSupportedException("RestartNotSupported"); 
      } 

      if (_exiting) 
      { 
       return; 
      } 

      _exiting = true; 

      if (Environment.OSVersion.Version.Major < 6) 
      { 
       return; 
      } 

      bool cancelExit = true; 

      try 
      { 
       List<Form> openForms = Application.OpenForms.OfType<Form>().ToList(); 

       for (int i = openForms.Count - 1; i >= 0; i--) 
       { 
        Form f = openForms[i]; 

        if (f.InvokeRequired) 
        { 
         f.Invoke(new MethodInvoker(() => 
         { 
          f.FormClosing += (sender, args) => cancelExit = args.Cancel; 
          f.Close(); 
         })); 
        } 
        else 
        { 
         f.FormClosing += (sender, args) => cancelExit = args.Cancel; 
         f.Close(); 
        } 

        if (cancelExit) break; 
       } 

       if (cancelExit) return; 

       Process.Start(new ProcessStartInfo 
       { 
        UseShellExecute = true, 
        WorkingDirectory = Environment.CurrentDirectory, 
        FileName = Application.ExecutablePath, 
        Arguments = commandLine.Length > 0 ? string.Join(" ", commandLine) : string.Empty 
       }); 

       Application.Exit(); 
      } 
      finally 
      { 
       _exiting = false; 
      } 
     } 
    } 
+0

Si finisce sempre per avere due istanze in esecuzione. – Noli

+0

risolto. Il lock() e MethodInvoker se lo usi per thread esterno! –

0

Per. La soluzione applicativa di rete si presenta così:

System.Web.HttpRuntime.UnloadAppDomain() 

L'ho utilizzato per riavviare la mia applicazione Web dopo aver modificato AppSettings nel file myconfig.

System.Configuration.Configuration configuration = WebConfigurationManager.OpenWebConfiguration("~"); 
configuration.AppSettings.Settings["SiteMode"].Value = model.SiteMode.ToString(); 
configuration.Save();