Очень часто в 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).