Friday, October 24, 2008

C# - запуск только одной копии программы


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

Собственно код:

using System;
using System.Collections.Generic;
using System.Windows.Forms;
using System.Threading;

namespace MutexOnesF
{
public class SingleInstance
{
Mutex mutex = null;
EventWaitHandle even = null;
bool UnauthorizedAccess = false;
public bool FirstInstanceM
{
get
{
if (mutex == null && UnauthorizedAccess == false)
{
mutex = new Mutex(true, @"Global\MutexOnesF");
return true;
}
else return false;
}
}
public bool FirstInstanceE
{
get
{
if (even == null && UnauthorizedAccess == false)
{

try
{
even = new EventWaitHandle(false, EventResetMode.AutoReset,
@"Global\EvenOnesF");
}
catch (Exception ex)
{
}
return true;
}
else return false;
}
}

public SingleInstance()
{
try
{
mutex = Mutex.OpenExisting(@"Global\MutexOnesF");
//even = EventWaitHandle.OpenExisting(@"Global\EvenOnesF");
}
catch (WaitHandleCannotBeOpenedException e)
{
}
catch (UnauthorizedAccessException exp)
{
// mutex exist but cannot be open
UnauthorizedAccess = true;
}
}
}
static class Program
{
///
/// The main entry point for the application.
///
[STAThread]
static void Main()
{
SingleInstance single = new SingleInstance();

if (single.FirstInstanceM)
{
Application.EnableVisualStyles();
Application.SetCompatibleTextRenderingDefault(false);
Application.Run(new Form1());
}
}
}
}


Цена вопроса собственно была только в добавлении префикса Global\ в имена объектов синхронизации. Без данного префикса мьютекс/евент создаються только в рамках текущей windows сессии пользователя. В чем можно убедиться используя process explorer.

Вы увидите чтото типа такого
Mutant \Sessions\1\BaseNamedObjects\{имя_мьютекса}
Mutant \Sessions\2\BaseNamedObjects\{имя_мьютекса}
для каждого из процессов.
При использовании же префикса Global\ ,объект будет один вида
Mutant BaseNamedObjects\{имя_мьютекса}
что нам собственно и требовалось.

Не стоит забывать также о других пользователях которые также могут попытаться запустить приложение и если мьютекс уже создан выпадут по исключению UnauthorizedAccessException, что значит мьютекс существует, но к нему нет доступа.
В нашем случае важен сам факт СУЩЕСТВОВАНИЯ, а не работа с самим объектом, по этому не будем замарачиваться с правами.

Комментариев нет т.к. код довольно таки прозрачный и говорящий сам за себя.





































































































No comments: