實現思路:
在Main()方法開始時遍歷所有進程,獲取每個進程的程序集GUID和PID,若發現有跟自己GUID相同且PID不同的進程,就勒令自身退出。
注:
1、采用GUID是為了盡可能保證判定的可靠性,采用進程名太不靠譜。而且程序集GUID是建立項目時就生成的,不隨版本、內容的變化而變化,所以除非人為改動,否則同一項目編譯若干次都還是那個GUID,用來判斷程序集身份再適合不過。題外,網上盛傳的互斥體方法,互斥名也建議用GUID;
2、之所以要加上進程ID的判斷,是因為遍歷的進程中已經包含自身進程,所以必須排除自身;
3、訪問某些進程的MainModule屬性會引發異常,所以采用try-catch跳過這些進程;
4、經嘗試只有C#寫的程序才能獲取到GUID(有點廢話~),但這樣已經足夠
5、退出自身這裡采用的是Environment.Exit()方法,Application.Exit()方法不管用,程序仍然會運行,我猜原因是Application都還沒Run過,所以Exit不了~(小弟入門水平,很多東西只能靠坑蒙拐騙~哦不,是連蒙帶猜)
6、第一次在cnblogs寫博,希望各位前輩多多指教~少扔磚頭
1 using System;
2 using System.Diagnostics;
3 using System.Reflection;
4 using System.Runtime.InteropServices;
5 using System.Windows.Forms;
6
7 namespace TestCallAPIRefreshPolicy
8 {
9 static class Program
10 {
11 [STAThread]
12 static void Main()
13 {
14 Guid ownGUID = new Guid(((GuidAttribute)Attribute.GetCustomAttribute(Assembly.GetExecutingAssembly(), typeof(GuidAttribute))).Value);
15 Guid proGUID;
16 int ownPID = Process.GetCurrentProcess().Id;
17 int proPID;
18
19 foreach (Process p in Process.GetProcesses())
20 {
21 try
22 {
23 proGUID = new Guid(((GuidAttribute)Attribute.GetCustomAttribute(Assembly.LoadFile(p.MainModule.FileName), typeof(GuidAttribute))).Value);
24 proPID = p.Id;
25 if (proGUID.Equals(ownGUID) && proPID != ownPID)
26 {
27 MessageBox.Show("程序已運行");
28 Environment.Exit(Environment.ExitCode);
29 }
30 }
31 catch
32 {
33 continue;//遇上進程訪問異常就跳過該進程
34 }
35 }
36
37 //若未被Exit,正常啟動
38 Application.EnableVisualStyles();
39 Application.SetCompatibleTextRenderingDefault(false);
40 Application.Run(new FmMain());
41 }
42 }
43 }
摘自 ahdung