如何在SplashScreen显示前执行代码完成单实例检测?
问题根源
项目文件中通过<SplashScreen Include="Images\SplashScreen.png" />配置的启动屏由WPF构建系统自动处理:构建阶段会把启动屏显示逻辑直接注入到自动生成的应用入口(Main方法)最前端,执行优先级高于App类构造函数、OnStartup重写方法等所有你写在App生命周期内的自定义逻辑,因此把Mutex校验放在App类中永远会晚于启动屏显示。
解决方案
核心思路是放弃自动注入的启动屏逻辑,手动接管应用入口,先执行单实例校验,再按需控制启动屏显示,步骤如下:
- 第一步:移除项目文件中原有的SplashScreen配置项,即删除
<SplashScreen Include="Images\SplashScreen.png" />这行配置,避免构建系统自动注入提前显示启动屏的逻辑。 - 第二步:找到项目里的
SplashScreen.png资源文件,将它的生成操作从SplashScreen修改为Resource。 - 第三步:自定义应用入口方法,先执行Mutex单实例校验,校验通过后再手动显示启动屏、初始化应用运行。参考代码如下:
using System; using System.Threading; using System.Windows; public static class Program { [STAThread] public static void Main() { // 单实例校验逻辑放在最前端,此时未加载任何WPF界面逻辑,不会弹出启动屏 bool isFirstInstance; using (var appMutex = new Mutex(initiallyOwned: true, "替换为你的应用全局唯一标识名", out isFirstInstance)) { if (!isFirstInstance) { // 检测到已存在运行实例,直接退出进程,不会显示任何界面 // 如需唤醒已运行的实例窗口,可在此处添加查找主窗口、置顶激活的逻辑 return; } // 单实例校验通过后,再手动创建并显示启动屏 var splashScreen = new SplashScreen("Images/SplashScreen.png"); splashScreen.Show(autoClose: true, topMost: true); // 正常初始化应用、启动主流程 var app = new App(); app.InitializeComponent(); app.Run(); } } }
注意:自定义入口后,需要把项目的启动对象设置为你定义的
Program类,否则还是会走WPF默认的自动生成入口逻辑。
内容的提问来源于stack exchange,提问作者James Screech
相关产品推荐
相关产品推荐

