防止.NET應(yīng)用多實例運(yùn)行的有效方法
核心思路
1、檢查是否已有程序?qū)嵗\(yùn)行
使用 System.Diagnostics.Process
獲取當(dāng)前程序進(jìn)程,并與系統(tǒng)中所有同名的程序進(jìn)程進(jìn)行比較。如果發(fā)現(xiàn)另一個同名進(jìn)程,則認(rèn)為程序已經(jīng)運(yùn)行。
2、激活已運(yùn)行的程序窗口
如果發(fā)現(xiàn)已有實例運(yùn)行,使用 Win32 API
操作將其窗口置于前臺,避免用戶啟動多個實例。
3、運(yùn)行主程序邏輯
如果沒有其他實例運(yùn)行,正常啟動主程序。
代碼解析
1、檢查是否已有程序運(yùn)行
以下代碼通過進(jìn)程名稱篩選當(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; // 沒有其他實例 }
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) // 如果有實例運(yùn)行 { IntPtr mainWindowHandle = runningProcess.MainWindowHandle; if (mainWindowHandle == IntPtr.Zero) // 窗口被隱藏 { mainWindowHandle = FindWindow(null, "唯一程序"); } ShowWindowAsync(mainWindowHandle, 1); // 顯示窗口 SetForegroundWindow(mainWindowHandle); // 置于前臺 } else { Application.Run(new MainForm()); // 啟動新實例 } } }
3、Win32 API 調(diào)用
以下是關(guān)鍵的 Win32 API
函數(shù),用于操作窗口顯示和前臺設(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ù)窗口名稱查找窗口句柄。
ShowWindowAsync
: 顯示或隱藏窗口。
SetForegroundWindow
: 將窗口設(shè)置為前臺窗口。
注意事項
1、窗口名稱匹配問題
如果窗口標(biāo)題動態(tài)變化,FindWindow
的效果可能不佳,需保證窗口標(biāo)題唯一或改用其他識別方法。 2、權(quán)限問題
如果以管理員權(quán)限運(yùn)行程序,SetForegroundWindow
操作可能會被限制。需要確保權(quán)限一致。
3、多線程問題
如果程序使用了多線程,需注意線程間的窗口操作同步。
優(yōu)化建議
1、使用互斥量
利用 Mutex
可以更簡潔地實現(xiàn)程序唯一性。例如:
static Mutex mutex = new Mutex(true, "UniqueAppName", out bool createdNew); if (!createdNew) { // 已經(jīng)有實例運(yùn)行 return; }
2、窗口句柄緩存
可以在程序啟動時緩存主窗口句柄,避免頻繁調(diào)用 FindWindow
。
3、日志記錄
在實際應(yīng)用中建議記錄重復(fù)啟動的嘗試,以便后續(xù)調(diào)試和優(yōu)化。
總結(jié)
這是一種基于進(jìn)程和 Win32 API 的方法來保持程序唯一性的解決方案。代碼邏輯清晰,適用于大多數(shù)桌面應(yīng)用場景。如果你有更復(fù)雜的需求或更高的性能要求,建議結(jié)合互斥量或現(xiàn)代框架特性來實現(xiàn)更可靠的方案。
最后
到此這篇關(guān)于防止.NET應(yīng)用多實例運(yùn)行的有效方法的文章就介紹到這了,更多相關(guān)防止.NET多實例運(yùn)行內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
詳解ASP.NET Core3.0 配置的Options模式
這篇文章主要介紹了詳解ASP.NET Core3.0 配置的Options模式,文中通過示例代碼介紹的非常詳細(xì),對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧2020-08-08Asp.Net Core利用xUnit進(jìn)行主機(jī)級別的網(wǎng)絡(luò)集成測試詳解
這篇文章主要給大家介紹了關(guān)于Asp.Net Core利用xUnit進(jìn)行主機(jī)級別的網(wǎng)絡(luò)集成測試的相關(guān)資料,文中通過示例代碼介紹的非常詳細(xì),對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價值,需要的朋友們來一起看看吧2018-12-12利用ASP.NET MVC+Bootstrap搭建個人博客之打造清新分頁Helper(三)
這篇文章主要介紹了利用ASP.NET MVC+Bootstrap搭建個人博客之打造清新分頁Helper(三)的相關(guān)資料,非常不錯,具有參考借鑒價值,需要的朋友可以參考下2016-06-06排除JQuery通過HttpGet調(diào)用WebService返回Json時“parserror”錯誤
排除JQuery通過HttpGet調(diào)用WebService返回Json時“parserror”錯誤的解決方法。2011-10-10SqlDataSource 鏈接Access 數(shù)據(jù)
如何用AccessDataSource鏈接有密碼的access數(shù)據(jù)庫總是會報錯,替代方法是用SqlDataSource 鏈接Access 數(shù)據(jù)。2009-04-04ASP.NET下母版頁和內(nèi)容頁中的事件發(fā)生順序整理
母版頁與內(nèi)容頁合并后事件的發(fā)生順序,有需要區(qū)別的朋友能用的到2009-03-03