2009-10-30 55 views
0

当我调用Application.Restart()方法时,出现错误,检测应用程序当前是否正在运行。有没有办法解决?C# - 重新启动应用程序与“程序已在运行”错误冲突

static void Main(string[] args) 
    { 
     string proc = Process.GetCurrentProcess().ProcessName; 
     Process[] processes = Process.GetProcessesByName(proc); 
     if (processes.Length > 1) 
     { 
      MessageBox.Show("Program is already running.", "Error", MessageBoxButtons.OK, MessageBoxIcon.Error); 
     } 
     else 
     { 
      Application.EnableVisualStyles(); 
      Application.SetCompatibleTextRenderingDefault(false); 
      Application.Run(new Form1()); 
     } 
    } 
+0

请注意,如果您的用户重命名该exe文件,他们仍然可以启动多个副本。 – SLaks 2009-10-30 03:20:38

回答

0

最简单的方法是在退出前添加延迟。

换句话说,

string proc = Process.GetCurrentProcess().ProcessName; 
if (Process.GetProcessesByName(proc).Length > 1) { 
    Thread.Sleep(500);  //500 milliseconds; you might need to wait longer 
    if (Process.GetProcessesByName(proc).Length > 1) { 
     MessageBox.Show("Program is already running.", "Error", MessageBoxButtons.OK, MessageBoxIcon.Error); 
     return; 
    } 
} //no else 
+0

为什么这会降低投票率? – SLaks 2009-10-30 03:41:29

+0

对不起,但投票与睡眠真的很难看。我不会为任何目的推荐它。 – 2009-10-30 03:42:43

+0

我没有说这是最好的;我说这是最简单的。最好的解决办法是我的其他答案。 – SLaks 2009-10-30 03:44:27

0

您可以尝试重启代码挂接到Application.ApplicationExit事件作为一个监听器方法。然后你会调用Application.Exit来使代码间接运行。

编辑:添加代码示例:

例如,当用户点击重新启动按钮或应用决定重新启动,调用此RestartMeSmartly()方法。你不必担心欺骗 - 它会起作用。

void RestartMeSmartly() { 
    Application.ApplicationExit += BeforeExiting; 
    Application.Exit(); 
} 

void BeforeExiting(object sender, EventArgs args) { 
    Application.Restart(); 
} 
+0

实际上,最好在程序执行的最后一个托管代码'Main'方法结束时重新启动程序。 (终结者除外)然而,即便如此,这将是非确定性的,我不会推荐它。 – SLaks 2009-10-30 03:27:25

+0

我们如何知道Application.ApplicationExit事件没有在Main方法的末尾被调用,甚至后来被运行时调用?也许ApplicationExit更好。 – 2009-10-30 03:36:25

+0

在调用Application.Run期间,消息循环退出时调用Application.Exit。 – SLaks 2009-10-30 03:39:38

1

我有一个类似的问题,但我的是无法管理的内存泄漏,我无法找到一个必须全天候运行的应用程序。对于客户,我同意如果内存消耗超过定义的值,则重新启动应用程序的安全时间为上午03:00。

我试过Application.Restart,但由于它似乎使用了一些在已经运行时启动新实例的机制,所以我去了另一个方案。我使用了文件系统句柄持续存在的技巧,直到创建它们的进程死亡。所以,从应用程序,我把文件放到磁盘上,并没有Dispose()的句柄。我使用该文件发送“我自己”的可执行文件和启动目录(以增加灵活性)。

代码:

_restartInProgress = true; 
string dropFilename = Path.Combine(Application.StartupPath, "restart.dat"); 
StreamWriter sw = new StreamWriter(new FileStream(dropFilename, FileMode.Create, FileAccess.ReadWrite, FileShare.ReadWrite)); 
sw.WriteLine(Application.ExecutablePath); 
sw.WriteLine(Application.StartupPath); 
sw.Flush(); 
Process.Start(new ProcessStartInfo 
{ 
    FileName = Path.Combine(Application.StartupPath, "VideoPhill.Restarter.exe"), 
    WorkingDirectory = Application.StartupPath, 
    Arguments = string.Format("\"{0}\"", dropFilename) 
}); 
Close(); 

Close()在年底将启动的应用程序停机,并且文件句柄我用StreamWriter这里将举行开到过程真的死了。然后...

Restarter.exe开始生效。它尝试以独占模式读取文件,阻止它获得访问权限,直到主应用程序未死,然后启动主应用程序,删除文件并存在。我想这不能简单:

static void Main(string[] args) 
{ 
    string filename = args[0]; 
    DateTime start = DateTime.Now; 
    bool done = false; 
    while ((DateTime.Now - start).TotalSeconds < 30 && !done) 
    { 
     try 
     { 
      StreamReader sr = new StreamReader(new FileStream(filename, FileMode.Open, FileAccess.ReadWrite, FileShare.ReadWrite)); 
      string[] runData = new string[2]; 
      runData[0] = sr.ReadLine(); 
      runData[1] = sr.ReadLine(); 
      Thread.Sleep(1000); 
      Process.Start(new ProcessStartInfo { FileName = runData[0], WorkingDirectory = runData[1] }); 
      sr.Dispose(); 
      File.Delete(filename); 
      done = true; 
     } 
     catch (Exception ex) 
     { 
      Console.WriteLine(ex.Message); 
     } 
     Thread.Sleep(1000); 
    } 
} 
相关问题