WinForm防止程序重復(fù)運(yùn)行的方法分析
本文實(shí)例講述了WinForm防止程序重復(fù)運(yùn)行的方法。分享給大家供大家參考,具體如下:
需求:
1、點(diǎn)擊“關(guān)閉”按鈕時(shí),程序最小化到托盤,并沒有退出,這時(shí)再次運(yùn)行程序,不會(huì)重復(fù)運(yùn)行,而是顯示已運(yùn)行的程序;
2、支持不同目錄;
3、支持修改名稱。
代碼(不支持修改名稱,不支持不同目錄):
using System; using System.Collections.Generic; using System.IO; using System.Linq; using System.Text; using System.Windows.Forms; using Tool; using System.Diagnostics; using System.Reflection; using System.Runtime.InteropServices; namespace 計(jì)算器 { static class Program { [DllImport("user32.dll")] public static extern IntPtr FindWindow(string lpClassName, string lpWindowName); /// <summary> /// 該函數(shù)設(shè)置由不同線程產(chǎn)生的窗口的顯示狀態(tài)。 /// </summary> /// <param name="hWnd">窗口句柄</param> /// <param name="cmdShow">指定窗口如何顯示。查看允許值列表,請(qǐng)查閱ShowWlndow函數(shù)的說明部分。</param> /// <returns>如果函數(shù)原來可見,返回值為非零;如果函數(shù)原來被隱藏,返回值為零。</returns> [DllImport("User32.dll")] private static extern bool ShowWindow(IntPtr hWnd, int cmdShow); /// <summary> /// 該函數(shù)將創(chuàng)建指定窗口的線程設(shè)置到前臺(tái),并且激活該窗口。鍵盤輸入轉(zhuǎn)向該窗口,并為用戶改各種可視的記號(hào)。系統(tǒng)給創(chuàng)建前臺(tái)窗口的線程分配的權(quán)限稍高于其他線程。 /// </summary> /// <param name="hWnd">將被激活并被調(diào)入前臺(tái)的窗口句柄。</param> /// <returns>如果窗口設(shè)入了前臺(tái),返回值為非零;如果窗口未被設(shè)入前臺(tái),返回值為零。</returns> [DllImport("User32.dll")] private static extern bool SetForegroundWindow(IntPtr hWnd); private const int SW_SHOWNORMAL = 1; /// <summary> /// 應(yīng)用程序的主入口點(diǎn)。 /// </summary> [STAThread] static void Main() { Application.EnableVisualStyles(); Application.SetCompatibleTextRenderingDefault(false); Process processes = RunningInstance(); if (processes == null) { Application.Run(new Form1()); } else { HandleRunningInstance(processes); } } /// <summary> /// 獲取正在運(yùn)行的實(shí)例,沒有運(yùn)行的實(shí)例返回null; /// </summary> public static Process RunningInstance() { Process current = Process.GetCurrentProcess(); Process[] processes = Process.GetProcessesByName(current.ProcessName); foreach (Process process in processes) { if (process.Id != current.Id) { if (Assembly.GetExecutingAssembly().Location.Replace("/", "\\") == current.MainModule.FileName) { return process; } } } return null; } /// <summary> /// 顯示已運(yùn)行的程序。 /// </summary> public static void HandleRunningInstance(Process instance) { try { IntPtr formHwnd = FindWindow(null, "計(jì)算器"); ShowWindow(formHwnd, SW_SHOWNORMAL); //顯示 SetForegroundWindow(formHwnd); //放到前端 } catch (Exception ex) { MessageBox.Show(ex.Message); } } } }
代碼(支持修改名稱,支持不同目錄):
using System; using System.Collections.Generic; using System.IO; using System.Linq; using System.Text; using System.Windows.Forms; using Tool; using System.Diagnostics; using System.Reflection; using System.Runtime.InteropServices; namespace 計(jì)算器 { static class Program { [DllImport("user32.dll")] public static extern IntPtr FindWindow(string lpClassName, string lpWindowName); /// <summary> /// 該函數(shù)設(shè)置由不同線程產(chǎn)生的窗口的顯示狀態(tài)。 /// </summary> /// <param name="hWnd">窗口句柄</param> /// <param name="cmdShow">指定窗口如何顯示。查看允許值列表,請(qǐng)查閱ShowWlndow函數(shù)的說明部分。</param> /// <returns>如果函數(shù)原來可見,返回值為非零;如果函數(shù)原來被隱藏,返回值為零。</returns> [DllImport("User32.dll")] private static extern bool ShowWindow(IntPtr hWnd, int cmdShow); /// <summary> /// 該函數(shù)將創(chuàng)建指定窗口的線程設(shè)置到前臺(tái),并且激活該窗口。鍵盤輸入轉(zhuǎn)向該窗口,并為用戶改各種可視的記號(hào)。系統(tǒng)給創(chuàng)建前臺(tái)窗口的線程分配的權(quán)限稍高于其他線程。 /// </summary> /// <param name="hWnd">將被激活并被調(diào)入前臺(tái)的窗口句柄。</param> /// <returns>如果窗口設(shè)入了前臺(tái),返回值為非零;如果窗口未被設(shè)入前臺(tái),返回值為零。</returns> [DllImport("User32.dll")] private static extern bool SetForegroundWindow(IntPtr hWnd); private const int SW_SHOWNORMAL = 1; /// <summary> /// 應(yīng)用程序的主入口點(diǎn)。 /// </summary> [STAThread] static void Main() { Common.AutoRegister(); Application.EnableVisualStyles(); Application.SetCompatibleTextRenderingDefault(false); bool createNew; using (System.Threading.Mutex m = new System.Threading.Mutex(true, Application.ProductName, out createNew)) { if (createNew) { FileOperator.SetValue("ProcessId", Process.GetCurrentProcess().Id.ToString()); //進(jìn)程ID寫入文件 Application.Run(new Form1()); } else { try { string strProcessId = FileOperator.GetValue("ProcessId"); //從文件中獲取進(jìn)程ID int processId = Convert.ToInt32(strProcessId); Process process = Process.GetProcessById(processId); HandleRunningInstance(process); } catch { FileOperator.SetValue("ProcessId", Process.GetCurrentProcess().Id.ToString()); //進(jìn)程ID寫入文件 Application.Run(new Form1()); } } } } /// <summary> /// 顯示已運(yùn)行的程序。 /// </summary> public static void HandleRunningInstance(Process instance) { try { IntPtr formHwnd = FindWindow(null, "計(jì)算器"); ShowWindow(formHwnd, SW_SHOWNORMAL); //顯示 SetForegroundWindow(formHwnd); //放到前端 } catch (Exception ex) { MessageBox.Show(ex.Message); } } } }
其實(shí),IntPtr formHwnd = FindWindow(null, "計(jì)算器"); 這段代碼是有BUG的,比如你打開一個(gè)名為“計(jì)算器”的文件夾,那么FindWindow找到的其實(shí)是這個(gè)文件夾,而不是計(jì)算器程序。我們可以在主窗體第一次顯示的時(shí)候,記下窗口句柄,代碼如下:
private void Form1_Shown(object sender, EventArgs e) { FileOperator.SetValue("hwnd", Process.GetCurrentProcess().MainWindowHandle.ToString()); }
然后,顯示已運(yùn)行的程序時(shí),從文件中讀取之前記錄的窗口句柄,代碼如下:
/// <summary> /// 顯示已運(yùn)行的程序 /// </summary> public static void HandleRunningInstance(Process instance) { try { IntPtr hwnd = new IntPtr(Convert.ToInt32(FileOperator.GetValue("hwnd"))); ShowWindow(hwnd, SW_SHOWNORMAL); //顯示 SetForegroundWindow(hwnd); //放到前端 } catch (Exception ex) { MessageBox.Show(ex.Message); } }
綜上,再整理一下,就能得到完美的解決方案。
更多關(guān)于C#相關(guān)內(nèi)容感興趣的讀者可查看本站專題:《WinForm控件用法總結(jié)》、《C#窗體操作技巧匯總》、《C#數(shù)據(jù)結(jié)構(gòu)與算法教程》、《C#常見控件用法教程》、《C#面向?qū)ο蟪绦蛟O(shè)計(jì)入門教程》及《C#程序設(shè)計(jì)之線程使用技巧總結(jié)》
希望本文所述對(duì)大家C#程序設(shè)計(jì)有所幫助。
上一篇:C# for循環(huán)的經(jīng)典案例集錦
欄 目:C#教程
下一篇:淺談C#中的for循環(huán)與foreach循環(huán)
本文標(biāo)題:WinForm防止程序重復(fù)運(yùn)行的方法分析
本文地址:http://mengdiqiu.com.cn/a1/C_jiaocheng/5706.html
您可能感興趣的文章
- 01-10WinForm限制窗體不能移到屏幕外的方法
- 01-10WinForm繪制圓角的方法
- 01-10WinForm實(shí)現(xiàn)仿視頻播放器左下角滾動(dòng)新聞效果的方法
- 01-10C#實(shí)現(xiàn)Winform中打開網(wǎng)頁頁面的方法
- 01-10winform實(shí)現(xiàn)創(chuàng)建最前端窗體的方法
- 01-10WinForm實(shí)現(xiàn)自定義右下角提示效果的方法
- 01-10.net2.0+ Winform項(xiàng)目實(shí)現(xiàn)彈出容器層
- 01-10winform 實(shí)現(xiàn)控制輸入法
- 01-10WinForm實(shí)現(xiàn)程序一段時(shí)間不運(yùn)行自動(dòng)關(guān)閉的方法
- 01-10Winform消除button按下出現(xiàn)的虛線簡(jiǎn)單實(shí)現(xiàn)方法


閱讀排行
- 1C語言 while語句的用法詳解
- 2java 實(shí)現(xiàn)簡(jiǎn)單圣誕樹的示例代碼(圣誕
- 3利用C語言實(shí)現(xiàn)“百馬百擔(dān)”問題方法
- 4C語言中計(jì)算正弦的相關(guān)函數(shù)總結(jié)
- 5c語言計(jì)算三角形面積代碼
- 6什么是 WSH(腳本宿主)的詳細(xì)解釋
- 7C++ 中隨機(jī)函數(shù)random函數(shù)的使用方法
- 8正則表達(dá)式匹配各種特殊字符
- 9C語言十進(jìn)制轉(zhuǎn)二進(jìn)制代碼實(shí)例
- 10C語言查找數(shù)組里數(shù)字重復(fù)次數(shù)的方法
本欄相關(guān)
- 01-10C#通過反射獲取當(dāng)前工程中所有窗體并
- 01-10關(guān)于ASP網(wǎng)頁無法打開的解決方案
- 01-10WinForm限制窗體不能移到屏幕外的方法
- 01-10WinForm繪制圓角的方法
- 01-10C#實(shí)現(xiàn)txt定位指定行完整實(shí)例
- 01-10WinForm實(shí)現(xiàn)仿視頻播放器左下角滾動(dòng)新
- 01-10C#停止線程的方法
- 01-10C#實(shí)現(xiàn)清空回收站的方法
- 01-10C#通過重寫Panel改變邊框顏色與寬度的
- 01-10C#實(shí)現(xiàn)讀取注冊(cè)表監(jiān)控當(dāng)前操作系統(tǒng)已
隨機(jī)閱讀
- 08-05dedecms(織夢(mèng))副欄目數(shù)量限制代碼修改
- 01-10C#中split用法實(shí)例總結(jié)
- 01-11Mac OSX 打開原生自帶讀寫NTFS功能(圖文
- 08-05DEDE織夢(mèng)data目錄下的sessions文件夾有什
- 01-10delphi制作wav文件的方法
- 08-05織夢(mèng)dedecms什么時(shí)候用欄目交叉功能?
- 01-10SublimeText編譯C開發(fā)環(huán)境設(shè)置
- 01-11ajax實(shí)現(xiàn)頁面的局部加載
- 04-02jquery與jsp,用jquery
- 01-10使用C語言求解撲克牌的順子及n個(gè)骰子