• C#唯一进程的处理Winform/WPF


    在C#客户端(Winform/WPF)开发过程中,有的情况需要确保程序的唯一性,如果启动同时启动同一个程序多次,可能导致数据,通信等异常。下面有两种方法来实现唯一进程

    1.使用进程(Process)判断

    需要引入SwitchToThisWindow,用于将已启动程序切换到最前显示。

    使用Process获取同名的程序,判断是否有同名但是不同Id的进程,如有,则关闭当前程序;如果没有,则进行正常启动。

    具体代码示例如下:

    winform

    internal static class Program
    {
        [DllImport("user32.dll")]
        public static extern void SwitchToThisWindow(IntPtr hWnd, bool fAltTab);
    
        /// 
        /// 应用程序的主入口点。
        /// 
        [STAThread]
        static void Main()
        {
            Process current = Process.GetCurrentProcess();
            Process[] processes = Process.GetProcessesByName(current.ProcessName);
    
            foreach (Process process in processes)
            {
                if (process.Id != current.Id)
                { //根据进程ID排除当前进程
                    MessageBox.Show("系统已启动");
                    IntPtr handle = process.MainWindowHandle;
                    //将原进程显示在最前
                    SwitchToThisWindow(handle, true);
                    current.Close();
                    return;
                }
            }
            //正常启动程序
            Application.EnableVisualStyles();
            Application.SetCompatibleTextRenderingDefault(false);
            Application.Run(new Form1());
        }
    }
    

    WPF

    在App.xaml.cs中重写OnStartup程序,然后添加下面代码

      [DllImport("user32.dll")]
      public static extern void SwitchToThisWindow(IntPtr hWnd, bool fAltTab);
    
      protected override void OnStartup(StartupEventArgs e)
      {
          Process currentProcess = Process.GetCurrentProcess(); //获取当前进程
          //获取当前运行程序完全限定名
          string currentFileName = currentProcess.MainModule.FileName;
          Process[] processes = Process.GetProcessesByName(currentProcess.ProcessName);
          foreach (Process process in processes)
          {
              if (process.Id != currentProcess.Id)
              { //根据进程ID排除当前进程
                  MessageBox.Show("系统已启动");
                  IntPtr handle = process.MainWindowHandle;
                  //将原进程显示在最前
                  SwitchToThisWindow(handle, true);
                  Application.Current.Shutdown();
                  return;
              }
          }
          base.OnStartup(e);
      }
    

    执行效果:

    第二次启动,显示弹窗,然后关闭之后显示第一个程序窗体。

    在这里插入图片描述

    2.使用互斥体(Metux)实现

    基本实现方式一样,只是一开始判断使用使用互斥体Metux进行判断,选择一个字符串进行创建,如果未存在,则为True,继续创建,如果已经存在了,则为False,关闭当前进程,显示原进程。

    winform

    using System;
    using System.Collections.Generic;
    using System.Diagnostics;
    using System.Linq;
    using System.Runtime.InteropServices;
    using System.Threading;
    using System.Threading.Tasks;
    using System.Windows.Forms;
    
    namespace WindowsFormsApp1
    {
        internal static class Program
        {
            /// 
            /// 焦点切换指定的窗口,并将其带到前台
            /// 
            /// 
            /// 
            [DllImport("user32.dll")]
            public static extern void SwitchToThisWindow(IntPtr hWnd, bool fAltTab);
    
            /// 
            /// 应用程序的主入口点。
            /// 
            [STAThread]
            static void Main()
            {
                bool createdNew;
                Mutex mutex = new Mutex(true, "ED4D323242424324242ERS", out createdNew); // 使用唯一的GUID作为互斥锁名称
    
                //
                if (!createdNew)
                {
                    var current = Process.GetCurrentProcess();
                    var processes = Process.GetProcessesByName(current.ProcessName);
    
                    var process = processes.FirstOrDefault(x => x.Id == current.Id);
                    if (process != null)
                    {
                        MessageBox.Show("系统已启动");
                        IntPtr handle = process.MainWindowHandle;
                        SwitchToThisWindow(handle, true);
                    }
                    current.Close();
                    return;
                }
    
                Application.EnableVisualStyles();
                Application.SetCompatibleTextRenderingDefault(false);
                Application.Run(new Form1());
            }
        }
    }
    
    

    WPF

    在App.xaml.cs中重写OnStartup程序,然后添加下面代码

     using System.Configuration;
    using System.Data;
    using System.Diagnostics;
    using System.Runtime.InteropServices;
    using System.Windows;
    
    namespace WpfApp1
    {
        /// 
        /// Interaction logic for App.xaml
        /// 
        public partial class App : Application
        {
            [DllImport("user32.dll")]
            public static extern void SwitchToThisWindow(IntPtr hWnd, bool fAltTab);
    
            protected override void OnStartup(StartupEventArgs e)
            {
                bool createdNew;
                Mutex mutex = new Mutex(true, "ED4D324324242ERS", out createdNew); // 使用唯一的GUID作为互斥锁名称
    
                if (!createdNew)
                {
                    var current = Process.GetCurrentProcess();
                    var processes = Process.GetProcessesByName(current.ProcessName);
    
                    var process = processes.FirstOrDefault(x => x.Id == current.Id);
                    if (process != null)
                    {
                        IntPtr handle = process.MainWindowHandle;
                        SwitchToThisWindow(handle, true);
                    }
                    Application.Current.Shutdown();
                }
    
                //正常启动
                base.OnStartup(e);
            }
        }
    }
    
    

    实现效果:

    效果一样
    在这里插入图片描述

  • 相关阅读:
    Windows10 前端项目所需的node.js安装环境
    Empire(三)域内渗透
    Android面试每日一题(4): 哪些情况下会导致oom问题?
    Tomcat 使用过滤器阻止 IP 地址
    微服务 Spring Boot 整合Redis分布式锁 Lua脚本 实现优惠卷秒杀 一人一单
    基于spingboot的websocket订阅、广播、多人聊天室示例
    数据治理-定义数据治理运营框架
    C++初阶-内存管理
    宋浩高等数学笔记(一)函数与极限
    json进阶---jackson底层之JsonParser理解使用(springboot多结构参数的映射方法的实现思路)
  • 原文地址:https://blog.csdn.net/qq_39427511/article/details/139772291