为什么Application.Restart()不可靠?

在C#中使用方法Application.Restart()应该重新启动当前的应用程序:但似乎这并不总是工作。

是否有这个问题的原因,有人可以告诉我,为什么它不工作?

这可能有很多原因。 这种方法不行, 相反,很多时候程序员忘记了他们已经在代码中放置了一些东西来阻止应用程序自动closures或启动。 两个例子:

  • 表单上的closures事件可以阻止应用程序的closures
  • 如果你正在检查一个已经运行的进程,那么旧的进程可能不够快,不能让新进程启动。

检查你的代码,find这样的陷阱。 如果您在空白应用程序中看到这种行为,那么实际function比代码更可能是问题。

在我的情况(没有单一实例),在哪里

 Application.Restart(); 

没有工作,

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

做了这个工作!

我遇到这种问题的唯一时间是在我的主窗体中,我有一个自定义FormClosing事件处理程序,执行逻辑和取消事件。

编辑:

我现在已经碰到另外一个例子,根据你的意见,它可能反映了你正在经历的事情。

当运行一个单一的实例应用程序,使用一个Mutex,我从一个相当embedded的位置调用Application.Restart() ,有很多清理工作。 所以看起来重启是在前一个实例完成之前启动一个新的实例,所以Mutex保持新实例的启动。

在我的程序中,我有一个互斥锁来确保只有一个应用程序在计算机上运行。 这导致新启动的应用程序无法启动,因为互斥体没有及时释放。 因此,我将一个值放入Properties.Settings ,指示应用程序正在重新启动。 在调用Application.Restart()之前,将Properties.Settings值设置为true 。 在Program.Main()我也添加了一个特定的property.settings值的检查,以便当它真正重置为false,并有一个Thread.Sleep(3000);

在你的程序中你可能有这样的逻辑:

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

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

而已。

倾倒前尝试locking。 以下是我如何启动完整的应用程序转储。 可能为你工作,可能不会。

 Context.Application.Lock(); Context.Session.Abandon(); Context.Application.RemoveAll(); Context.Application.Restart(); Context.Application.UnLock(); 

如果应用程序首次从networking位置启动,并且未经签名(先获得警告对话框),则不会重新启动,只会退出。

试试这个代码:

 bool appNotRestarted = true; 

这个代码也必须在函数中:

 if (appNotRestarted == true) { appNotRestarted = false; Application.Restart(); Application.ExitThread(); } 
 Application.Restart(); Application.ExitThread(); 

这对我的工作感谢。

我知道这是一个旧的线程,但我find了一个解决方法。 希望这会帮助有需要的人。

我需要一个解决scheme,在ClickOnce应用程序从代码启动时触发更新序列。 Applicatoin.Restart .Restart没有这样做。 我希望能够检查更新,然后调用内置的更新pipe理器,以便我不必编写自定义更新pipe理器。

  'VB Code Sample Dim strStart As String = System.Environment.GetFolderPath(Environment.SpecialFolder.StartMenu) & "\Programs\Folder\YourApplication.appref-ms" Application.Exit() Try Process.Start(strStart) Catch ex As Exception 'Do something with the exception End Try 

我看到与此解决方法唯一的问题是用户可以从开始菜单中删除快捷方式。 如果这是一个问题,您可以编写一些代码,将开始菜单链接复制到您select的某个文件夹,最好在ClickOnce应用程序文件夹中。 这很重要,因为您的应用程序的开始菜单图标不是.lnk或.exe,它实际上是一个.appref-ms链接。 请参阅ClickOnce .appref-ms比链接到.application文件多? 这个链接更详细地解释了这一点。

此代码将与ClickOnce SingleInstance应用程序一起使用。

 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 { foreach (Form f in Application.OpenForms.OfType<Form>().ToList()) { f.InvokeIfRequired(frm => { frm.FormClosing += (sender, args) => cancelExit = args.Cancel; frm.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; } } }