工作上經常會遇到"程式只能啟動一個例項"這樣的需求. 我想,這樣的需求應該很普遍,所以沒打算去動腦筋,去找谷歌問下就得了,用下來發現,不是這裡不爽就是那裡不行.
先說下我詳細的幾點需求(假設程式名為"A.exe")
1.程式只能同時開啟一個例項.
2.在A.exe已經啟動的情況下,雙擊A.exe,則把已經啟動的A.exe啟用,並呈現到最前.
3.複製A.exe,命名為B.exe,在A.exe已經啟動的情況下,雙擊B.exe,則把A.exe啟用,並呈現到最前.
好,現在就來看看網路上的解決方案
1.互斥法
bool createdNew; Mutex instance
= new Mutex(true,"互斥名(保證在本機中唯一)", out
createdNew);
if
(createdNew)
{
Application.EnableVisualStyles();
Application.SetCompatibleTextRenderingDefault(false);
Application.Run(new FormMain());
instance.ReleaseMutex();
}
else
{
MessageBox.Show("已經啟動了一個程式,請先退出!", "系統提示", MessageBoxButtons.OK,
MessageBoxIcon.Error);
Application.Exit();
}
評價:
個人認為這種方法非常的好,能做出判斷的準確,即使啟動複製的執行檔案,依然可以提示"已經啟動一個程式,請先退出!".這樣,它滿足了上述需要中的第一條和第三條的前半部分.但是有一個不足:無法啟用已經啟動的程式(至少我不知道怎麼實現 ,如果有誰知道用互斥可以實現以上三個要求,請留言告訴我,不勝感激!)
2.Process法
新增如下函式:
public static Process RunningInstance()
{
Process current = Process.GetCurrentProcess();
Process[] processes = Process.GetProcessesByName(current.ProcessName);
//Loop through the running processes in with the same name
foreach (Process process in processes)
{
//Ignore the current process
if (process.Id != current.Id)
{
//Make sure that the process is running from the exe file.
if (Assembly.GetExecutingAssembly().Location.Replace("/", "\") == current.MainModule.FileName)
{
//Return the other process instance.
return process;
}
}
}
//No other instance was found, return null.
return null;
}
修改系統Main函式,大致如下:
if( RunningInstance() == null )
Application.Run(new yourFormName());
評價:速度比較慢,其次通過ProcessName去系統中查尋,有可能查出來的Process並不是我想要得,不過,稍做修改,便可以很實現需求的第二條(讓程式只執行一次,如果程式已經執行,把它彈出並顯示到最前面).但是它同樣有一個很嚴重的問題,也就無法滿足需求中的第三條,做一個複製,然後修改名字(程式名即為程式名),便可以啟動多個例項.
3.VB法(個人推薦的方法,談不上原創,但是網路上很少見)
不解釋,直接看程式碼
using
Microsoft.VisualBasic.ApplicationServices;
static void Main(string[] args)
{
App myApp = new App();
myApp.Run(args);
}
class App : WindowsFormsApplicationBase
{
public App()
{
// 設定單例模式
this.IsSingleInstance = true;
// 設定可用於XP視窗樣式
this.EnableVisualStyles = true;
// 視窗關閉時的操作
this.ShutdownStyle = ShutdownMode.AfterMainFormCloses;
}
/// <summary>
/// 重寫OnCreateMainForm()函式
/// </summary>
protected override void OnCreateMainForm()
{
this.MainForm = new FormMain();
}
}
}
怎麼樣,也不是很複雜,程式碼量很少,輕鬆實現所有需求.當然,有些朋友還可能還有這樣的需求
程式第二次啟動的時候,除了把程式啟用前置,還要往程式裡傳遞引數,並做處理.沒有問題,這樣也可以做到,但是可能稍微複雜一點,在VB法的基礎上再做點修改就OK啦