# 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  阅读(184)  评论(0)    收藏  举报