21

I want to build my application with the function to restart itself. I found on codeproject

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();

This does not work at all... And the other problem is, how to start it again like this? Maybe there are also arguments to start applications.

Edit:

http://www.codeproject.com/script/Articles/ArticleVersion.aspx?aid=31454&av=58703
slavoo
  • 5,798
  • 64
  • 37
  • 39
Noli
  • 604
  • 2
  • 10
  • 27
  • What happens, any exceptions or just nothing? – Paulie Waulie Mar 07 '12 at 15:09
  • 3
    "This does not work at all" is a poor description of a problem. What is not working? Errors? Exceptions? Something else? – Oded Mar 07 '12 at 15:11
  • Are you sure that's the correct arguments? That looks like it's going to try and delete your application! In general you'll have to have some other process restart it for you - which they're trying to do here with cmd - although maybe the parent process can just CreateProcess itself, or even somehow create a new AppDomain in process and destroy the old one? – Rup Mar 07 '12 at 15:11
  • FYI, there's no such thing as "C#.NET". The language is named "C#". – John Saunders Mar 07 '12 at 15:14
  • According to your various comments below, you cannot tolerate two instances of the application at one time. Can you use a synchronization mechanism such as a named mutex to ensure that no more than one instance is attempting to do useful work? A second instance could start, but you could have it immediately exit if there is already a productive instance. To restart, the first instance would release the mutex, trigger the restart, and exit. – HABO Mar 07 '12 at 15:41

10 Answers10

48

I use similar code to the code you tried when restarting apps. I send a timed cmd command to restart the app for me like this:

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(); 

The command is sent to the OS, the ping pauses the script for 2-3 seconds, by which time the application has exited from Application.Exit(), then the next command after the ping starts it again.

Note: The \" puts quotes around the path, incase it has spaces, which cmd can't process without quotes.

Hope this helps!

Bali C
  • 30,582
  • 35
  • 123
  • 152
  • This solution is awesome, but using the ping command as a delay makes it feel a bit 'dirty' - unfortunately it doesn't seem like there is any other way to do it - I tried the (batch) 'sleep' command and it doesn't work. – dodgy_coder May 15 '12 at 02:46
  • Thanks. Yeah it is a bit hacky, but it means you can reliably restart the app without having to install anything else separately. I think the batch `sleep` command is an extra you have to install manually. – Bali C May 15 '12 at 08:29
  • 1
    The two second pause does not work for me. It just launches the specified application immediately. In my case, I'm using an updater application which then fails because the running application has not yet shut down releasing it's files. I'm using .NET 4.5.1 on Windows 10. – Craig Nov 09 '16 at 02:35
  • 1
    Thanks it worked great for me. I just suggest to write Info.arguments = $"/C ping 127.0.0.1 -n 4 && {Environment.CommandLine}" to restart the application preserving the arguments that were provided at the initial run. – Kro Oct 31 '18 at 14:40
  • 3
    Instead of `Application.ExecutablePath` better use `Process.GetCurrentProcess().MainModule.FileName` In some places you cannot call ExecutablePath – Guy Jul 09 '19 at 11:10
  • For a command that works on both Windows and Linux (tested on Debian), I use `ping 127.0.0.1 -w 2`. Untested on Mac. – Lunar May 08 '21 at 21:28
30

Why not use

Application.Restart();

??

More on Restart

Shai
  • 25,159
  • 9
  • 44
  • 67
9

Why not just the following?

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

If you want to be sure the app does not run twice either use Environment.Exit(-1) which kills the process instantaneously (not really the nice way) or something like starting a second app, which checks for the process of the main app and starts it again as soon as the process is gone.

Asken
  • 7,679
  • 10
  • 45
  • 77
