A bit like this? Rather that a Mutex (which would also work), this relies on
only being able to bind one server to the port.
using System;
using System.Runtime.Remoting.Channels;
using System.Runtime.Remoting;
using System.Runtime.Remoting.Channels.Ipc;
class Program
{
static void Main(string[] appArgs)
{
string message = string.Join("|", appArgs);
if (RemoteMessage.StartServer())
{ // new instance; start main app
RemoteMessage.MessageReceived += delegate(object sender,
RemoteMessage.RemoteMessageEventArgs remoteArgs)
{
Console.WriteLine("Received: " + remoteArgs.Message);
};
Console.WriteLine("Startup: " + message);
Console.WriteLine("Press [Return] to end server");
Console.ReadLine();
}
else
{ // already running; forward the message
RemoteMessage.SendMessage(message);
Console.WriteLine("Forwarded: " + message);
}
}
}
public static class RemoteMessage
{
public static event EventHandler<RemoteMessageEventArgs>
MessageReceived;
private static void OnMessageReceived(string message)
{
EventHandler<RemoteMessageEventArgs> handler = MessageReceived;
if (handler != null)
{
handler(typeof(RemoteMessage), new
RemoteMessageEventArgs(message));
}
}
public class RemoteMessageEventArgs : EventArgs
{
public readonly string Message;
public RemoteMessageEventArgs(string message)
{
Message = message;
}
}
public sealed class RemoteAgent : ContextBoundObject
{
public void ProcessMessage(string message)
{
RemoteMessage.OnMessageReceived(message);
}
}
private readonly static object _syncLock = new object();
private static object SyncLock { get { return _syncLock; } }
private static int _port = 32561;
public static int Port
{
get { lock (SyncLock) { return _port; } }
set { lock (SyncLock) { _port = value; } }
}
private static string _app = "Anon";
public static string App
{
get { lock (SyncLock) { return _app; } }
set
{
if (value == null) throw new ArgumentNullException("App");
lock (SyncLock)
{
_app = value;
}
}
}
public static bool StartServer()
{
try
{
int port = Port;
string app = App;
if (ChannelServices.GetChannel("ipc") == null)
{
ChannelServices.RegisterChannel(new IpcChannel("127.0.0.1:"
+ port.ToString()), false);
}
WellKnownServiceTypeEntry serviceType = new
WellKnownServiceTypeEntry(typeof(RemoteAgent), app,
WellKnownObjectMode.Singleton);
RemotingConfiguration.RegisterWellKnownServiceType(serviceType);
return true;
}
catch (Exception e)
{
return false; // server already running
}
}
public static void SimulateMessage(string message)
{
OnMessageReceived(message);
}
public static bool SendMessage(string message, string server, string
app, int port)
{
bool localChannel;
IChannel channel = ChannelServices.GetChannel("ipc");
localChannel = channel == null;
string uri = string.Format("ipc://{2}:{0}/{1}", port, app, server);
if (localChannel)
{
channel = new IpcChannel();
ChannelServices.RegisterChannel(channel, false);
}
try
{
if
(RemotingConfiguration.IsWellKnownClientType(typeof(RemoteAgent)) == null)
{
WellKnownClientTypeEntry serviceType = new
WellKnownClientTypeEntry(typeof(RemoteAgent), uri);
RemotingConfiguration.RegisterWellKnownClientType(serviceType);
}
RemoteAgent agent =
(RemoteAgent)Activator.GetObject(typeof(RemoteAgent), uri);
try
{
agent.ProcessMessage(message);
return true;
}
catch
{
return false;
}
}
finally
{
if (localChannel)
{
ChannelServices.UnregisterChannel(channel);
}
}
}
public static bool SendMessage(string message)
{
return SendMessage(message, "127.0.0.1", App, Port);
}
}