Как сделать так, чтобы приложение службы Windows работало как отдельная программа? - PullRequest
15 голосов
/ 28 июня 2010

Я начну с примера: веб-сервер Apache (под Windows) имеет приятную особенность: его можно запускать как отдельное приложение (с правами текущих пользователей), а также устанавливать и запускать как windowsобслуживать напрямую (как локальная системная учетная запись), используя тот же исполняемый файл.

Для того чтобы приложение запускалось как отдельное приложение, все, что ему нужно сделать, - это использовать статический public Main () в некоторых publicclass.

Чтобы приложение можно было установить и запустить как службу, оно должно определенным образом реализовать классы ServiceBase и Installer.Но если приложение, подобное этому, запускается как автономное приложение, оно отобразит окно сообщения.

Как можно добиться такого режима работы, подобного Apache?Я считаю, что решение простое, но у меня нет идеи, с чего начать.

Часть кода, которая следует, используется для вызова службы.Можно ли его изменить, чтобы разрешить автономное использование?

static class Program
{
    /// <summary>
    /// The main entry point for the application.
    /// </summary>
    static void Main()
    {
        ServiceBase[] ServicesToRun;
        ServicesToRun = new ServiceBase[] 
        { 
            new Service() // defined elsewhere as Service : ServiceBase
        };
        ServiceBase.Run(ServicesToRun);
    }
}

Мой язык выбора - C #.

Редактировать: В настоящее время я абстрагировал общий код в отдельную сборку (давайте назовем его Library.dll), и у меня есть два исполняемых файла: Console.exe и Service.exe, которые являются автономными приложениями и приложениями службы Windows, соответственно, и оба являются всего лишь средством для вызова Library.dll.

MyЦель состоит в том, чтобы объединить эти два исполняемых файла в один, который все равно будет вызывать Library.dll.

Ответы [ 4 ]

10 голосов
/ 28 июня 2010

В C # простой способ сделать это - запросить аргумент командной строки, чтобы запустить его как службу.Если аргумента нет, запустите приложение формы / консоли.Затем просто установите ваш установщик в качестве аргумента в пути к исполняемому файлу при установке службы, чтобы он выглядел так:

C:\MyApp\MyApp.exe -service

Это выглядело бы примерно так:Например, чтобы дать вам представление, возможно, есть более понятные способы написания этого кода.

8 голосов
/ 28 июня 2010

После некоторого копания я, наконец, заглянул под капот .NET (метод System.ServiceProcess.ServiceBase.Run), но обнаружил, что он проверяет Environment.UserInteractive bool, чтобы убедиться, что исполняемый файл НЕ выполняется в интерактивном режиме.

Упрощенное решение, которое работает для меня:

class Program
{
    static void Main(string[] args)
    {
        if (!Environment.UserInteractive)
        {
            ServiceBase[] ServicesToRun;
            ServicesToRun = new ServiceBase[] 
            { 
                // Service.OnStart() creates instance of MainLib() 
                // and then calls its MainLib.Start() method
                new Service()
            };
            ServiceBase.Run(ServicesToRun);
            return;
        }

        // Run in a console window
        MainLib lib = new MainLib();
        lib.Start();
        // ...
    }
}
3 голосов
/ 28 июня 2010

Вы действительно должны иметь все свои функциональные возможности, абстрагированные в библиотеке. Тот факт, что он запускается из службы Windows, не имеет значения. На самом деле, если у вас есть класс с именем ServiceFrontEnd, в котором есть Start () и Stop () - это может вызвать приложение службы Windows, а также приложение командной строки, приложение Windows или что-то еще.

То, что вы здесь описываете, просто требует большей абстракции. Функциональность «службы» не должна быть тесно связана с тем, как работает служба Windows. надеюсь, что это поможет

0 голосов
/ 28 июня 2010

В примере с вашим сайтом я уверен, что приложение Apache написано на C или C ++.Для этого вам понадобится функция ServiceMain.Если вы выполняете его как обычную программу, вызывается main.Если вы укажете диспетчеру управления службами, вместо этого будет вызван ServiceMain.

Что касается C #, я не могу сказать, что знаю об этом.Если бы мне пришлось написать сервис на C #, я бы начал здесь - http://msdn.microsoft.com/en-us/library/bb483064.aspx

...