Christoph Fink
  • 22,727
  • 9
  • 68
  • 113
  • I forgot, I dont want to, that this app is opened twice at the same time. – Noli Mar 07 '12 at 15:12
  • 1
    @Noli The second line takes care of that. – user247702 Mar 07 '12 at 15:13
  • Then try `"/C choice /C Y /N /D Y /T 3 & "+Application.ExecutablePath;` as the "Del" will delete your application, but it can still happen, that the app runs twice if the closing takes longer then 3s... – Christoph Fink Mar 07 '12 at 15:16
  • 1
    This above will start the application TWICE so for a very short time both are active untill in line 2 the current proc gets canceled. – Noli Mar 07 '12 at 15:32
  • Why is this such a big deal (if you tell us that we may can find a better way)? Especially if you use `Environment.Exit(-1)` it is maybe a few ms and the first one will be closed before the new process is even started completely... – Christoph Fink Mar 07 '12 at 15:39
  • @Noli I don't see a problem with that. If you're restarting your application, it should not be doing anything at that point, so it shouldn't matter if it's active for a very short time. – user247702 Mar 07 '12 at 15:39
  • I have experience with Exit not closing the application when called. – JeremyK Mar 07 '12 at 15:40
  • @JeremyK: Maybe with `Application.Exit` as other componets can cancel that event, but `Environment.Exit` terminates the process. – Christoph Fink Mar 07 '12 at 15:43
7

You have the initial application A, you want to restart. So, When you want to kill A, a little application B is started, B kill A, then B start A, and kill B.

To start a process:

Process.Start("A.exe");

To kill a process, is something like this

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

foreach (Process proc in procs)
   proc.Kill();
Mentezza
  • 627
  • 5
  • 16
  • Yes! Thats why I used the comand above, app. B is "CMD". I want to let it start again, its allright that it will get deleted. Just tell me how :D – Noli Mar 07 '12 at 15:35
  • Better use [Process.ID](https://msdn.microsoft.com/en-us/library/system.diagnostics.process.id%28v=vs.110%29.aspx) and [Process.GetProcessById](https://msdn.microsoft.com/en-us/library/76fkb36k%28v=vs.110%29.aspx) – boop Jan 29 '15 at 01:35
  • I like that a lot. I'd call program B "Terminator". The nice thing is, that Terminator can wait for A.exe to finalize however long it needs to – henon Jun 01 '16 at 17:58
5

A lot of people are suggesting to use Application.Restart. In reality, this function rarely performs as expected. I have never had it shut down the application I am calling it from. I have always had to close the application through other methods such as closing the main form.

You have two ways of handling this. You either have an external program that closes the calling process and starts a new one,

or,

you have the start of your new software kill other instances of same application if an argument is passed as restart.

        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
            {
            }
        }
JeremyK
  • 1,075
  • 1
  • 22
  • 45
2

Another way of doing this which feels a little cleaner than these solutions is to run a batch file which includes a specific delay to wait for the current application to terminate. This has the added benefit of preventing the two application instances from being open at the same time.

Example windows batch file ("restart.bat"):

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

In the application, add this code:

// 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();
dodgy_coder
  • 12,407
  • 10
  • 54
  • 67
2

Winforms has the Application.Restart() method, which does just that. If you're using WPF, you can simply add a reference to System.Windows.Forms and call it.

Avner Shahar-Kashtan
  • 14,492
  • 3
  • 37
  • 63
  • Application.Restart does not work. It rarely shuts down the application calling the function. It is very unreliable – JeremyK Mar 07 '12 at 15:41
1

My solution:

        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;
            }
        }
    }
Martin.Martinsson
  • 1,894
  • 21
  • 25
1

This worked for me:

Process.Start(Process.GetCurrentProcess().MainModule.FileName);
Application.Current.Shutdown();

Some of the other answers have neat things like waiting for a ping to give the initial application time to wind down, but if you just need something simple, this is nice.

bwall
  • 984
  • 8
  • 22
0

For .Net application solution looks like this:

System.Web.HttpRuntime.UnloadAppDomain()

I used this to restart my web application after changing AppSettings in myconfig file.

System.Configuration.Configuration configuration = WebConfigurationManager.OpenWebConfiguration("~");
configuration.AppSettings.Settings["SiteMode"].Value = model.SiteMode.ToString();
configuration.Save();
Pal
  • 756
  • 2
  • 10
  • 20