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