Службы Windows это удобный способ запускать и контролировать программы, выполняемые на заднем плане. Они часто используются в больших приложениях или как альтернатива консоли или Form приложения, которое можно спрятать в трей. Сегодня я попробую объединить все идеи и наработки касательно сервисов и консольных приложений, используемые мной за время моего «молчания» лета.
Для начала, о консоли
- Не пишите логику в методе Main — рано или поздно ее все равно нужно будет перенести в собственный класс.
- Не надо парсить входящие параметры в ручную. Не изобретайте велосипед, используйте готовое, например NDesk.Options.
- Если вы делаете консоль, вместо Console.ReadLine используйте getline.cs от Мигеля де Икаса. При наличии достаточно интереса я покажу как красиво объединить его с номером два.
Теперь о службе
- Есть достаточно техник послать консоль на задний фон, возможно вам и не нужна служба.
- Вы все еще можете читать параметры командной строки с помощью Environment.CommandLine. Используйте его, например для задания имени службы.
- Только для Windows: Свойство Environment.UserInteractive всегда false в службах и true — в консольных приложениях. Готовый пример тут.
- С помощью ServiecInstaller класса можно настроить автостарт службы и учетную запись, под которой он должен работать.
И еще,
Не используйте Console.WriteLine в коде
Дело в том, что когда вы начнете переносить приложение в Формы или Службу, от этого потока нужно будет избавится или перенаправить в другое место.
- Создать собственное статическое свойство типа ITextWriter в возвращать Console.Out. Это простой но не действенный способ, так как если возвращать поток пишущий в файл, он не позволяет контролировать открытие и закрытие файла а также сброс буфера.
- Сделать свой интерфейс (ILoggger или IMyWriter) с нужными методами. Это, наверно, самый популярный способ. Требует немного больше времени чем первый, но позволяет контролировать процесс на нужном уровне.
- Использовать готовую библиотеку — Будь то log4net или System.Diagnostics. Тут, думаю, все понятно. Настроить такие библиотеки обычно можно из конфигурации, также, есть возможность контролировать уровень важности и фильтр.
Что, если запустить службу в Linux?
Mono окружение обладает рядом особенностей работы со службой. Несмотря на то, что «запускалка» сервисов в Mono есть, я вообще отказался от служб в кросс-платформанных приложениях. Дело в том, что в mono-service нет одной мелочи, переключения на новый сборщик мусора. А это ведет к утечкам, при использовании .NET 4.0. Тут есть выход, так как в Linux еще больше способов послать консоль в фон, чем в Windows. 🙂
Как лочить выполнение с возможностью остановки?
Как вариант, можно сделать lock на основе файла:
#region FileLock private static FileSystemWatcher watcher; private static string watchFilename; public static void LockByFile(string filename = "lock") { if (File.Exists(filename)) File.Delete(filename); File.WriteAllText(filename, ""); watchFilename = filename; watcher = new FileSystemWatcher(Environment.CurrentDirectory); watcher.Deleted += watcher_Deleted; watcher.Renamed += watcher_Renamed; watcher.EnableRaisingEvents = true; log.Warn("to unlock: Delete file - " + filename); while (!String.IsNullOrEmpty(watchFilename)) Thread.Sleep(800); } private static void watcher_Renamed(object sender, RenamedEventArgs e) { if (!File.Exists(watchFilename)) watchFilename = null; } static void watcher_Deleted(object sender, FileSystemEventArgs e) { if (e.Name == watchFilename) watchFilename = null; } #endregion
Скрипт для запуска службы
Вот так выглядит .bat файл, который я даю вместе с программой, которая будет запускаться на Windows в качестве службы:
::
@ECHO OFF
echo :: This script will install and start
echo :: [YourProgram] service
rem set UTIL=C:\WINDOWS\Microsoft.NET\Framework\v2.0.50727\InstallUtil.exe
set UTIL=C:\Windows\Microsoft.NET\Framework\v4.0.30319\InstallUtil.exe
set NAME=Program.exe
cd %~dp0
%UTIL% %NAME% /ShowCallStack
echo :: If service started: (if not, you are probably not under Administrator rights)
echo :: Press [Enter] to stop and uninstall it.
echo :: Press [Ctrl+C] to leave it in the service table.
pause
%UTIL% %NAME% /u BioStarSimpleConnector.exe
Метки:C#, разработка, OpenSource
Похожие статьи
- 15 сентября 2011 -- C#: Запуск Windows сервисов как консольных приложений (5)
- 8 марта 2011 -- C#: Silverlight таймаут (Timeout) (2)
- 12 января 2012 -- Генерация строк перебором букв. (4)
- 30 июля 2010 -- DLR 1.0 на примере IronPython 2.6 (0)
- 18 декабря 2008 -- Транслитерация RUS 2 LAT на C# (22)