如何重新启动 WPF 应用程序?

如何重新启动 WPF 应用程序? 在 Windows 表单中,我使用

System.Windows.Forms.Application.Restart();

如何做到这一点在 WPF?

92517 次浏览

I found this: It works. But. Is there any better way?

System.Diagnostics.Process.Start(Application.ResourceAssembly.Location);
Application.Current.Shutdown();

I've used this in WPF, successfully:

System.Windows.Forms.Application.Restart();
System.Windows.Application.Current.Shutdown();

These proposed solutions may work, but as another commenter has mentioned, they feel kind of like a quick hack. Another way of doing this which feels a little cleaner is to run a batch file which includes a delay (e.g. 5 seconds) to wait for the current (closing) application to terminate.

This prevents the two application instances from being open at the same time. In my case its invalid for two application instances to be open at the same time - I'm using a mutex to ensure there is only one application open - due to the application using some hardware resources.

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

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

And in the WPF application, add this code:

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


// Close the current application
Application.Current.MainWindow.Close();
Application.Restart();

or

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

In my program I have a mutex to ensure only one instance of the application running on a computer. This was causing the newly started application to not start because the mutex had not been release in a timely fashion. As a result I put a value into Properties.Settings that indicates that the application is restarting. Before calling Application.Restart() the Properties.Settings value is set to true. In Program.Main() I also added a check for that specific property.settings value so that when true it is reset to false and there is a Thread.Sleep(3000);

In your program you may have the logic:

if (ShouldRestartApp)
{
Properties.Settings.Default.IsRestarting = true;
Properties.Settings.Default.Save();
Application.Restart();
}

In Program.Main()

[STAThread]
static void Main()
{
Mutex runOnce = null;


if (Properties.Settings.Default.IsRestarting)
{
Properties.Settings.Default.IsRestarting = false;
Properties.Settings.Default.Save();
Thread.Sleep(3000);
}


try
{
runOnce = new Mutex(true, "SOME_MUTEX_NAME");


if (runOnce.WaitOne(TimeSpan.Zero))
{
Application.EnableVisualStyles();
Application.SetCompatibleTextRenderingDefault(false);
Application.Run(new Form1());
}
}
finally
{
if (null != runOnce)
runOnce.Close();
}
}

That's it.

 Application.Restart();
Process.GetCurrentProcess().Kill();

work like a charm for me

Application.Current.Shutdown();
System.Windows.Forms.Application.Restart();

In this order worked for me, the other way around just started another instance of the app.

Runs a new instance of the program by command line after 1 second delay. During the delay current instance shutdown.

ProcessStartInfo Info = new ProcessStartInfo();
Info.Arguments = "/C choice /C Y /N /D Y /T 1 & START \"\" \"" + Assembly.GetEntryAssembly().Location + "\"";
Info.WindowStyle = ProcessWindowStyle.Hidden;
Info.CreateNoWindow = true;
Info.FileName = "cmd.exe";
Process.Start(Info);
Process.GetCurrentProcess().Kill();

EDIT:

I fixed the code:

instead of: Assembly.GetExecutingAssembly().Location

this: Assembly.GetEntryAssembly().Location

This is important when the function runs in a separate dll.

And -

instead of: Application.Current.Shutdown();

this: Process.GetCurrentProcess().Kill();

It will work both in WinForms and in WPF and if you write a dll that is designed for both then it is very important.

Taking Hooch's example, I used the following:

using System.Runtime.CompilerServices;


private void RestartMyApp([CallerMemberName] string callerName = "")
{
Application.Current.Exit += (s, e) =>
{
const string allowedCallingMethod = "ButtonBase_OnClick"; // todo: Set your calling method here


if (callerName == allowedCallingMethod)
{
Process.Start(Application.ResourceAssembly.Location);
}
};


Application.Current.Shutdown(); // Environment.Exit(0); would also suffice
}