Удобная разработка Windows Service с TopShelf

TopShelf - это инструмент для тестирования сервиса как консольного приложения. Чаще всего от сервиса данные можно получить только через лог, а TopShelfпозволяет выводить данные в консоль, даже не устанавливая сервис

Более подробная документация на официальном сайте.

http://topshelf.readthedocs.org/en/latest/configuration/quickstart.html

1. Создаем консольное приложение TopShelfTest

2. Проект - управление пакетами NuGet
3. Ищем в поиске и устанавливаем

4. Установим Nlog (напрямую к TopShelf он не относится, просто удобен)
Nlog.config поменем на

<?xml version="1.0" encoding="utf-8" ?>
<nlog xmlns="http://www.nlog-project.org/schemas/NLog.xsd"
      xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
      xsi:schemaLocation="http://www.nlog-project.org/schemas/NLog.xsd NLog.xsd"
      autoReload="true"
      throwExceptions="false"
      internalLogLevel="Off" internalLogFile="c:\temp\nlog-internal.log" >


  <!-- optional, add some variabeles
  https://github.com/nlog/NLog/wiki/Configuration-file#variables
  -->
  <variable name="myvar" value="myvalue"/>

  <!-- 
  See https://github.com/nlog/nlog/wiki/Configuration-file 
  for information on customizing logging rules and outputs.
   -->
  <targets>

    <!-- 
    add your targets here 
    See https://github.com/nlog/NLog/wiki/Targets for possible targets.
    See https://github.com/nlog/NLog/wiki/Layout-Renderers for the possible layout renderers.
    -->
    <target name="console" xsi:type="Console" layout="${date:format=HH\:mm\:ss}|${level}|${message}" />
    <target name="file"
        xsi:type="File"
        fileName="${basedir}/logs/Log.${level}.current.txt"
        layout="${longdate} ${callsite} ${level}: ${message} ${exception:format=Message,StackTrace} ${stacktrace}"
        archiveFileName="${basedir}/logs/archives/log.error.${shortdate}.{#}.txt"
        archiveAboveSize="5242880"
        archiveEvery="Day"
        archiveNumbering = "Rolling"
        maxArchiveFiles="3" />
    <!--
    Writing events to the a file with the date in the filename. 
    <target xsi:type="File" name="f" fileName="${basedir}/logs/${shortdate}.log"
            layout="${longdate} ${uppercase:${level}} ${message}" />
    -->
  </targets>

  <rules>
    <!-- add your logging rules here -->
    <logger name="*" minlevel="Debug" writeTo="file" />
    <logger name="*" minlevel="Trace" writeTo="console" />
    <!--
    Write all events with minimal level of Debug (So Debug, Info, Warn, Error and Fatal, but not Trace)  to "f"
    <logger name="*" minlevel="Debug" writeTo="f" />
    -->
  </rules>
</nlog>

5. Program.cs должно принять следующий вид

using System;
//----------
using System.Timers;
using Topshelf;
using NLog;

namespace TopShelfTest
{
    public class TownCrier
    {
        private static Logger logger = LogManager.GetCurrentClassLogger(); //log
        readonly Timer _timer;
        public TownCrier()
        {
            _timer = new Timer(1000) { AutoReset = true };
            _timer.Elapsed += (sender, eventArgs) => Console.WriteLine("It is {0} and all is well", DateTime.Now);

        }
        public void Start()
        {
            _timer.Start();
            logger.Trace("Start at {0}", DateTime.Now);
        }
        public void Stop()
        {
            _timer.Stop();
            logger.Debug("Stop at {0}", DateTime.Now);
        }
    }

    class Program
    {
        static void Main(string[] args)
        {
            HostFactory.Run(x =>                               //1
            {

                x.Service<TownCrier>(s =>                      //2
                {
                    s.ConstructUsing(name => new TownCrier()); //3
                    s.WhenStarted(tc => tc.Start());           //4 
                    s.WhenStopped(tc => tc.Stop());            //5
                });
                x.RunAsLocalSystem();                          //6

                x.SetDescription("Sample Topshelf Host");      //7
                x.SetDisplayName("Stuff");                     //8
                x.SetServiceName("Stuff");                     //9
            });                                                //10
        }
    }
}

Можно запускать.

1. Здесь мы настроили хост с помощью HostFactory.Run. Мы открываем новое лямбда выражение, где «х» в этом случае включает все конфигурации уровня хоста. Используя этот метод  аргументы извлекаются из переменных окружения.
2. Здесь мы говорим, что Topshelf есть сервис типа "TownCrier". Лямбда выражение получает конфигурацию службы с помощью параметра 's'.
3. Это говорит Topshelf как построить экземпляр службы. В настоящее время мы только собираемся инициализировать его, но мы могли бы так же легко вытащить его из контейнера IoC с каким-то кодом, который будет выглядеть примерно так "container.GetInstance <TownCrier> () ' 
4. Как Topshelf запускает службу
5. Как Topshelf останавливает службу
6. Здесь мы настроили запуск службы как локальной. Мы также можем настроить это из командной строки в интерактивном режиме 
7. Здесь мы создаем описание для WinService  
8. Здесь мы создаем отображаемое имя для WinService
9.  Здесь мы создаем имя для WinService
10. Теперь, когда лямбда выражение закрылось, конфигурация будет использована для запуска сервиса
---
Пару слов про NLog
logger.Trace("Start at {0}", DateTime.Now);   - запись будет в консоль
logger.Debug("Stop at {0}", DateTime.Now);  - запись будет в папку logs

1 способ применим при консольном тестировании, 2 подходит при запуске в качестве службы

Установить приложение как службу можно из папки с service.exe командой
service.exe install


Удалить - командой
service.exe uninstall

исходники


Популярные сообщения из этого блога

Пишем логи на C# (.NET). Легкий способ.

Авторизация yii 2 из базы

Средства для работы с базой данный PostgreSql