1、SingletonExeController.cs
using System; using System.Collections.Generic; using System.Windows.Forms; using System.Threading; using System.Diagnostics; using System.Runtime.Remoting; using System.Runtime.Remoting.Channels; using System.Runtime.Remoting.Channels.Tcp; namespace SingletonExeTest { //通过检测Mutex,确认只会启用一个进程 //第一个进程,会启用Tcp监听,接收参数 //后续进程,通过TcpChannel,将参数传递给第一个进程 //使用前,必须先调用InitSingleton,使用后必须调用UninitSingleton class SingletonExeController : MarshalByRefObject { private static Mutex m_Mutex = null; private static TcpChannel m_TCPChannel = null; //初始化 public static void InitSingleton() { string assemblyName = System.Reflection.Assembly.GetExecutingAssembly().GetName(false).CodeBase; string uniqueIdentifier = assemblyName.Replace("\\", "_"); m_Mutex = new Mutex(false, uniqueIdentifier); } //回收资源 public static void UninitSingleton() { if (m_Mutex != null) { m_Mutex.Close(); } m_Mutex = null; if (m_TCPChannel != null) { m_TCPChannel.StopListening(null); } m_TCPChannel = null; } //判断是否为第一个进程 public static bool FirstProcToRun(int tcpPort,String serviceName) { if (m_Mutex.WaitOne(1, true)) { CreateTCPChannel(tcpPort,serviceName); return true; } else { m_Mutex.Close(); m_Mutex = null; return false; } } //创建TCP监听 private static void CreateTCPChannel(int tcpPort,String serviceName) { try { m_TCPChannel = new TcpChannel(tcpPort); ChannelServices.RegisterChannel(m_TCPChannel, false); RemotingConfiguration.RegisterWellKnownServiceType(typeof(SingletonExeController), serviceName, WellKnownObjectMode.SingleCall); } catch(Exception ex) { //Fix me... //port in use MessageBox.Show(ex.Message); } } //后续进程,向第一个进程发送自己的参数 public static void Send(int port,String serviceName, string[] s) { try { SingletonExeController ctrl; TcpChannel channel = new TcpChannel(); ChannelServices.RegisterChannel(channel, false); try { String address = "tcp://localhost:" + port + "/" + serviceName; ctrl = (SingletonExeController)Activator.GetObject(typeof(SingletonExeController), address); } catch (Exception e) { Console.WriteLine("Exception: " + e.Message); throw; } ctrl.Receive(s); } catch (Exception ex) { MessageBox.Show(ex.Message); } } //第一个进程,接收传入参数 public void Receive(string[] s) { //Do something here //... //Test Code MessageBox.Show(s[0]); } //查找第一个进程 public static Process findMainProcess() { Process currentProcess = Process.GetCurrentProcess(); string processName = currentProcess.ProcessName; Process mainProcess = null; Process[] allProcesses = Process.GetProcessesByName(processName); if (allProcesses != null) { foreach (Process p in allProcesses) { if (p.Id != currentProcess.Id) { if (p.MainWindowHandle != null) { mainProcess = p; break; } } } } return mainProcess; } //查找第一个进程的主窗口 public static IntPtr findMainWnd() { IntPtr mainWnd = IntPtr.Zero; Process p = findMainProcess(); if(p!=null && p.MainWindowHandle != null) { mainWnd=p.MainWindowHandle; } return mainWnd; } } }
2、Program.cs
using System; using System.Collections.Generic; using System.Windows.Forms; using System.Diagnostics; using System.Threading; namespace SingletonExeTest { static class Program { [STAThread] static void Main(string[] args) { //Debugger.Launch(); //Debugger.Break(); int tcpPort = 9999; String serviceName = "MyTestService"; SingletonExeController.InitSingleton(); if (SingletonExeController.FirstProcToRun(tcpPort, serviceName)) { Application.EnableVisualStyles(); Application.SetCompatibleTextRenderingDefault(false); //Do something here //... //Test Code Application.Run(new MainForm()); } else { IntPtr mainWnd = SingletonExeController.findMainWnd(); Win32Utils.ShowWindow(mainWnd, Win32Utils.SW_RESTORE); //Real Code //SingletonExeController.Send(tcpPort, serviceName, args); //Test Code String[] msgs = {"hi","hello","good"}; SingletonExeController.Send(tcpPort, serviceName, msgs); } SingletonExeController.UninitSingleton(); } } }