# C# 程序单一进程化与实现程序重启的冲突问题 #

C# 程序单一进程化与实现程序重启的冲突问题

思路借鉴
需求描述:

  1. 程序运行过程中,不能有多个实例运行,进程唯一SingletonProcess
  2. 程序自己可以重启(重新运行),或者发生网络错误等严重错误时,程序重新启动,回到登录自检前的状态

需求分析:

程序重新启动时,需要先启动一个新的Process,然后再退出当前程序。
这样便与在Program.cs里遇到禁止多重启动的逻辑冲突。代码如下:

重启代码 Process.Start(Process.GetCurrentProcess().ProcessName + ".exe"); Application.Exit();

解决方案

  1. 解决方案一:借助另一个程序实现重启功能(具体过程略)
  2. 解决方案二:重新启动时传递一个参数,用以表示目前需要执行重启逻辑,绕过SingletonProcess判断以此达到重启目的

程序重启函数

程序重启函数
public static void RestartProgram()
{
	//释放资源
	//释放资源
	//释放资源
	System.Diagnostics.Process.Start(Application.ExecutablePath, "false");
	System.Threading.Thread.Sleep(300);
	//这里暴力杀死进程,不建议
	System.Diagnostics.Process.GetCurrentProcess().Kill();
}
完整代码Program.cs static class Program { static readonly CommonLogger.Logger logger = new CommonLogger.Logger(typeof(Program)); public static bool createNew = true; [STAThread] static void Main(string[] str) { if (str != null && str.Length > 0) { if (str[0].Equals("false")) { createNew = false; } else { createNew = true; } } else { createNew = true; } using (System.Threading.Mutex m = new System.Threading.Mutex(true, Application.ProductName/*,out xxx*/)) { try { if (createNew) { Process instance = RunningInstance(); if (instance == null) { Application.EnableVisualStyles(); Application.SetCompatibleTextRenderingDefault(false); Application.Run(new FrmLoading()); } else { HandleRunningInstance(instance); } } else { //重启时 //启动新的进程杀掉旧的进程 //并将重启标识复位 createNew = true; Application.EnableVisualStyles(); Application.SetCompatibleTextRenderingDefault(false); Application.Run(new FrmLoading()); } } catch (Exception e) { logger.Error("" + e); } } logger.Info("STAThread Main End " + GlobalInfo.MianID); //单一逻辑时会执行到此处,确保新的进程没有启动,也不存在资源占用的后台进程 Environment.Exit(0); }
	#region 进程唯一
    [DllImport("User32.dll")]
    private static extern bool SetForegroundWindow(IntPtr hWnd);
    [DllImport("User32.dll")]
    private static extern bool ShowWindowAsync(IntPtr hWnd, int cmdShow);
    private static void HandleRunningInstance(Process instance)
    {
        // 确保窗口没有被最小化或最大化 
        // ShowWindowAsync(instance.MainWindowHandle, 4);
        ShowWindowAsync(instance.MainWindowHandle, 4);

        // 设置真实例程为foreground  window  
        SetForegroundWindow(instance.MainWindowHandle);// 放到最前端 
    }

    private static Process RunningInstance()
    {
        Process current = Process.GetCurrentProcess();
        Process[] processes = Process.GetProcessesByName(current.ProcessName);
        foreach (Process process in processes)
        {
            if (process.Id != current.Id)
            {
                // 确保例程从EXE文件运行 
                if (Assembly.GetExecutingAssembly().Location.Replace("/", "\\") == current.MainModule.FileName)
                {
                    return process;
                }
            }
        }
        return null;
    }
    #endregion
}
posted @ 2021-09-29 17:24  jsnr  阅读(155)  评论(0)    收藏  举报