Служба Windows на C#: ещё один пример
Всем доброго времени суток. На связи Алексей Гулынин. В данной статье я бы хотел привести ещё один пример службы Windows на C#. Ранее мы уже писали службу Windows, но это была WCF-служба, т.е. мы ей отправляли запросы и получали ответы. Сейчас же я бы хотел реализовать следующий пример:
Наша служба будет отслеживать количество запусков калькулятора (процесс calc.exe). Результат будет записываться в текстовый файл. Сразу приведу код:
Файл CalcService.cs:
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Configuration.Install; // не забываем добавить ссылку
using System.Diagnostics;
using System.IO;
using System.ServiceProcess; // не забываем добавить ссылку
using System.Text;
using System.Threading;
namespace FileWindowsService
{
// это служебный класс для служб Windows
[RunInstaller(true)]
public class ProjectInstaller : Installer
{
private ServiceProcessInstaller serviceProcess;
private ServiceInstaller serviceInstaller;
public ProjectInstaller()
{
serviceProcess = new ServiceProcessInstaller();
// учетная запись, под которой будет запускаться служба
serviceProcess.Account = ServiceAccount.LocalSystem;
serviceInstaller = new ServiceInstaller();
serviceInstaller.ServiceName = "Отслеживание запуска файла";
serviceInstaller.Description = @"Служба, которая отслеживает запуск исполняемого файла calc.exe (Калькулятор).";
// указываем, чтобы служба запускалась автоматически при запуске рабочей станции
serviceInstaller.StartType = ServiceStartMode.Automatic;
Installers.Add(serviceProcess);
Installers.Add(serviceInstaller);
}
}
class CalcService
{
// количество запусков службы
private static int count = 0;
// будем помещать id процесса в массив, чтобы не учитывать процессы с
// одинаковым id несколько раз
public static List<int> oldProcsID = new List<int>();
//
public static void CalcProcess(Object o)
{
// Получаем все процессы calc.exe
Process[] procs = Process.GetProcessesByName("calc");
foreach (Process proc in procs)
{
// Если данного процесса нет в нашем массиве
if (!oldProcsID.Contains(proc.Id))
{
count++;
writeInfoToFile("Количество запусков процесса: " + count.ToString() + " | ID процесса: {1}" + proc.Id.ToString() + Environment.NewLine);
// Добавляем процесс
oldProcsID.Add(proc.Id);
}
}
}
public static void CheckIDsCalcProcess(Object o)
{
Process[] allProcs = Process.GetProcesses();
foreach (int procID in oldProcsID.ToArray())
{
bool isDelete = true;
foreach (Process proc in allProcs)
{
if (proc.Id == procID)
{
isDelete = false;
}
}
if (isDelete) oldProcsID.Remove(procID);
}
}
// запись данных в файл
private static void writeInfoToFile(string info)
{
using (StreamWriter sw = new StreamWriter(@"C:\calc.txt", true, Encoding.Unicode))
{
sw.WriteLine(info);
}
}
}
// Наша служба Windows
public partial class WindowsService : ServiceBase
{
Timer t;
Timer t1;
// Запуск службы
protected override void OnStart(string[] args)
{
t = new Timer(CalcService.CalcProcess, null, 0, 2000);
t1 = new Timer(CalcService.CheckIDsCalcProcess, null, 0, 15000);
}
// Остановка службы
protected override void OnStop()
{
t = null;
t1 = null;
}
}
}
Файл Program.cs:
using System.ServiceProcess;
namespace FileWindowsService
{
class Program
{
// В данном методе запускается наша служба
static void Main(string[] args)
{
ServiceBase[] ServicesToRun;
ServicesToRun = new ServiceBase[]
{
new WindowsService()
};
ServiceBase.Run(ServicesToRun);
}
}
}
Метод CheckIDsCalcProcess(), который выполняется раз в 15 секунд, делает следующее:
Он сравнивает содержимое списка oldProcsID со всеми текущими процессами. Если в списке есть id процесса, которого нет во всех процессах, то данный id удаляется из списка.
Далее нам необходимо корректно установить службу. Приведу содержимое двух бат-файлов для установки и удаления службы. После выполнения данных команд необходимо зайти в службы Windows и запустить нашу службу.
Файл InstallService.bat:
C:\Windows\Microsoft.NET\Framework\v4.0.30319\installutil.exe FileWindowsService.exe
Файл UninstallService.bat:
C:\Windows\Microsoft.NET\Framework\v4.0.30319\installUtil.exe /u FileWindowsService.exe
Мы видим, что служба успешно запустилась:

Давайте теперь протестируем работу службы. Запустите несколько процессов калькулятора. После этого у нас на диске C создастся файл calc.txt:

Мы видим, что всё работает.
У нашей службы есть один недостаток, который сразу бросается в глаза. Каждый раз при загрузке компьютера, служба будет заново стартовать, при этом переменная count будет равна 0. Чтобы этого избежать значение переменной count можно записывать в текстовый файл или базу данных, и при старте службы переменной count присваивать это значение.
В данной статье мы реализовали ещё один пример службы Windows на C#.
На связи был Алексей Гулынин, оставляйте свои комментарии, увидимся в следующих статьях.




