如何实现仅启动一个 WPF 进程实例,并在打开第二个时,自动唤起之前打开的进程。

1 代码入口

App.xaml.cs 文件中,重写 OnStartup 方法,并添加 Mutex 进程锁。

/// <summary>
/// 只打开一个进程
/// </summary>
/// <param name="e"></param>
protected override void OnStartup(StartupEventArgs e)
{
string mutexName = "32283F61-EC4D-43B1-9C44-40280D5854DD"; ProgramStarted = new EventWaitHandle(false, EventResetMode.AutoReset, mutexName, out var createNew); if (!createNew)
{
// 唤起已经启动的进程 App.Current.Shutdown();
Environment.Exit(-1);
}
else
{
// 正常启动
base.OnStartup(e);
}
}

2 唤起已经启动的进程

try
{
var processes = Process.GetProcessesByName("进程名");
if (!processes.Any())
{
// 没有找到进程名,可能是启动文件被改名了,但还是启动了的。
MessageBox.Show("已经启动了XXX", "错误提示", MessageBoxButton.OK, MessageBoxImage.Error);
}
else
{
// 其实这里应该只有一个
foreach (Process process in processes)
{
ShowWindowAsync(process.MainWindowHandle, SW_SHOWNOMAL);
SetForegroundWindow(process.MainWindowHandle);
SwitchToThisWindow(process.MainWindowHandle, true);
}
}
}
catch (Exception exception)
{
// Logger.Error(exception, "唤起已启动进程时出错");
}

Win32 函数引入:

private const int SW_SHOWNOMAL = 1;

///<summary>
/// 该函数设置由不同线程产生的窗口的显示状态
/// </summary>
/// <param name="hWnd">窗口句柄</param>
/// <param name="cmdShow">指定窗口如何显示。查看允许值列表,请查阅ShowWindow函数的说明部分</param>
/// <returns>如果函数原来可见,返回值为非零;如果函数原来被隐藏,返回值为零</returns>
[DllImport("User32.dll")]
private static extern bool ShowWindowAsync(IntPtr hWnd, int cmdShow); /// <summary>
/// 该函数将创建指定窗口的线程设置到前台,并且激活该窗口。键盘输入转向该窗口,并为用户改各种可视的记号。
/// 系统给创建前台窗口的线程分配的权限稍高于其他线程。
/// </summary>
/// <param name="hWnd">将被激活并被调入前台的窗口句柄</param>
/// <returns>如果窗口设入了前台,返回值为非零;如果窗口未被设入前台,返回值为零</returns>
[DllImport("User32.dll", EntryPoint = "SetForegroundWindow")]
private static extern bool SetForegroundWindow(IntPtr hWnd); [DllImport("user32.dll")]
public static extern void SwitchToThisWindow(IntPtr hWnd, bool fAltTab);

3 完整代码

using System;
using System.Collections.Generic;
using System.Configuration;
using System.Data;
using System.Diagnostics;
using System.Linq;
using System.Runtime.InteropServices;
using System.Threading;
using System.Threading.Tasks;
using System.Windows; namespace Test
{
/// <summary>
/// Interaction logic for App.xaml
/// </summary>
public partial class App : Application
{
public EventWaitHandle ProgramStarted { get; set; } private const int SW_SHOWNOMAL = 1; ///<summary>
/// 该函数设置由不同线程产生的窗口的显示状态
/// </summary>
/// <param name="hWnd">窗口句柄</param>
/// <param name="cmdShow">指定窗口如何显示。查看允许值列表,请查阅ShowWindow函数的说明部分</param>
/// <returns>如果函数原来可见,返回值为非零;如果函数原来被隐藏,返回值为零</returns>
[DllImport("User32.dll")]
private static extern bool ShowWindowAsync(IntPtr hWnd, int cmdShow); /// <summary>
/// 该函数将创建指定窗口的线程设置到前台,并且激活该窗口。键盘输入转向该窗口,并为用户改各种可视的记号。
/// 系统给创建前台窗口的线程分配的权限稍高于其他线程。
/// </summary>
/// <param name="hWnd">将被激活并被调入前台的窗口句柄</param>
/// <returns>如果窗口设入了前台,返回值为非零;如果窗口未被设入前台,返回值为零</returns>
[DllImport("User32.dll", EntryPoint = "SetForegroundWindow")]
private static extern bool SetForegroundWindow(IntPtr hWnd); [DllImport("user32.dll")]
public static extern void SwitchToThisWindow(IntPtr hWnd, bool fAltTab); /// <summary>
/// 只打开一个进程
/// </summary>
/// <param name="e"></param>
protected override void OnStartup(StartupEventArgs e)
{
string mutexName = "32283F61-EC4D-43B1-9C44-40280D5854DD"; ProgramStarted = new EventWaitHandle(false, EventResetMode.AutoReset, mutexName, out var createNew); if (!createNew)
{
try
{
var processes = Process.GetProcessesByName("进程名");
if (!processes.Any())
{
MessageBox.Show("已经启动了XXX", "错误提示", MessageBoxButton.OK, MessageBoxImage.Error);
}
else
{
foreach (Process process in processes)
{
ShowWindowAsync(process.MainWindowHandle, SW_SHOWNOMAL);
SetForegroundWindow(process.MainWindowHandle);
SwitchToThisWindow(process.MainWindowHandle, true);
}
}
}
catch (Exception exception)
{
// Logger.Error(exception, "唤起已启动进程时出错");
} App.Current.Shutdown();
Environment.Exit(-1);
}
else
{
base.OnStartup(e);
}
} } }

