只启动一个实例

[STAThread]
static void Main()
{
bool createNew;
using (System.Threading.Mutex m = new System.Threading.Mutex(true, Application.ProductName, out createNew))
    {
if (createNew)
        {
            Application.EnableVisualStyles();
            Application.SetCompatibleTextRenderingDefault(false);
            Application.Run(new Form1());
        }
else
        {
            MessageBox.Show("Only one instance of this application is allowed!");
        }
    }
}

    主要使用了Sytem.Theading.Mutex对象,该对象用于解决多线程操作中的互斥问题,有关它的详细介绍读者可以参考MSDN。

http://msdn.microsoft.com/zh-cn/library/bwe34f1k(VS.80).aspx

[转 http://www.cnblogs.com/phaibin/archive/2008/05/19/1202418.html]

看到愚翁的这篇文章《如何使自己的程序只运行一次》 ,感觉有点问题。第一种方法用互斥体可以实现单实例,但是无法操纵原来的窗口。第二种方法按程序名搜寻进程,只要程序改了名字,就可以运行好几次了。在下面的评论里他又给了另一个链接,是个外国人写的:http://www.codeproject.com/csharp/cssingprocess.asp。他综合了互斥体和搜寻进程,如果已经打开了程序,则把原来的窗口显示出来。其实已经比较完美了,但是还有点问题。如果我的程序改了名,就会找不到原来的进程,就没有办法把原来的窗口显示出来了。
        在百度上搜索这方面的文章,看到这么一篇:《C# 单实例运行》,是在.NET 3.0中使用的,确实比较方便。
        我觉得关键是应该用打开程序的PID来搜寻,这样肯定不会错。于是我修改了程序,在程序第一次运行的时候把它的PID写到一个文件中去,下一次再运行就从这个文件中找到打开窗口的PID。
        再后来经人提醒可以用进程间通讯来获得PID,虽然程序麻烦了一点,但是不用再写文件了。下面是我写的程序完整代码:

1namespace SingleInstance {
2 static class Program {
3 /**//**/
4 /**//// <summary>
5 /// 应用程序的主入口点。
6 /// </summary>
7        [STAThread]
8 static void Main() {
9            Application.EnableVisualStyles();
10            Application.SetCompatibleTextRenderingDefault(false);
11 bool bCreatedNew;
12            Mutex m = new Mutex(false, "myUniqueName", out bCreatedNew);
13 if (bCreatedNew) {
14 //实例化服务器信道
15                IpcServerChannel channel = new IpcServerChannel("ServerChannel");
16 //注册信道
17                ChannelServices.RegisterChannel(channel, false);
18 //注册服务类型
19                RemotingConfiguration.RegisterWellKnownServiceType(typeof(ProcessID), "ProcessID", WellKnownObjectMode.SingleCall);
20                Application.Run(new Form1());
21            }
22 else {
23 //建立客户端信道
24                IpcClientChannel channel = new IpcClientChannel();
25 //注册信道
26                ChannelServices.RegisterChannel(channel, false);
27                ProcessID obj = (ProcessID)Activator.GetObject(typeof(ProcessID), "ipc://ServerChannel/ProcessID");
28 int processID = obj.PID;
29                Process instance = Process.GetProcessById(processID);
30                HandleRunningInstance(instance);
31            }
32        }
33 public static void HandleRunningInstance(Process instance) {
34 //还原窗口
35 if (IsIconic(instance.MainWindowHandle))
36                ShowWindowAsync(instance.MainWindowHandle, SW_RESTORE);
37 //前置窗口
38            SetForegroundWindow(instance.MainWindowHandle);
39        }
40
41        [DllImport("User32.dll")]
42 private static extern bool ShowWindowAsync(IntPtr hWnd, int cmdShow);
43        [DllImport("User32.dll")]
44 private static extern bool SetForegroundWindow(IntPtr hWnd);
45        [DllImport("user32.dll")]
46 private static extern bool IsIconic(IntPtr hWnd);
47 private const int SW_RESTORE = 9;
48    }
49 public class ProcessID : MarshalByRefObject {
50 private int _pID;
51 public int PID {
52 get { return _pID; }
53        }
54 public ProcessID() {
55            _pID = Process.GetCurrentProcess().Id;
56        }
57    }
58}

        其中进程间通讯的代码来自与《利用IPC通道进行进程间通信(C#)》。这方面的知识原来没有学过,也许还有更方便的办法。
        这里面只涉及了很简单的情况,即单个窗口的情况。没有考虑MDI程序,在主窗口里面打开的情况。

你可能感兴趣的:(实例)