2

我正在尝试在 WPF 中重新启动应用程序。

我尝试了以下方法:

Process.Start(Application.ExecutablePath);
Process.GetCurrentProcess().Kill();

它不起作用,因为应用程序设置为单实例应用程序。

然后我厌倦了这个:

Process.GetCurrentProcess().Kill();
Process.Start(Application.ExecutablePath);

它不起作用,因为一旦我们终止进程,它就不会到达第 2 行

有没有办法安排 .Start 以便我不会遇到问题 #1。

4

2 回答 2

2

您可以启动一个辅助应用程序,然后在延迟后重新启动您的主程序。几年前我写了一个自我更新程序时,这就是我采取的实现路径。它只是一个简单的程序,将可执行文件作为命令行参数,会休眠十分之一秒,然后 .Start 它。

比我采用的更好的实现路径是让新启动的程序等待启动它的进程终止。等待任意长度的时间可能会使事情复杂化。为了实现这一点,我可能会将进程 ID 传递给重新启动器,以便它确切知道要等待哪个进程。

于 2010-06-16T17:54:09.997 回答
2

这并不像你想象的那么难。您需要做的就是调用以下方法,并为重新启动的实例传入命令行:

public static void RestartMe(string commandLine)
{
  var myId = Process.GetCurrentProcess().Id;
  var myPath = Assembly.GetEntryAssembly().CodeBase.Replace("file:///", "");
  var systemPath = typeof(object).Assembly.CodeBase.Replace("file:///", "");

  var tempPath = Path.GetTempFileName();

  File.WriteAllText(tempPath + ".cs", @"
    using System;
    using System.Diagnostics;
    public class App
    {
      public static void Main(string[] args)
      {
        try { Process.GetProcessById(" + myId + @").WaitForExit(); } catch {}
        Process.Start(""" + myPath + @""", Environment.CommandLine);
      }
    }");

  var compiler = new ProcessStartInfo
  {
    FileName = Path.Combine(Path.GetDirectoryName(systemPath), "csc.exe"),
    Arguments = tempPath + ".cs",
    WorkingDirectory = Path.GetDirectoryName(tempPath),
    WindowStyle = ProcessWindowStyle.Hidden,
  };

  var restarter = new ProcessStartInfo
  {
    FileName = tempPath + ".exe",
    Arguments = commandLine,
    WindowStyle = ProcessWindowStyle.Hidden,
  };

  Process.Start(compiler).WaitForExit();
  Process.Start(restarter); // No WaitForExit: restarter WaitForExits us instead

  File.Delete(tempPath);
  File.Delete(tempPath + ".cs");
  Environment.Exit(0);
}

它是如何工作的:这实际上确实创建了另一个“重启”程序,但它可以轻松且自动地完成。重启程序具有当前进程 ID 和内置的可执行文件名。它总是会找到编译器,因为 NET Framework 版本在与 System.dll 相同的文件夹中附带了兼容的 csc.exe。

于 2010-06-16T21:25:47.400 回答