Очень часто в Windows необходимо выполнять какие-либо задачи в фоновом режиме, при этом запуск этого процесса не должен зависеть от наличия прав у конкретного пользователя операционной системы. Обычно для этого используют службы.
Создание службы Windows
Файл - Создать проект - Служба Windows
Добавляем в проект класс установщика
Например, нам нужно, чтобы по определенному алгоритму службой обрабатывались файлы в указанной папке. Будем считать, что сам обработчик уже описан в классе SERVICE.FileCheckedProcessor.
Рассмотрим описание класса создаваемой службы.
//#define LOGEVENTS //Включить лог всех событий using System; using System.Collections.Generic; using System.ComponentModel; using System.Data; using System.Diagnostics; using System.Linq; using System.ServiceProcess; using System.Text; using System.Threading; using System.Threading.Tasks; namespace WIN_SERVICE { public partial class WinService : ServiceBase { private Thread workerThread = null; SERVICE.FileCheckedProcessor fileCheckedProcessor = null; public WinService() { InitializeComponent(); fileCheckedProcessor = new SERVICE.FileCheckedProcessor(WIN_SERVICE.Properties.Settings.Default.CheckedPath); fileCheckedProcessor.TEST = WIN_SERVICE.Properties.Settings.Default.TEST; } protected override void OnStart(string[] args) { if ((workerThread == null) || ((workerThread.ThreadState & (System.Threading.ThreadState.Unstarted | System.Threading.ThreadState.Stopped)) != 0)) { #if LOGEVENTS EventLog.WriteEntry("WinService", DateTime.Now.ToLongTimeString() + " - Запускаем вспомогательный поток службы"); #endif workerThread = new Thread(new ThreadStart(ServiceWorkerMethod)); workerThread.Start(); } } protected override void OnStop() { // Завершение работы потока обработки if ((workerThread != null) && (workerThread.IsAlive)) { #if LOGEVENTS EventLog.WriteEntry("WinService", DateTime.Now.ToLongTimeString() + " - Останавливаем вспомогательный поток службы"); #endif Thread.Sleep(5000); workerThread.Abort(); } if (workerThread != null) { #if LOGEVENTS EventLog.WriteEntry("WinService", DateTime.Now.ToLongTimeString() + " - Статус вспомогательного потока службы: " + workerThread.ThreadState.ToString()); #endif } this.ExitCode = 0; } //Поток обработки public void ServiceWorkerMethod() { #if LOGEVENTS EventLog.WriteEntry("WinService", DateTime.Now.ToLongTimeString() + " - Запускаем цикл обработки запросов во вспомогательном потоке службы"); #endif try { do { if (WIN_SERVICE.Properties.Settings.Default.TEST) { EventLog.WriteEntry("WinService", DateTime.Now.ToLongTimeString() + " - Обработка файлов в папке..."); } //Обработка в папке файлов fileCheckedProcessor.Process(); if (WIN_SERVICE.Properties.Settings.Default.TEST) { EventLog.WriteEntry("WinService", DateTime.Now.ToLongTimeString() + " - Обработка файлов выполнена"); } Thread.Sleep(3000); //3 сек пауза перед следующей обработкой #if LOGEVENTS EventLog.WriteEntry("WinService", DateTime.Now.ToLongTimeString() + " - Выполнение работ во вспомогательном потоке службы"); #endif } while (true); } catch (ThreadAbortException exc) { #if LOGEVENTS EventLog.WriteEntry("WinService", DateTime.Now.ToLongTimeString() + " - ThreadAbortException: " + exc.Message); #endif } #if LOGEVENTS EventLog.WriteEntry("WinService", DateTime.Now.ToLongTimeString() + " - Выход из вспомогательного потока службы"); #endif } } }
Класс установщика необходим для установки службы в систему. В нем задаются параметры необходимые для работы службы (название, тип, описание и т.д.).
using System; using System.Collections; using System.Collections.Generic; using System.ComponentModel; using System.Configuration.Install; using System.Linq; using System.ServiceProcess; using System.Threading.Tasks; namespace WIN_SERVICE { [RunInstaller(true)] public partial class WinServiceInstaller : System.Configuration.Install.Installer { ServiceInstaller serviceInstaller; ServiceProcessInstaller processInstaller; public WinServiceInstaller() { InitializeComponent(); serviceInstaller = new ServiceInstaller(); processInstaller = new ServiceProcessInstaller(); processInstaller.Account = ServiceAccount.LocalSystem; serviceInstaller.StartType = ServiceStartMode.Manual; serviceInstaller.ServiceName = "WIN_SERVICE"; serviceInstaller.Description = "Processing files"; Installers.Add(processInstaller); Installers.Add(serviceInstaller); } } }
Установка/удаление службы Windows
Для упрощения процесса установки/удаления создаем bat-файлы. Используем утилиту установщика поставляемую с NetFramework.
install.bat
cd /d %~dp0 %windir%\Microsoft.NET\Framework\v4.0.30319\InstallUtil /i "WIN_SERVICE.exe" pause
uninstall.bat
cd /d %~dp0 %windir%\Microsoft.NET\Framework\v4.0.30319\InstallUtil /u "WIN_SERVICE.exe" pause
Запуск службы Windows
Приложение устанавливается в систему в качестве локальной службы и выполняется вне зависимости от статуса текущего пользователя, запуск службы осуществляется вручную с помощью Service Control Manager (или другими аналогичными способами).
Регистрация событий службы Windows
В локальный системный журнал событий заносятся записи о выполняемых службой операциях (если в коде примера определить LOGEVENTS).