Служба 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#.
На связи был Алексей Гулынин, оставляйте свои комментарии, увидимся в следующих статьях.