在開發(fā) WinForms 應用程序時,有時需要防止同一個應用程序的多個實例同時運行。這種需求在某些情況下非常重要,例如,當你需要確保某個資源(如文件或數據庫)只被一個應用實例訪問時。
本文將介紹幾種防止同一應用運行多個實例的方法,提供詳細的代碼示例,并輸出為 Markdown 格式。
方法一:使用 Mutex
類
Mutex
(互斥量)是一個同步基元,它可以用于跨線程和進程同步。通過創(chuàng)建一個命名互斥量,可以防止應用運行多個實例。
示例代碼
namespace SingleInstanceApp
{
internal static class Program
{
private static Mutex mutex = null;
/// <summary>
/// The main entry point for the application.
/// </summary>
[STAThread]
static void Main()
{
const string mutexName = "MyApp";
bool isOwned;
mutex = new Mutex(true, mutexName, out isOwned);
if (!isOwned)
{
MessageBox.Show("應用程序已經在運行中。", "多實例檢測", MessageBoxButtons.OK, MessageBoxIcon.Exclamation);
return;
}
// To customize application configuration such as set high DPI settings or default font,
// see https://aka.ms/applicationconfiguration.
ApplicationConfiguration.Initialize();
Application.Run(new Form1());
GC.KeepAlive(mutex);
}
}
}
在上述代碼中,我們使用 Mutex
類創(chuàng)建了一個系統(tǒng)全局命名的互斥體 mutexName
。如果應用程序已經在運行,則 isOwned
將為 false
,應用會顯示一條消息并退出。
方法二:使用 Process
類
通過 Process
類檢查當前是否已經有同名進程在運行,也可以防止多個實例的運行。
示例代碼
using System.Diagnostics;
namespace SingleInstanceApp
{
internal static class Program
{
/// <summary>
/// The main entry point for the application.
/// </summary>
[STAThread]
static void Main()
{
if (IsAlreadyRunning())
{
MessageBox.Show("應用程序已經在運行中。", "多實例檢測", MessageBoxButtons.OK, MessageBoxIcon.Exclamation);
return;
}
// To customize application configuration such as set high DPI settings or default font,
// see https://aka.ms/applicationconfiguration.
ApplicationConfiguration.Initialize();
Application.Run(new Form1());
}
static bool IsAlreadyRunning()
{
string currentProcessName = Process.GetCurrentProcess().ProcessName;
Process[] processes = Process.GetProcessesByName(currentProcessName);
return processes.Length > 1;
}
}
}
此方法通過 Process.GetProcessesByName
方法獲取當前運行的同名進程。如果長度大于1,說明此時已有另一個實例在運行。
方法三:使用 Windows API
還有一種方法是利用 Windows API 創(chuàng)建一個命名事件,檢查該事件是否已經存在。
示例代碼
using System.Diagnostics;
using System.Runtime.InteropServices;
namespace SingleInstanceApp
{
internal static class Program
{
const string UniqueEventName = "Global\\MyApp";
[DllImport("kernel32", SetLastError = true)]
static extern IntPtr CreateEvent(IntPtr lpEventAttributes, bool bManualReset, bool bInitialState, string lpName);
[DllImport("kernel32.dll")]
static extern uint GetLastError();
/// <summary>
/// The main entry point for the application.
/// </summary>
[STAThread]
static void Main()
{
IntPtr handle = CreateEvent(IntPtr.Zero, false, false, UniqueEventName);
if (handle == IntPtr.Zero || GetLastError() == 183) // ERROR_ALREADY_EXISTS (183)
{
MessageBox.Show("應用程序已經在運行中。", "多實例檢測", MessageBoxButtons.OK, MessageBoxIcon.Exclamation);
return;
}
// To customize application configuration such as set high DPI settings or default font,
// see https://aka.ms/applicationconfiguration.
ApplicationConfiguration.Initialize();
Application.Run(new Form1());
}
}
}
上述代碼使用了 CreateEvent
API 創(chuàng)建一個命名事件,并通過 GetLastError
檢查事件是否已經存在(錯誤代碼 183 表示該事件已存在)。
CreateEvent
是一個 Windows API 函數,用于創(chuàng)建或打開一個命名的或未命名的事件對象。事件對象在進程間和線程間同步中非常有用。
GetLastError()
函數是用于檢索擴展的錯誤信息的函數。它通常與其他 Windows API 函數一起使用,這些函數不返回明確的錯誤代碼,但是如果調用失敗,可以通過 GetLastError()
獲取詳細的錯誤信息。
總結
以上介紹了三種在 WinForms 開發(fā)中防止同一應用運行多個實例的方法:
使用 Mutex
類。
使用 Process
類。
使用 Windows API。
每種方法都有其優(yōu)點和適用場景,開發(fā)者可根據具體需求選擇合適的方法來實現多實例檢測功能。希望此文對你有所幫助,歡迎提出任何問題或建議。
該文章在 2024/7/23 22:28:12 編輯過