C#開發單例項應用程式並響應後續程序啟動引數

【一路向东】發表於2024-07-07

C#預設的WinForm模板是不支援設定單例項的,也沒有隔壁大哥VB.NET那樣有個“生成單個例項應用程式”的勾選選項(VB某些時候要比C#更方便),實現單例項可以有多種方法:

  • 檢測同名程序:Process.GetProcessesByName(Process.GetCurrentProcess().ProcessName),如果集合的Length > 1那就表明已有同名程序了,如果有需要還可以進一步檢查該程序的路徑;
  • 命名互斥鎖:Mutex,網上介紹的很多都是這種方法;
  • 鎖定檔案:使用File.Create方法建立檔案並在程式退出時釋放,如果建立失敗則表明已經有例項在執行;
  • VB.NET方法:WindowsFormsApplicationBase,個人認為該方法最完美,可以接收後續程序的啟動引數,還可以彈出前序程序的主窗體。

WindowsFormsApplicationBase是一個Microsoft.VisualBasic.ApplicationServices名稱空間下的類,是微軟為VB.NET實現應用程式啟動控制的類,其內部是以命名管道通訊來實現的。既然是同一個爹的東西,C#拿過來用毫無違和感。Microsoft.VisualBasic和Microsoft.CSharp一樣,都是.NET Framework中的一部分,不用擔心會缺少執行環境。

WindowsFormsApplicationBase類的一些常用屬性和方法:

  • 屬性IsSingleInstance:設定當前程序是否為單例項程序,在構造方法中設定,如果是後續程序且為值true,構造方法結束後會給前序程序傳送啟動引數,然後就退出程序了,不會執行到下面的OnStartup;
  • 方法OnStartup:首次啟動後執行,返回false就會退出程序,後續程序永遠不會執行到該方法;
  • 方法OnStartupNextInstance:後續程序啟動後的重寫方法,前序程序會接收到後續程序的啟動引數,彈出主窗體等;
  • 方法OnCreateMainForm:建立主窗體的重寫方法,必須指定主窗體。

建立一個單例項應用程式並響應後續程序引數的大概過程:

  • 建立一個專案名稱為“SingleInstanceSample”的Windows窗體專案;
  • 新增引用“Microsoft.VisualBasic”;
  • 重新命名“Form1”為“MainForm”;
  • 新增類“ApplicationBase.cs”,繼承自“WindowsFormsApplicationBase”;
  • 修改“Program.cs”,從“ApplicationBase”啟動。

各個類的程式碼如下:

  • Program.cs
 1 using System;
 2 using System.Windows.Forms;
 3 
 4 namespace SingleInstanceSample
 5 {
 6     internal static class Program
 7     {
 8         [STAThread]
 9         static void Main(string[] args)
10         {
11             Application.EnableVisualStyles();
12             Application.SetCompatibleTextRenderingDefault(false);
13 
14             var app = new ApplicationBase();
15             app.Run(args);
16         }
17     }
18 }
  • ApplicationBase.cs
 1 using Microsoft.VisualBasic.ApplicationServices;
 2 using System.IO;
 3 
 4 namespace SingleInstanceSample
 5 {
 6     internal class ApplicationBase : WindowsFormsApplicationBase
 7     {
 8         public ApplicationBase() : base(AuthenticationMode.Windows)
 9         {
10             //指示程序為單程序:IsSingleInstance
11             base.IsSingleInstance = true;
12             base.SaveMySettingsOnExit = true;
13             base.ShutdownStyle = ShutdownMode.AfterMainFormCloses;
14         }
15 
16         /// <summary>
17         /// 首次啟動後的重寫方法,返回false就會退出程序,
18         /// 比如可以顯示登入窗體,登入失敗返回false就不會執行到OnCreateMainForm
19         /// </summary>
20         protected override bool OnStartup(StartupEventArgs eventArgs)
21         {
22              base.OnStartup(eventArgs);
23 
24             //處理當前程序的啟動引數
25 
26             return true;
27         }
28 
29         /// <summary>
30         /// 後續程序啟動後的重寫方法
31         /// </summary>
32         protected override void OnStartupNextInstance(StartupNextInstanceEventArgs eventArgs)
33         {
34             base.OnStartupNextInstance(eventArgs);
35 
36             //處理後續程序的啟動引數
37         }
38 
39         /// <summary>
40         /// 指定主窗體,
41         /// 除非OnStartup返回false,否則必須指定主窗體
42         /// </summary>
43         protected override void OnCreateMainForm()
44         {
45             base.MainForm = new MainForm();
46         }
47     }
48 }

相關文章