代碼參考: C#代碼 程序只能運行一次!
防止程序運行多個實例的方法有多種,如:通過使用互斥量和進程名等.而我想要實現的是:在程序運行多個實例時激活的是第一個實例,使其獲得焦點,並在前端顯示.
主要用到兩個API 函數:
- ShowWindowAsync 該函數設置由不同線程產生的窗口的顯示狀態。
- SetForegroundWindow 該函數將創建指定窗口的線程設置到前臺,並且激活該窗口。鍵盤輸入轉向該窗口,併爲用戶改各種可視的記號。系統給創建前臺窗口的線程分配的權限稍高於其他線程。
代碼如下:
- static class Program
- {
- /// <summary>
- /// 該函數設置由不同線程產生的窗口的顯示狀態。
- /// </summary>
- /// <param name="hWnd">窗口句柄</param>
- /// <param name="cmdShow">指定窗口如何顯示。查看允許值列表,請查閱ShowWlndow函數的說明部分。</param>
- /// <returns>如果函數原來可見,返回值爲非零;如果函數原來被隱藏,返回值爲零。</returns>
- [DllImport("User32.dll")]
- private static extern bool ShowWindowAsync(IntPtr hWnd, int cmdShow);
- /// <summary>
- /// 該函數將創建指定窗口的線程設置到前臺,並且激活該窗口。鍵盤輸入轉向該窗口,併爲用戶改各種可視的記號。系統給創建前臺窗口的線程分配的權限稍高於其他線程。
- /// </summary>
- /// <param name="hWnd">將被激活並被調入前臺的窗口句柄。</param>
- /// <returns>如果窗口設入了前臺,返回值爲非零;如果窗口未被設入前臺,返回值爲零。</returns>
- [DllImport("User32.dll")]
- private static extern bool SetForegroundWindow(IntPtr hWnd);
- private const int WS_SHOWNORMAL = 1;
- /// <summary>
- /// 應用程序的主入口點。
- /// </summary>
- [STAThread]
- static void Main()
- {
- Application.EnableVisualStyles();
- Application.SetCompatibleTextRenderingDefault(false);
- Process instance = RunningInstance();
- if (instance == null)
- {
- Form1 frm = new Form1();
- Application.Run(new Form1());
- }
- else
- {
- HandleRunningInstance(instance);
- }
- }
- /// <summary>
- /// 獲取正在運行的實例,沒有運行的實例返回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>
- /// 顯示已運行的程序。
- /// </summary>
- public static void HandleRunningInstance(Process instance)
- {
- ShowWindowAsync(instance.MainWindowHandle, WS_SHOWNORMAL); //顯示,可以註釋掉
- SetForegroundWindow(instance.MainWindowHandle); //放到前端
- }
- }
記着引用以下命名空間:
using System.Runtime.InteropServices;
using System.Diagnostics;
using System.Reflection;