4 参考链接


原文链接:

https://www.cnblogs.com/jasongrass/p/11761153.html

C#/WPF 仅启动一个进程实例的更多相关文章

  1. MFC 只启动一个程序实例

    问题描述: 我们开发过程中可能会经常遇到,只启动一个程序实例.即一个程序启动之后,如果再次执行该程序,将会恢复之前打开的程序,而不是打开一个新的程序. 实现原理:利用FindWindow/FindWi ...

  2. C#只启动一个进程的代码

    把写内容过程中经常用到的内容做个收藏,如下的内容是关于C#只启动一个进程的内容.public partial class App : Application { protected override ...

  3. 【.net 深呼吸】启动一个进程并实时获取状态信息

    地球人和火星人都知道,Process类既可以获取正在运行的进程,也可以启动一个新的进程.在79.77%应用场合,我们只需要让目标进程顺利启动就完事了,至于它执行了啥,有没有出错,啥时候退出就不管了. ...

  4. Eucalyptus-利用镜像启动一个Centos实例

    1.前言 使用kvm制作Eucalyptus镜像(Centos6.5为例)——http://www.cnblogs.com/gis-luq/p/3990795.html 上一篇我们讲述了如何利用kvm ...

  5. CentOS7安装OpenStack(Rocky版)-08.启动一个虚拟机实例

    安装完openstack的必要组件keystone,nova,glance,neutron以后就可以使用openstack命令创建一台云虚拟机了 ------------------- 完美的分割线 ...

  6. (转)linux用文件锁实现保证一个程序只能启动一个进程

    #include <stdio.h> #include <unistd.h>#include <fcntl.h>#include <errno.h>in ...

  7. Qt 进程和线程之一:运行一个进程和进程间通信

    Qt提供了对进程和线程的支持.本节讲述了怎样在Qt应用程序中启动一个进程,以及几种常用的进程间通信方法.如果对进程和线程的概念不是很了解,可以看我的另一篇博客:[多进程和多线程的概念. 设计应用程序时 ...

  8. Qt ------ QProcess,启动外部进程,进程间通信

    简介: 可用于完成启动外部程序,并与之交互通信. 启动一个进程的名字叫“program”,如果某进程的路径没有设置成环境变量,“program”需要包含路径 如果进程可以接收参数,参数叫“argume ...

  9. erlang supervisor中启动普通的进程

    文字部分转自: http://1234n.com/?post/qou3eb supervisor的子进程 一开始使用supervisor的时候,我用的是init/1返回子进程规格列表的方式,并且所有子 ...

随机推荐

  1. Ubuntu安装Node和npm

    本文简单介绍在Ubuntu上安装最新版本的node和npm. 本次试验环境是Ubuntu 18.10. 安装nodejs root@ubuntu:~# cat /etc/issue Ubuntu 18 ...

  2. jQuery-跨域问题的处理

    调用登录接口时,后端一般会在调用登录接口成功后,在response中设置cookie,之后前端的每次请求都会自动地在请求头上加上后端设置好的cookie,这对前端来说是透明的. 当登录接口与登录后调用 ...

  3. 分布式文件服务器FastDFS的使用

    分布式项目中涉及到的文件上传与下载,此时使用之前的上传方式,将上传的文件与当前项目所在服务器放在同一个位置,显然不符合分布式项目的理念,此时我们借助FastDFS将上传的文件数据存储到单纯的一个服务器 ...

  4. emojy表情的小问题

    报错内容:在emojy表情入库或者更新库的时候,会报这个错:java.sql.SQLException:Incorrect string value: '\xF0\x9F\x99\x8F\..' fo ...

  5. Git - Git基本常用命令

    Git基本常用命令 mkdir:         XX (创建一个空目录 XX指目录名) pwd:          显示当前目录的路径. git init          把当前的目录变成可以管理 ...

  6. Winform中自定义添加ZedGraph右键实现设置所有Y轴刻度的上下限

    场景 Winforn中实现ZedGraph自定义添加右键菜单项(附源码下载): https://blog.csdn.net/BADAO_LIUMANG_QIZHI/article/details/10 ...

  7. itextsharp操作pdf——插入图片、二维码等

    简单介绍 业务需求,需要往pdf图纸上添加二维码功能,将实现过程记录下来 下载类库 直接下载 添加引用 添加命名空间 using System.IO; using iTextSharp.text.pd ...

  8. 一则sql优化实现接口耗时降低30倍的优化案例

    业务场景: 也测的业务,如上图,通过捕获业务的涉及的接口如下: 查询接口耗时大于7s,已经是非常的慢 经验提示: 一般接口响应时间慢的问题,最简单的方式就是监控接口相关的sql是否存在问题 开启mys ...

  9. 矩阵的运算:Python语言实现

    一.矩阵的加减法 import numpy as np #这里是矩阵的加法 ar1=np.arange(10).reshape(10,1) ar1 ar2=np.arange(10).reshape( ...

  10. 网络编程~~~osi五层协议

    物理层 / 数据链路层 / 网络层 / 传输层 / 应用层(表示层/会话层) 一 物理层 物理层指的就是网线,光纤, 双绞线等物理传输介质 物理层发送的是数据(比特流) 二 数据链路层 数据链路层对数 ...