C# - запуск только одной копии программы
10.08.2008
Недавно пришлось решить вопрос запуска только одной копии программы на C#. Вопрос решил успешно, используя Mutex. Собственно велосипед изобретать не стал и воспользовался готовым кодом, который нашел здесь. Сначала создаем класс (который я успешно использовал уже в нескольких проектах):
public class SingleInstance
{
private bool firstInstance = false;
public bool FirstInstance
{
get { return firstInstance; }
}
public SingleInstance()
{
Mutex mutex=null;
try
{
//Пытаемся получить мутекс, если он уже существует
mutex = Mutex.OpenExisting("ИмяНашегоПриложения");
}
catch (WaitHandleCannotBeOpenedException e)
{
//Если получили ошибку - мутекс не существует
firstInstance = true;
}
//Если null - создаем новый мутекс
if (mutex == null)
{
mutex = new Mutex(false, "ИмяНашегоПриложения");
//Чтобы сборщик мусора не удалил наш мутекс делаем так:
GC.KeepAlive(mutex);
}
}
}
После чего изменяем Program.cs:
[STAThread]
static void Main()
{
SingleInstance single = new SingleInstance();
if (single.FirstInstance)
{
Application.EnableVisualStyles();
Application.SetCompatibleTextRenderingDefault(false);
Application.Run(new MainForm());
}
}
Код не дает запускать несколько копий программы, которая написана на C#. Тестировал под XP, Vista с различными SP - работает отлично.
Такой вот простой вспомагательный класс решает одну важную задачу. Спасибо.
11.08.2008 в 13:02
А если названия исполнительных файлов поменять - все равно работает? Т.е. один запустился с одинм названием, а другой с другим?
13.08.2008 в 10:56
Да, работает даже если файлы переименовать.
26.08.2008 в 22:53
Чтобы все было совсем хорошо, тебе еще нужно унаследовать класс твоего прложения от SingleInstance.
01.09.2008 в 11:36
почему не перенести создание мьютекса в тот же кетч WaitHandleCannotBeOpenedException, а чтобы сборщик мусора его даже не пытался убить вынести Mutex mutex из локальной области конструктора в переменные класса?
Собственно эту же переменную можно использовать как замена ненужному boolу.
к примеру так:
public bool FirstInstance
{
get {
if(mutex!=null) return false;
else return true;
}
}
03.09.2008 в 20:26
Кстати, метод не работает если программа запускается на сервере терминалов. Если логиниться в несколько сессий под одним и тем же пользователем - программа успешно стартует в любой из сессий.
А жаль…
04.09.2008 в 15:53
Вопрос с терминальным сервером решаемый, нужно добавлять префикс Global\ к именам объектов синхронизации.
Свой вариант велосипеда запостил в блоге.
04.09.2008 в 20:29
Ага, спасибо. Завтра попробую
Просто есть задача гонять на сервере бот-почтовик и хочется чтобы две его копии случайно не запускались в разных сессиях.
06.09.2008 в 17:25
Спасибо, за ссылку… тоже мне было
срочно нужно.
10.10.2008 в 23:09
Хм. Недавно опубликовал в своем блоге (bitonic.wordpress.com) примерно то же самое - работа с мьютексом, только на С++. Мой пример короче, хотя признаю, что твой/ваш техничнее
11.11.2008 в 18:56
Тема с…к нераскрыта.
Во многих случаях необходимо передать параметры коммандной строки первому экземпляру или активировать это окно. В данном случае - первый экземпляр программы даже не узнает о попытке запуска второй копии. Решается все при помощи семафора, а не мьютекса.