Иногда необходимо запретить запускать несколько копий одного приложения. Причины тому могут быть самые разные, сейчас не будем их обсуждать, а перейдем непосредственно к коду, позволяющему добиться требуемой функциональности. Для тех, кто знаком с многопоточным программированием, наверняка знаком с классом Mutex. Напомню, что Мьютекс - это синхронизирующий класс, инкапсулирующий в себе средства синхронизаци потоков (процессов) на конкретной операционной системе. Данный класс чаще всего используют для обеспечения строго единственного доступа к данным в определенный промежуток времени так, что в любой момент к данным имеет доступ только один поток и не более.
Когда один поток получает мьютекс-объект,все остальные потоки не могут получить доступ к нему до тех пор, пока данный поток не освободит его. Мы помним, что любое приложение запускается в отдельном потоке, а значит, вполне логично воспользоваться возможностями мьютекса для управления копиями приложения.
Как же работает Mutex.
При своем запуске приложение пытается создать мьютекс с определенным именем. Если это удалось, то запускаемый экземпляр приложения является первым и пока единственным. В противном случае Mutex не позволит вновь запустить пока еще работающее приложение
Поэтому, данный класс мы и используем в нашем случае:
using System;
using System.Windows.Forms;
using System.Threading;
namespace OneCopyOfApp
{
static class Program
{
private static Mutex m_instance;
private const string m_appName = "NameOfMyApp";
[STAThread]
static void Main()
{
bool tryCreateNewApp;
m_instance = new Mutex(true, m_appName,
out tryCreateNewApp);
if (tryCreateNewApp)
{
Application.EnableVisualStyles();
Application.
SetCompatibleTextRenderingDefault(false);
Application.Run(new Form1());
return;
}
}
}
}
Ключевым моментом в данном коде является инструкция
m_instance = new Mutex(true, m_appName, out tryCreateNewApp);
В данном конструкторе первый параметр указывает на необходимость для приложения получать создаваемый мьютекс. True указывает на это. Второй параметр задает имя мьютекса. Третий параметр как раз устанавливается в процессе создания мьютекса и указывает был ли получен мьютекс. Соответственно, с одним и тем же именем мьютекса мы не можем захватить его дважды. В итоге, проверив факт захвата мьютекса мы сами определяем запускать ли новую копию приложения.
Создайте новый проект и поместите в него данный код. Проже всего проверить его в работе это открыть еще одно окно VisualStudio с данным проектом и попробовать запустить его из обеих открытых VS. В итоге первый запуск пройдет нормально, второй попытается запуститься и сразу же закроется. Мы успеем лишь заметить некоторое мигание.
Есть второй, более безопасный в отношении атак способ. Основан он на библиотеках VB.
Для начала добавьте ссылку на сборку Microsoft.VisualBasic.dll.

Рисунок 1. Добавление сборки VB
Для удобства вынести в начало проекта пространство имен Microsoft.VisualBasic.ApplicationServices.
Ну а сам код следующий (обратите внимание каким образом мы вызываем метод Run())
using System;
using System.Windows.Forms;
using System.Threading;
using Microsoft.VisualBasic.ApplicationServices;
namespace OneCopyOfApp
{
public class OneInstanceApp :
WindowsFormsApplicationBase
{
private SingleInstanceApplication()
{
base.IsSingleInstance = true;
}
public static void Run(Form form,
StartupNextInstanceEventHandler startupHandler)
{
OneInstanceApp app =
new OneInstanceApp();
app.MainForm = form;
app.StartupNextInstance += startupHandler;
app.Run(Environment.GetCommandLineArgs());
}
}
static class Program
{
[STAThread]
static void Main()
{
Application.EnableVisualStyles();
OneInstanceApp.Run(new Form1(),
StartupNextInstanceHandler);
}
static void StartupNextInstanceHandler(
object sender, StartupNextInstanceEventArgs e)
{
MessageBox.Show(e.CommandLine[0]);
}
}
}
Вот, таким нехитрым кодом мы запрещаем повторный запуск любого приложения.