Restart an application by itself
Asked Answered
C

11

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
Cyrie answered 7/3, 2012 at 15:7 Comment(5)
What happens, any exceptions or just nothing?Thunderbolt
"This does not work at all" is a poor description of a problem. What is not working? Errors? Exceptions? Something else?Subterrane
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?Peasecod
FYI, there's no such thing as "C#.NET". The language is named "C#".Herbert
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.Periodate
J
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!

Joeljoela answered 8/3, 2012 at 9:54 Comment(6)
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.Medievalism
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.Joeljoela
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.Besmirch
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.Feodore
Instead of Application.ExecutablePath better use Process.GetCurrentProcess().MainModule.FileName In some places you cannot call ExecutablePathSwanee
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.Flutist
S
31

Why not use

Application.Restart();

??

More on Restart

Supernova answered 7/3, 2012 at 15:15 Comment(3)
@Noli: Why? This does exactly what you asked for: Shuts down the application and starts a new instance immediately.Pisano
Application.Restart does not work. It rarely shuts down the application calling the function. It is very unreliable.Chavira
Works only in FormsAnastatius
P
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.

Pisano answered 7/3, 2012 at 15:10 Comment(8)
I forgot, I dont want to, that this app is opened twice at the same time.Cyrie
@Cyrie The second line takes care of that.Thundering
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...Pisano
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.Cyrie
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...Pisano
@Cyrie 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.Thundering
I have experience with Exit not closing the application when called.Chavira
@JeremyK: Maybe with Application.Exit as other componets can cancel that event, but Environment.Exit terminates the process.Pisano
A
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();
Archivolt answered 7/3, 2012 at 15:18 Comment(3)
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 :DCyrie
Better use Process.ID and Process.GetProcessByIdColumbary
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 toPelerine
C
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
            {
            }
        }
Chavira answered 7/3, 2012 at 15:45 Comment(2)
Debug statements are subjective. Whoever uses the code can handle it how they like.Chavira
On your 2nd option, how do you avoid the code killing its own process?Unblushing
T
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.

Terpsichorean answered 7/3, 2012 at 15:16 Comment(1)
Application.Restart does not work. It rarely shuts down the application calling the function. It is very unreliableChavira
M
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();
Medievalism answered 15/5, 2012 at 2:32 Comment(0)
G
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;
            }
        }
    }
Golconda answered 4/7, 2016 at 21:41 Comment(2)
You still end up having two instaces running.Cyrie
Fixed it. The lock() and MethodInvoker if you use it by external thread!Golconda
B
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.

Bunkhouse answered 16/11, 2020 at 22:5 Comment(0)
B
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();
Bespread answered 17/8, 2016 at 10:47 Comment(0)
P
0

In case the app is running as a Windows Service it's quite easy to restart it using powershell:

var psi = new ProcessStartInfo(
    "pwsh",
    "-Command \"Start-Sleep -Seconds 3; Restart-Service -Name 'TheServiceName';\""
);
Process.Start(psi);
Environment.Exit(0);
Pydna answered 14/7, 2024 at 18:27 Comment(0)

© 2022 - 2025 — McMap. All rights reserved.