Требует ли служба .NET Windows вызова ServiceBase.Run () - PullRequest
4 голосов
/ 19 апреля 2011

Я довольно новичок в работе со службами Windows, но обнаружил необычный инцидент, и мне хотелось бы получить некоторые разъяснения. У меня есть служба Windows, написанная на C #, которую я устанавливаю и начинаю использовать командную строку (отличные инструкции можно найти в stackoverflow). Основной метод моего сервиса выглядит так:

    static void Main(string[] args)
    {
        if (args.Length == 0)
        {
            ServiceBase.Run(new MyServiceName());
        }
        else if (args.Length == 1)
        {
            const string name = "MyServiceName";
            Type type = typeof(MyAssembly);
            switch (args[0])
            {
                case "-install":
                    ServiceUtils.InstallService(name, type);
                    ServiceUtils.StartService(args, name);
                    break;
                case "-uninstall":
                    ServiceUtils.StopService(name);
                    ServiceUtils.UninstallService(name, type);
                    break;
                default:
                    throw new NotImplementedException();
            }
        }
    }

Когда я отлаживаю, я ВСЕГДА посылаю один параметр (-install) приложению. Из-за этого первый оператор if (if (args.Length == 0) НИКОГДА не выполняется. Это ожидается, и мой сервис установлен и запущен просто отлично. Тем не менее, если я удаляю оператор if и просто оставляю оператор if (args.Length == 1), моя служба устанавливается правильно, но не запускается, и я получаю следующую ошибку:

Невозможно запустить MyServiceName на компьютере '.'

Мой вопрос: Почему код в первом операторе if необходим, когда он НИКОГДА не выполняется в моем приложении?

Вот вспомогательный код для методов InstallService и StartService (который я также получил от stackoverflow):

    public static void InstallService(string serviceName, Type t)
    {
        if (IsInstalled(serviceName)) return;

        try
        {
            Assembly a = t.Assembly;
            using (AssemblyInstaller installer = GetInstaller(a))
            {
                IDictionary state = new Hashtable();
                try
                {
                    installer.Install(state);
                    installer.Commit(state);
                }
                catch
                {
                    try
                    {
                        installer.Rollback(state);
                    }
                    catch
                    { }
                    throw;
                }
            }
        }
        catch
        {
            throw;
        }
    }

    public static void StartService(string[] args, string serviceName)
    {
        if (!IsInstalled(serviceName)) return;

        Console.WriteLine("Service is installed.  Attempting to start service.");

        ServiceController sc = new ServiceController();
        sc.ServiceName = serviceName;

        if (sc.Status == ServiceControllerStatus.Stopped)
        {
            Console.WriteLine("Starting {0}: ", sc.ServiceName);
            try
            {
                sc.Start(args);
                sc.WaitForStatus(ServiceControllerStatus.Running);
            }
            catch (Exception ex)
            {
                Console.WriteLine(ex.Message);
            }
        }
    }

Ответы [ 3 ]

9 голосов
/ 19 апреля 2011

первый оператор if (if (args.Length == 0) НИКОГДА не выполняется

Это не правильно, выполнено . По ServiceController.Start (). Вы не можете видеть это, потому что сервисный контроллер снова запускает ваш EXE, создавая другой процесс. На этот раз сервисный процесс, а не консольный процесс. Тот, к которому у вас нет отладчика. Если вы удалите это заявление if, то служба сразу же завершает работу после начала работы. И сервисный контроллер правильно жалуется на это с сообщением об исключении «Не удается запустить MyServiceName».

1 голос
/ 19 апреля 2011
if (args.Length == 0)
{            
    ServiceBase.Run(new MyServiceName());
}

запускается, когда служба запускается контроллером службы, так как контроллер службы не передает никаких аргументов в Main ().

Если вы не выполните ServiceBase.Run(new MyServiceName()), то ваша служба не будет реагировать на какие-либо команды от контроллера службы, и вы получите ошибки, подобные тем, которые вы видите.

0 голосов
/ 19 апреля 2011

Main() по-прежнему является точкой входа в приложение.Процесс запускается как отдельный шаг от запуска службы (ей) внутри.

Фактически возможно иметь несколько служб, работающих в одном процессе, и этот способ обработки вещей позволяет это сделать.То есть ... не просто та же самая исполняемая программа, но фактически в том же самом запущенном процессе.

...