[C#] [WinForm] 使程式無法重複開啟,只能單一執行

[C#] [WinForm] 使程式無法重複開啟,只能單一執行

為了避免使用者出錯

有時候必須做好一次只能啟動一個程序的防呆措施

而最簡單的做法就是用Mutex來實現

Mutex mutex = new Mutex(bool initiallyOwned, string name, out bool createdNew);

initiallyOwned : 此執行緒對Mutex是否有初始擁有權
name : 為這個Mutex命名(可隨意取個特殊名,在此我使用程序本身的名字)
createdNew : 回傳此執行緒是否為新

所以只要用這個方法檢查回傳的createdNew即可得知是否為新開啟程序

[STAThread]
        static void Main()
        {
            bool isFirstOpen;

            Mutex mutex = new Mutex(false, Application.ProductName , out isFirstOpen);

            if (isFirstOpen)
            {
                Application.EnableVisualStyles();
                Application.SetCompatibleTextRenderingDefault(false);
                Application.Run(new Form1());
            }
            else
            {
                MessageBox.Show("重複開啟!");
            }

            mutex.Dispose();
        }

最後一段mutex.Dispose(); 也可以不用

但聽說(?)mutex有可能會被GC處理掉導致失效(雖然我還沒遇到過)

所以還是加上去比較保險

另外如果想要使用者重複開啟程序時 會把舊程序拉到最上層的話

下面提供一個可行的方法

using System.Diagnostics;
using System.Reflection;
using System.Runtime.InteropServices;

[STAThread]
        static void Main()
        {
            // Get the running instance
            Process instance = RunningInstance();

            if (instance == null)
            {
                Application.EnableVisualStyles();
                Application.SetCompatibleTextRenderingDefault(false);
                Application.Run(new Form1());
            }
            else
            {
                // There is another instance of this process.  
                HandleRunningInstance(instance);
            }
            
        }

        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;
        }

        public static void HandleRunningInstance(Process instance)
        {
            // Make sure the window is not minimized or maximized 
            ShowWindowAsync(instance.MainWindowHandle, WS_SHOWNORMAL);
            // Set the real intance to foreground window
            SetForegroundWindow(instance.MainWindowHandle);
        }

        [DllImport("User32.dll")]
        private static extern bool ShowWindowAsync(IntPtr hWnd, int cmdShow);
        [DllImport("User32.dll")]
        private static extern bool SetForegroundWindow(IntPtr hWnd);

        private const int WS_SHOWNORMAL = 1;

最後一行 WS_SHOWNORMAL 的設定是使呼叫出來的視窗大小

WS_SHOWNORMAL=1;  //normal
WS_SHOWNORMAL=2;  //minimized
WS_SHOWNORMAL=3;  //maximized

 

新手發文,有謬誤請告知,也請多多指教。