C# 主窗口 单例 唯一进程 互斥锁

用第一个就行

csharp 复制代码
using Microsoft.VisualBasic.ApplicationServices;

namespace EngineEMS {

    internal static class Program {

        /// <summary>
        /// 应用程序的主入口点
        /// </summary>
        [STAThread]
        private static void Main() {
            ApplicationConfiguration.Initialize();

            // 使用单实例管理器
            var singleInstanceManager = new SingleInstanceManager();
            singleInstanceManager.Run(Environment.GetCommandLineArgs());
        }
    }

    // 单实例应用程序管理器
    public class SingleInstanceManager : WindowsFormsApplicationBase {
        private MainForm _mainForm;

        public SingleInstanceManager() {
            // 启用单实例应用
            IsSingleInstance = true;
        }

        // 当创建新实例时执行
        protected override void OnCreateMainForm() {
            _mainForm = new MainForm();
            MainForm = _mainForm;
        }

        // 当检测到已有实例时执行
        protected override void OnStartupNextInstance(StartupNextInstanceEventArgs eventArgs) {
            base.OnStartupNextInstance(eventArgs);

            // 激活已存在的主窗口
            if (MainForm != null) {
                MainForm.WindowState = FormWindowState.Maximized; // 确保窗口最大化
                MainForm.Activate();    // 激活窗口
                MainForm.BringToFront();// 前置窗口
                MainForm.Focus();       // 设置焦点
            }
        }
    }
}

csharp 复制代码
using System;
using System.IO.Pipes;
using System.Threading;
using System.Windows.Forms;

namespace EngineEMS {
    internal static class Program {
        // 应用程序唯一标识(建议生成新的GUID)
        private static readonly string UniqueAppId = $"{{AFC5ASE5-LGHJ-4D5C-9A5A-CNNO20010810}}";
        private static readonly string PipeName = $"EngineEMS_{UniqueAppId}";
        private static MainForm _mainForm;

        /// <summary>
        /// 应用程序的主入口点
        /// </summary>
        [STAThread]
        private static void Main() {
            using var mutex = new Mutex(true, UniqueAppId, out bool isNewInstance);

            if (!isNewInstance) {
                // 不是第一个实例,通过管道通知第一个实例激活窗口
                NotifyFirstInstance();
                return;
            }

            try {
                // 第一个实例,启动管道服务器监听新实例
                StartPipeServer();

                // 正常启动应用程序
                ApplicationConfiguration.Initialize();
                _mainForm = new MainForm();
                Application.Run(_mainForm);
            } finally {
                // 释放互斥体
                mutex.ReleaseMutex();
            }
        }

        /// <summary>
        /// 启动命名管道服务器,监听新实例的激活请求
        /// </summary>
        private static void StartPipeServer() {
            var thread = new Thread(PipeServerLoop) {
                IsBackground = true,
                Name = "PipeServerThread"
            };
            thread.Start();
        }

        /// <summary>
        /// 管道服务器循环,持续监听新实例
        /// </summary>
        private static void PipeServerLoop() {
            while (true) {
                try {
                    using var pipeServer = new NamedPipeServerStream(
                        PipeName,
                        PipeDirection.In,
                        1,
                        PipeTransmissionMode.Byte,
                        PipeOptions.Asynchronous);

                    // 等待客户端连接
                    pipeServer.WaitForConnection();

                    // 收到连接,激活主窗口
                    _mainForm?.Invoke((Action)ActivateMainWindow);
                } catch (Exception ex) {
                    // 记录错误但不中断循环
                    Console.WriteLine($"管道服务器错误: {ex.Message}");
                    Thread.Sleep(1000); // 避免错误时CPU占用过高
                }
            }
        }

        /// <summary>
        /// 激活主窗口
        /// </summary>
        private static void ActivateMainWindow() {
            if (_mainForm == null) return;

            // 恢复窗口(如果最小化)
            if (_mainForm.WindowState == FormWindowState.Minimized) {
                _mainForm.WindowState = FormWindowState.Maximized;
            }

            // 激活并前置窗口
            _mainForm.ShowInTaskbar = true;
            _mainForm.Activate();
            _mainForm.BringToFront();
            _mainForm.Focus();
        }

