防止.NET應(yīng)用多實(shí)例運(yùn)行的有效方法
核心思路
1、檢查是否已有程序?qū)嵗\(yùn)行
使用 System.Diagnostics.Process 獲取當(dāng)前程序進(jìn)程,并與系統(tǒng)中所有同名的程序進(jìn)程進(jìn)行比較。如果發(fā)現(xiàn)另一個(gè)同名進(jìn)程,則認(rèn)為程序已經(jīng)運(yùn)行。
2、激活已運(yùn)行的程序窗口
如果發(fā)現(xiàn)已有實(shí)例運(yùn)行,使用 Win32 API 操作將其窗口置于前臺(tái),避免用戶(hù)啟動(dòng)多個(gè)實(shí)例。
3、運(yùn)行主程序邏輯
如果沒(méi)有其他實(shí)例運(yùn)行,正常啟動(dòng)主程序。
代碼解析
1、檢查是否已有程序運(yùn)行
以下代碼通過(guò)進(jìn)程名稱(chēng)篩選當(dāng)前運(yùn)行的程序進(jìn)程列表,返回除當(dāng)前進(jìn)程外的其他同名進(jìn)程(如果存在):
public static Process GetExistProcess()
{
Process currentProcess = Process.GetCurrentProcess(); // 當(dāng)前程序
foreach (Process process in Process.GetProcessesByName(currentProcess.ProcessName))
{
if (process.Id != currentProcess.Id) // 找到其他同名進(jìn)程
{
return process; // 返回已運(yùn)行的進(jìn)程
}
}
return null; // 沒(méi)有其他實(shí)例
}
2、主程序入口
在 Main 方法中調(diào)用 GetExistProcess 檢查程序?qū)嵗?/p>
static class Program
{
[STAThread]
static void Main()
{
Application.EnableVisualStyles();
Application.SetCompatibleTextRenderingDefault(false);
var runningProcess = GetExistProcess();
if (runningProcess != null) // 如果有實(shí)例運(yùn)行
{
IntPtr mainWindowHandle = runningProcess.MainWindowHandle;
if (mainWindowHandle == IntPtr.Zero) // 窗口被隱藏
{
mainWindowHandle = FindWindow(null, "唯一程序");
}
ShowWindowAsync(mainWindowHandle, 1); // 顯示窗口
SetForegroundWindow(mainWindowHandle); // 置于前臺(tái)
}
else
{
Application.Run(new MainForm()); // 啟動(dòng)新實(shí)例
}
}
}
3、Win32 API 調(diào)用
以下是關(guān)鍵的 Win32 API 函數(shù),用于操作窗口顯示和前臺(tái)設(shè)置:
[DllImport("User32.dll", EntryPoint = "FindWindow")]
public static extern IntPtr FindWindow(string lpClassName, string lpWindowName);
[DllImport("user32.dll")]
public static extern bool ShowWindowAsync(IntPtr hWnd, int nCmdShow);
[DllImport("user32.dll ")]
public static extern bool SetForegroundWindow(IntPtr hWnd);
FindWindow: 根據(jù)窗口名稱(chēng)查找窗口句柄。
ShowWindowAsync: 顯示或隱藏窗口。
SetForegroundWindow: 將窗口設(shè)置為前臺(tái)窗口。
注意事項(xiàng)
1、窗口名稱(chēng)匹配問(wèn)題
如果窗口標(biāo)題動(dòng)態(tài)變化,FindWindow 的效果可能不佳,需保證窗口標(biāo)題唯一或改用其他識(shí)別方法。 2、權(quán)限問(wèn)題
如果以管理員權(quán)限運(yùn)行程序,SetForegroundWindow 操作可能會(huì)被限制。需要確保權(quán)限一致。
3、多線(xiàn)程問(wèn)題
如果程序使用了多線(xiàn)程,需注意線(xiàn)程間的窗口操作同步。
優(yōu)化建議
1、使用互斥量
利用 Mutex 可以更簡(jiǎn)潔地實(shí)現(xiàn)程序唯一性。例如:
static Mutex mutex = new Mutex(true, "UniqueAppName", out bool createdNew);
if (!createdNew)
{
// 已經(jīng)有實(shí)例運(yùn)行
return;
}
2、窗口句柄緩存
可以在程序啟動(dòng)時(shí)緩存主窗口句柄,避免頻繁調(diào)用 FindWindow。
3、日志記錄
在實(shí)際應(yīng)用中建議記錄重復(fù)啟動(dòng)的嘗試,以便后續(xù)調(diào)試和優(yōu)化。
總結(jié)
這是一種基于進(jìn)程和 Win32 API 的方法來(lái)保持程序唯一性的解決方案。代碼邏輯清晰,適用于大多數(shù)桌面應(yīng)用場(chǎng)景。如果你有更復(fù)雜的需求或更高的性能要求,建議結(jié)合互斥量或現(xiàn)代框架特性來(lái)實(shí)現(xiàn)更可靠的方案。
最后
到此這篇關(guān)于防止.NET應(yīng)用多實(shí)例運(yùn)行的有效方法的文章就介紹到這了,更多相關(guān)防止.NET多實(shí)例運(yùn)行內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
使用Fiddler調(diào)試visual studion多個(gè)虛擬站點(diǎn)的問(wèn)題分析
本篇文章小編為大家介紹,使用Fiddler調(diào)試visual studion多個(gè)虛擬站點(diǎn)的問(wèn)題分析。需要的朋友參考下2013-04-04
Web系統(tǒng)通過(guò)EXE文件實(shí)現(xiàn)讀取客戶(hù)電腦MAC等硬件信息且兼容非IE瀏覽器
我們?cè)趯?shí)際Web應(yīng)用中,可能會(huì)遇到“需要限定特定的電腦或用戶(hù)才能使用系統(tǒng)”的問(wèn)題。2014-08-08
MVC+EasyUI+三層架構(gòu)簡(jiǎn)單權(quán)限管理系統(tǒng)
這篇文章主要為大家詳細(xì)介紹了MVC+EasyUI+三層架構(gòu)簡(jiǎn)單權(quán)限管理系統(tǒng),文中示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2016-07-07
Repeater的FooterTemplate顯示某列總計(jì)思路與代碼
在Repeater的FooterTemplate顯示某列總計(jì),接下來(lái)與大家分享詳細(xì)的實(shí)現(xiàn)方案,感興趣的各位可以參考下哈2013-03-03
推薦8項(xiàng)提高 ASP.NET Web API 性能的技術(shù)
ASP.NET Web API 是非常棒的技術(shù)。編寫(xiě) Web API 十分容易,以致于很多開(kāi)發(fā)者沒(méi)有在應(yīng)用程序結(jié)構(gòu)設(shè)計(jì)上花時(shí)間來(lái)獲得很好的執(zhí)行性能。2014-08-08
Repeater事件OnItemCommand取得行內(nèi)控件的方法
這篇文章主要介紹了Repeater事件OnItemCommand取得行內(nèi)控件的方法,有需要的朋友可以參考一下2014-01-01
asp.net URL重寫(xiě)簡(jiǎn)化版 速學(xué)URL重寫(xiě)
asp.net URL重寫(xiě)(URLRewriter)簡(jiǎn)化版 。速學(xué)URL重寫(xiě)2010-01-01

