代码之家  ›  专栏  ›  技术社区  ›  user

C-重新启动应用程序与“程序已运行”错误冲突

  •  0
  • user  · 技术社区  · 15 年前

    当我调用application.restart()方法时,会出现一个错误,检测应用程序当前是否正在运行。这附近还有吗?

        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());
            }
        }
    
    5 回复  |  直到 14 年前
        1
  •  1
  •   SLaks    15 年前

    最有效的方法是从vb.net继承 WindowsFormsApplicationBase 类,也可以在C中使用,并设置 IsSingleInstance 属性到 true . 这将使用互斥体,并在重命名exe文件时继续工作。

        2
  •  3
  •   Bob Nadler    15 年前

    使用互斥体。例如。: A Single Instance Application which Minimizes to the System Tray when Closed . 这个例子比您可能需要的要复杂,但是使用互斥体的基本单实例概念工作得很好。

        3
  •  1
  •   Daniel MoÅ¡mondor    14 年前

    我也遇到过类似的问题,但我的问题与无法管理的内存泄漏有关,我在一个必须全天候运行的应用程序上找不到这一问题。我和客户约定,如果内存消耗超过了定义的值,重启应用程序的安全时间是凌晨3点。

    我试过 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);
        }
    }
    
        4
  •  0
  •   John K    15 年前

    尝试将重新启动代码连接到 Application.ApplicationExit 事件作为侦听器方法。然后您将调用application.exit以使代码间接运行。

    编辑 :添加的代码示例:

    例如,当用户单击重新启动按钮或应用程序决定重新启动时,调用这个restartMesmartly()方法。你不必担心骗局,它会奏效的。

    void RestartMeSmartly() {
        Application.ApplicationExit += BeforeExiting;
        Application.Exit();
    }
    
    void BeforeExiting(object sender, EventArgs args) {
        Application.Restart();
    }
    
        5
  •  0
  •   SLaks    15 年前

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

    换言之,

    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