        /// <summary>
        /// 通知第一个实例激活窗口
        /// </summary>
        private static void NotifyFirstInstance() {
            try {
                using var pipeClient = new NamedPipeClientStream(".", PipeName, PipeDirection.Out);
                pipeClient.Connect(1000); // 1秒超时
                // 连接成功即表示通知已发送,无需实际写入数据
            } catch (TimeoutException) {
                MessageBox.Show("程序已在运行中,但无法连接到现有实例。",
                              "程序已运行",
                              MessageBoxButtons.OK,
                              MessageBoxIcon.Information);
            } catch (Exception ex) {
                MessageBox.Show($"程序已在运行中,但发送激活请求时出错:{ex.Message}",
                              "错误",
                              MessageBoxButtons.OK,
                              MessageBoxIcon.Error);
            }
        }
    }
}
csharp 复制代码
using System;
using System.Windows.Forms;
using Microsoft.VisualBasic.ApplicationServices;

namespace EngineEMS {
    internal static class Program {
        /// <summary>
        /// 应用程序的主入口点
        /// </summary>
        [STAThread]
        private static void Main() {
            ApplicationConfiguration.Initialize();

            // 使用单实例管理器
            var singleInstanceManager = new SingleInstanceManager();
            singleInstanceManager.Run(Environment.GetCommandLineArgs());
        }
    }

    // 单实例应用程序管理器
    public class SingleInstanceManager : WindowsFormsApplicationBase {
        private MainForm _mainForm;

        public SingleInstanceManager() {
            // 启用单实例应用
            IsSingleInstance = true;
        }

        // 当创建新实例时执行
        protected override void OnCreateMainForm() {
            _mainForm = new MainForm();
            MainForm = _mainForm;
        }

        // 当检测到已有实例时执行
        protected override void OnStartupNextInstance(StartupNextInstanceEventArgs eventArgs) {
            base.OnStartupNextInstance(eventArgs);

            // 激活已存在的主窗口
            if (MainForm != null) {
                // 恢复窗口(如果最小化)
                if (MainForm.WindowState == FormWindowState.Minimized) {
                    MainForm.WindowState = FormWindowState.Normal;
                }

                // 激活并前置窗口
                MainForm.Activate();
                MainForm.BringToFront();
                MainForm.Focus();
            }

            // 处理新实例传递的命令行参数
            if (eventArgs.CommandLine.Count > 0) {
                // 可以在这里将命令行参数传递给主窗口处理
                // _mainForm.ProcessCommandLineArgs(eventArgs.CommandLine);
            }
        }
    }
}
相关推荐
布莱克6053 小时前
C/C++ 中变量的声明与定义:区别、联系与常见误区
c语言·开发语言·c++·声明·定义
LabVIEW开发3 小时前
LabVIEW 局部变量为何引发竞争条件?四种同步机制
开发语言·labview
benchmark_cc4 小时前
A 股、港股、美股如何建立统一的标的主数据格式?
开发语言·python·数据分析·pandas·量化交易·股票数据·quantdash
Zenova EdgeOS5 小时前
Go 工业边缘错误处理实战:用 errors 构建可追溯错误链
开发语言·数据库·golang
取名真是5 小时前
Python 算法知识点从基础到进阶
开发语言·python·算法
FRing035 小时前
vue2干货总结3(computed计算属性、watch监听器)
开发语言·前端·vue.js·vue2
Fatbobman(东坡肘子)6 小时前
快速消失的硬盘容量 -- 肘子的 Swift 周报 #160
开发语言·人工智能·redis·ios·swiftui·iphone·swift
揽星河..7 小时前
【C语言】底层程序设计
c语言·开发语言
JavaPub-rodert7 小时前
从零搭建通用管理后台:ShiyuAdmin 的 Go、React 与 RBAC 实践
开发语言·react.js·golang
海的透彻8 小时前
dockerfile如何快速构建容器(java服务)
java·开发语言