Картинка блога

В Visual Studio есть шаблон для создания сервисов. Проблема в том, что запустится они могут только с помощью SVCUTIL, а это отнимает время на сопровождение (обычный F5 гораздо удобней и быстрее). Еще возникают неудобства с отладкой — конечно, Debugger.Launch() никто не отменял, но эти 5 секунд хлопанья по окошкам для подключения программы к студии быстро достают. Это простой пример того, как запустить службу как консоль. Сразу скажу, что это не работает Mono из-за некорректного значения в UserInteractive:

using System;
using System.Collections.Generic;
using System.Linq;
using System.ServiceProcess;
using System.Text;
using System.Reflection;
using System.Diagnostics;

namespace Proj.ServiceProcess
{
static class ServiceProgram
{
/// <summary>
/// The main entry point for the application.
/// </summary>
static void Main(string[] args)
{
ServiceBase[] servicesToRun = new ServiceBase[]
			{
				new MyServiceProcess()
			};

if (Environment.UserInteractive)
{
Type type = typeof(ServiceBase);
BindingFlags flags = BindingFlags.Instance | BindingFlags.NonPublic;
MethodInfo method = type.GetMethod("OnStart", flags);

foreach (ServiceBase service in servicesToRun)
{
method.Invoke(service, new object[] { args });
}

Console.WriteLine("Press any key to exit");
Console.ReadLine();

foreach (ServiceBase service in servicesToRun)
{
service.Stop();
}

}
else
{
ServiceBase.Run(servicesToRun);
}
}
}
}

Код предпологает, что MyServiceProcess это класс вашей службы.

Метки:, ,

5 комментариев в “C#: Запуск Windows сервисов как консольных приложений”

  1. this will work in mono:

    try
    {
    ServiceBase.Run(servicesToRun);
    }
    catch (Win32Exception)
    {
    Type type = typeof(ServiceBase);BindingFlags flags = BindingFlags.Instance | BindingFlags.NonPublic;MethodInfo method = type.GetMethod(«OnStart», flags);
    ….
    }

  2. кстати так
    foreach (ServiceBase service in servicesToRun)
    {
    service.Stop();
    }
    возникает исключение.
    я сделал
    MethodInfo methodStop = type.GetMethod(«OnStop», flags);
    foreach (ServiceBase service in servicesToRun)
    {
    methodStop.Invoke(service, null);
    }

  3. Интересующийся
    28 августа, 2012 at 10:10

    День добрый. Воспользовался данным методом. Все замечательно. Но. На нашей вин-службе хостится еще WCF сервис. И этот WCF сервис отправляет команды службе..

    ServiceController sc = ServiceController.GetServices().Where(e => e.ServiceName == "SchoolAccessControl").Single();
    sc.ExecuteCommand(160);

    И вот в следствии того, что вин-служба запущена как консоль, то она не находится в списке служб в методе GetService().
    Так вот как ее найти, чтобы можно было выполнить команду?

    Заранее спасибо!

  4. Если сервис не запущен, то очевидно что Вы его не найдете. 🙂
    Я бы сделал еще какой-нибудь способ доступа и обернул его и вызов «sc.ExecuteCommand» общим интерфейсом. Например, для этого можно использовать NamedPipe. Если это скучно и долго, то всегда можно использовать Debug.Attach() (по крайне мере для отладки комманд).

    Вообще ServiceController.ExecuteCommand кажется мне не очень удачным решением, возвращаемый тип void, а это серьезное ограничение.

  5. Как подключить using System.ServiceProcess; а то у меня студия (2010) ругается