Я использую вот такой украденный где-то код. Он контролирует, что приложение создано, работает, а если запускается ещё одно такое же - сообщает об этом.
using System;
using System.Runtime.Remoting;
using System.Runtime.Remoting.Channels;
using System.Runtime.Remoting.Channels.Tcp;
using System.Threading;
namespace Pressmark.Service
{
[Serializable]
class SingletonController : MarshalByRefObject
{
private const string ControllerName = "PressMarkInstance";
private static TcpChannel _mTcpChannel = null;
private static Mutex _mMutex = null;
public delegate void ReceiveDelegate(string[] args);
static private ReceiveDelegate _mReceive = null;
static public ReceiveDelegate Receiver
{
get { return _mReceive; }
set { _mReceive = value; }
}
public static bool IamFirst(ReceiveDelegate r)
{
if (IamFirst())
{
Receiver += r;
return true;
}
else
{
return false;
}
}
public static bool IamFirst()
{
_mMutex = new Mutex(false, "PressMarkInstance");
if (_mMutex.WaitOne(1, true))
{
//We locked it! We are the first instance!!!
CreateInstanceChannel();
return true;
}
//Not the first instance!!!
_mMutex.Close();
_mMutex = null;
return false;
}
private static void CreateInstanceChannel()
{
_mTcpChannel = new TcpChannel(1234);
ChannelServices.RegisterChannel(_mTcpChannel, false);
RemotingConfiguration.RegisterWellKnownServiceType(typeof(SingletonController), ControllerName,
WellKnownObjectMode.SingleCall);
}
public static void Cleanup()
{
if (_mMutex != null)
{
_mMutex.Close();
}
if (_mTcpChannel != null)
{
_mTcpChannel.StopListening(null);
}
_mMutex = null;
_mTcpChannel = null;
}
public static void Send(string[] s)
{
TcpChannel channel = new TcpChannel();
ChannelServices.RegisterChannel(channel, false);
SingletonController ctrl = (SingletonController)Activator.GetObject(typeof(SingletonController), "tcp://localhost:1234/" + ControllerName);
ctrl.Receive(s);
}
public void Receive(string[] s)
{
if (_mReceive != null) _mReceive(s);
}
}
}
Соответственно, программа, когда запускаемся (у меня WPF приложение), на нем висит слушатель события запуска. Если процесс уже существует - забираем из него коммандную строку и убиваем процесс.
private void App_OnStartup(object sender, StartupEventArgs e)
{
if (!SingletonController.IamFirst(RunCommand))
{
var args = e.Args;
if (args.Length == 0) args = new[] { "newwindow" }; // если мы просто пытаемся открыть новый документ, а сервис уже запущен
SingletonController.Send(args);
Current.Shutdown();
return;
}
RunCommand(e.Args);
if (OpenedDocuments.Count == 0) CreateNewWindow(null); // если ещё ни одного окна не создано, создаем его пустое.
}
Не очень прозрачно (давно хотел переделать, но руки не доходили), но разобраться можно. Соответственно, RunCommand и CreateNewWindow методы вам нужно реализовать самому.