Принудительно использовать один экземпляр службы TopShelf

Я использую TopShelf для размещения своей службы Windows. Это мой код установки:

static void Main(string[] args)
{
    var host = HostFactory.New(x =>
    {
        x.Service<MyService>(s =>
        {
            s.ConstructUsing(name => new MyService());
            s.WhenStarted(tc => tc.Start());
            s.WhenStopped(tc => tc.Stop());
        });

        x.RunAsLocalSystem();
        x.SetDescription(STR_ServiceDescription);
        x.SetDisplayName(STR_ServiceDisplayName);
        x.SetServiceName(STR_ServiceName);
    });

    host.Run();
}

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

Мне очень нравится подход на основе mutex, но я понятия не имею, как это сделать. Работа с ТопШелф.


person Toperz    schedule 14.07.2012    source источник


Ответы (3)


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

private static Mutex mutex = new Mutex(true, @"Global\{my-guid-here}");

static void Main(string[] args)
{
    if (mutex.WaitOne(TimeSpan.Zero, true))
    {
        try
        {
            var host = HostFactory.New(x =>
            {
                x.Service<MyService>(s =>
                {
                    s.ConstructUsing(name => new MyService());
                    s.WhenStarted(tc =>
                    {
                        tc.Start();
                    });
                    s.WhenStopped(tc => tc.Stop());
                });
                x.RunAsLocalSystem();
                x.SetDescription(STR_ServiceDescription);
                x.SetDisplayName(STR_ServiceDisplayName);
                x.SetServiceName(STR_ServiceName);
            });

            host.Run();
        }
        finally
        {
            mutex.ReleaseMutex();
        }
    }
    else
    {
        // logger.Fatal("Already running MyService application detected! - Application must quit");
    }
}
person Toperz    schedule 14.08.2012

Более простая версия:

static void Main(string[] args)
{
    bool isFirstInstance;
    using (new Mutex(false, "MUTEX: YOUR_MUTEX_NAME", out isFirstInstance))
    {
        if (!isFirstInstance)
        {
            Console.WriteLine("Another instance of the program is already running.");
            return;
        }

        var host = HostFactory.New(x =>
        ...
        host.Run();
    }
}
person Monsignor    schedule 13.05.2016

Просто добавьте код мьютекса в tc.Start() и освободите мьютекс в tc.Stop(), а также добавьте код мьютекса в Main консольного приложения.

person Andriy Kizym    schedule 14.07.2012