Недавно пришлось решить вопрос запуска только одной копии программы на 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 - работает отлично.
Такой вот простой вспомагательный класс решает одну важную задачу. Спасибо.

Комментарии (10) на запись “C# - запуск только одной копии программы”

  1. Гром пишет:

    А если названия исполнительных файлов поменять - все равно работает? Т.е. один запустился с одинм названием, а другой с другим?

  2. DeVoid пишет:

    Да, работает даже если файлы переименовать.

  3. Alexey Nayda пишет:

    Чтобы все было совсем хорошо, тебе еще нужно унаследовать класс твоего прложения от SingleInstance.

  4. z00lus пишет:

    почему не перенести создание мьютекса в тот же кетч WaitHandleCannotBeOpenedException, а чтобы сборщик мусора его даже не пытался убить вынести Mutex mutex из локальной области конструктора в переменные класса?
    Собственно эту же переменную можно использовать как замена ненужному boolу.
    к примеру так:
    public bool FirstInstance
    {
    get {
    if(mutex!=null) return false;
    else return true;
    }
    }

  5. Fahrain пишет:

    Кстати, метод не работает если программа запускается на сервере терминалов. Если логиниться в несколько сессий под одним и тем же пользователем - программа успешно стартует в любой из сессий.
    А жаль…

  6. z00lus пишет:

    Вопрос с терминальным сервером решаемый, нужно добавлять префикс Global\ к именам объектов синхронизации.
    Свой вариант велосипеда запостил в блоге.

  7. Fahrain пишет:

    Ага, спасибо. Завтра попробую :)
    Просто есть задача гонять на сервере бот-почтовик и хочется чтобы две его копии случайно не запускались в разных сессиях.

  8. relaxreg пишет:

    Спасибо, за ссылку… тоже мне было
    срочно нужно.

  9. Bitonic пишет:

    Хм. Недавно опубликовал в своем блоге (bitonic.wordpress.com) примерно то же самое - работа с мьютексом, только на С++. Мой пример короче, хотя признаю, что твой/ваш техничнее :-)

  10. Tantal пишет:

    Тема с…к нераскрыта.

    Во многих случаях необходимо передать параметры коммандной строки первому экземпляру или активировать это окно. В данном случае - первый экземпляр программы даже не узнает о попытке запуска второй копии. Решается все при помощи семафора, а не мьютекса.

Оставить комментарий