首先要確保要避免程式被重複執行,一般常見的基本方法是,透過查詢目前所有執行程序(process)的名稱,來檢查是否有已經被執行,然而這種方式需要讀取程序清單逐個進行檢查,本文透過 互斥鎖(Mutual exclusion, Mutex) 來達到相同之效果,程式如下:

 

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Linq;
using System.Text;
using System.Threading;
using System.Threading.Tasks;

public class SingleProcessModule
{
    [System.Runtime.InteropServices.DllImport("User32.dll")]
    private static extern bool SetForegroundWindow(IntPtr handle);
    [System.Runtime.InteropServices.DllImport("User32.dll")]
    private static extern bool ShowWindow(IntPtr handle, int nCmdShow);
    [System.Runtime.InteropServices.DllImport("User32.dll")]
    private static extern bool IsIconic(IntPtr handle);
        
    private static SingleProcessModule _instance = null;
    public static SingleProcessModule getInstance()
    {
        if (_instance == null)
            _instance = new SingleProcessModule();
        return _instance;
    }
        
    private const int SW_RESTORE = 9;
    private string MutexUniqueName;
    private Mutex m = null;
        
    private SingleProcessModule()
    {
        MutexUniqueName = "TYGR_SINGLE_MUTEX_" + Process.GetCurrentProcess().ProcessName;
    }
        
    public bool IsCreated()
    {
        Boolean bCreatedNew = false;

        //Create a new mutex using specific mutex name
        m = new Mutex(false, MutexUniqueName, out bCreatedNew);
        GC.Collect();
        if (bCreatedNew)
            return false;
            
        BringSelfToFront();
        return true;
    }

    private void BringSelfToFront()
    {
        foreach (Process p in Process.GetProcessesByName(Process.GetCurrentProcess().ProcessName))
            BringProcessToFront(p);
    }

    private static void BringProcessToFront(Process process)
    {
        IntPtr handle = process.MainWindowHandle;
        if (IsIconic(handle))
        {
            ShowWindow(handle, SW_RESTORE);
        }

        SetForegroundWindow(handle);
    }
}

 

其中主要的核心程師部分為第40行 到 第43行,判斷其程式是否已經被啟動,這邊要注意的是,如果是將Mutext 宣告為函數內的變數,在Release 編譯下,可能會被GC釋放,導致Mutex失效,因此將其宣告為類別屬性。

 

 

由於在視窗介面程式情況下,若程式一直無法啟動,使用者會感到奇怪,不利於使用者體驗,因此在模組化的過程添加了當成是已被建立會自行將程式顯示到最上層( 第 45 行 )。

 

使用上非常簡單,只要在程式的最開始部分呼叫並進行判斷即可,範例如下:

1
2
if(!SingleProcessModule.getInstance().IsCreated())
    Application.Run(new Form1());

本物件模組化時,Mutex是使用Process Name進行設定,因此即使有多個不同程式調用此模組也不會互相衝突。

 

 
arrow
arrow
    文章標籤
    mutex .net C#
    全站熱搜
    創作者介紹
    創作者 Lung-Yu,Tsai 的頭像
    Lung-Yu,Tsai

    Lung-Yu,Tsai 的部落格

    Lung-Yu,Tsai 發表在 痞客邦 留言(0) 人氣()