WPF程序开发-保证程序启动唯一

前言

要保证程序唯一,有两种方式

  1. 新程序启动时发现已启动就自动退出
  2. 新程序启动发现已启动关闭之前的程序

关闭新进程

根据进程

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
protected override void OnStartup(StartupEventArgs e)
{
checkProcess();
}

private void checkProcess()
{
Console.WriteLine("程序启动");
//获取欲启动进程名
string ProcessName = Process.GetCurrentProcess().ProcessName;
//检查进程是否已经启动,已经启动则显示报错信息退出程序。
if (Process.GetProcessesByName(ProcessName).Length > 1)
{
MessageBox.Show("当前程序已在运行,请勿重复运行。");
Environment.Exit(1);//退出程序
return;
}
}

互斥锁

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
private void checkProcess()
{
//控制当前程序已经打开(即启动)
//利用Mutex互斥量实现同时只有一个进程实例在运行
//互斥锁(Mutex)
//互斥锁是一个互斥的同步对象,意味着同一时间有且仅有一个线程可以获取它。
//互斥锁可适用于一个共享资源每次只能被一个线程访问的情况
bool flag;
string ProcessName = System.Diagnostics.Process.GetCurrentProcess().ProcessName;
Mutex hMutex = new Mutex(true, ProcessName, out flag);
hMutex.WaitOne(0, false);
//上面的参数说明:
//第一个参数【initiallyOwned】:true:指示调用线程是否应具有互斥体的初始所有权
//第二个参数【name】:程序唯一name,(当前操作系统中)判定重复运行的标志
//第三个参数【createdNew】:返回值,如果检测到已经启动则返回(false)。
if (!flag)
{
MessageBox.Show("当前程序已在运行,请勿重复运行。");
Environment.Exit(1);//退出程序
return;
}
}

根据事件

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
private void checkProcess()
{
Console.WriteLine("程序启动");
bool createNew;
string strProcessName = System.Diagnostics.Process.GetCurrentProcess().ProcessName;
new EventWaitHandle(false, EventResetMode.AutoReset, strProcessName, out createNew);

if (!createNew)
{
MessageBox.Show("当前程序已在运行,请勿重复运行。");
Current.Shutdown();
Environment.Exit(0);
return;
}
}

关闭旧进程

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
private static void StopSameProcess()
{
var current = Process.GetCurrentProcess();
string strProcessName = current.ProcessName;
var processList = Process.GetProcessesByName(strProcessName);
foreach (var process in processList)
{
if (process.Id == current.Id) continue;
try
{
MessageBox.Show("当前程序已在运行,请勿重复运行。");
process.Kill(); //结束进程
}
catch (Exception)
{
}
}
}

让进程对应的窗口显示

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
[DllImportAttribute("User32.dll")]
private static extern int FindWindow(String ClassName, String WindowName);

[DllImport("user32.dll")]
public static extern bool SetForegroundWindow(int hWnd);

public static void DoOnProcess(string processName)
{
var allProcs = Process.GetProcessesByName(processName);
if (allProcs.Length > 0)
{
Process proc = allProcs[0];
int hWnd = FindWindow(null, proc.MainWindowTitle.ToString());
SetForegroundWindow(hWnd);
}
}

两者结合

关闭新进程,旧进程窗口获取焦点

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
[DllImportAttribute("User32.dll")]
private static extern int FindWindow(String ClassName, String WindowName);

[DllImport("user32.dll")]
public static extern bool SetForegroundWindow(int hWnd);

private void checkProcess()
{
Console.WriteLine("程序启动");
Process current = Process.GetCurrentProcess();
//获取欲启动进程名
string strProcessName = Process.GetCurrentProcess().ProcessName;
var processList = Process.GetProcessesByName(strProcessName);
if (processList.Length > 1)
{
MessageBox.Show("当前程序已在运行,请勿重复运行。");
foreach (var process in processList)
{
if (process.Id == current.Id) continue;
int hWnd = FindWindow(null, process.MainWindowTitle.ToString());
SetForegroundWindow(hWnd);
}
Environment.Exit(1);//退出程序
return;
}
}