C#唯一进程的处理
- 1.使用进程(Process)判断
- winform
- WPF
- 执行效果:
- 2.使用互斥体(Metux)实现
- 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);
/// <summary>
/// 应用程序的主入口点。
/// </summary>
[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
{
/// <summary>
/// 焦点切换指定的窗口,并将其带到前台
/// </summary>
/// <param name="hWnd"></param>
/// <param name="fAltTab"></param>
[DllImport("user32.dll")]
public static extern void SwitchToThisWindow(IntPtr hWnd, bool fAltTab);
/// <summary>
/// 应用程序的主入口点。
/// </summary>
[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
{
/// <summary>
/// Interaction logic for App.xaml
/// </summary>
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);
}
}
}
实现效果:
效果一样