Службы Windows В C#



Предисловие Службы в Windows управляют практически всем: от поддержания самой системы на плаву до служб родительского контроля.

В диспетчере задач есть инструмент для их просмотра и остановки/запуска, не говоря уже об отдельной утилите, встроенной в Windows. Но что, если вам нужно встроить такой инструмент в свою программу? Где я могу получить всю эту информацию? Как управлять услугами? Расскажу, как я это сделал на C# и с какими трудностями столкнулся.



Как это все началось
Я начинающий разработчик приложений на C#.

Точнее, я был новичком около года назад. Сейчас я думаю, что если очень захотеть, то смогу разработать довольно сложные вещи.

Ну, мы не об этом говорим.

В общем, мне нужно было создать утилиту, которая правильно будет отображать и обладать самым необходимым функционалом для управления сервисами.

Что-то вроде существующей функции в диспетчере окон.



Как все было нарисовано
Богатством интерфейс не грозил и я решил остановиться на панели инструментов и списке, в котором будут отображаться сервисы.

В качестве последнего был выбран DataGridView, поскольку он отображает информацию в виде столбцов, что для меня было очень удобно, а также имеет некоторые удобства для пользователей (сортировка, например).

На панели инструментов было около 6 кнопок, управляющих выбранными сервисами.

На этапе отрисовки интерфейса не возникло никаких сложностей, и он был успешно выполнен всего за несколько часов.



Как все разрабатывалось
Ну, во-первых, нужны были два механизма: первый, который бы находил все зарегистрированные на данной машине сервисы и информацию о них, и второй, который бы корректно вносил все это в DataGridView. Со вторым проблем быть не должно.

А вот с первым мне пришлось побороться (и как оказалось, это была самая сложная часть разработки).

Подробнее о нем.

По задумке, о каждом сервисе в системе необходимо было найти следующую информацию: имя, не имя системы, а имя пользователя; Описание услуг; ее состояние; тип запуска; путь к файлу и под чьим именем он был запущен.

С именем проблем не возникло — DisplayName из класса ServiceController отображал его очень корректно.

Статус тоже не представляет особой сложности — очень помогло свойство Status из того же класса.

Но чтобы узнать, кто запустил службу, какой это был тип запуска и где находится образ, нам уже пришлось залезть в реестр.

Тоже в принципе ничего особо сложного, но сидеть пришлось дольше, чем на предыдущих атрибутах.



Как все стало сложнее
Как оказалось в итоге, камнем преткновения стало описание сервиса, понятное пользователю.

Начав искать способы его получения, я понял, что ни ServiceController, ни даже реестр не могут дать нормального описания.

Часто в реестре в строке «Описание» стоит ссылка на библиотеку dll и номер строки, в которой находится описание службы в этой библиотеке.

А так как C# пока не умеет динамически брать информацию из dll, то каждый раз при обновлении списка приходилось искать в реестре, брать там ссылку и номер строки, идти в библиотеку, загружать, искать строку , скопируйте описание и выгрузите библиотеку обратно.

Как и ожидалось, это ужасно сказалось на производительности.

Первый запуск такой скромной программы занимает около 5 секунд (хотя последующие обновления производятся довольно быстро).



Как это закончилось
Всё остальное (управление, отображение информации в DataGrid, удобство пользователя в виде возврата фокуса и сортировки на место после обновления списка и т.д.) было достаточно простым.

Путем проб и ошибок (и бесконечного шуршания в Интернете) всего этого удалось добиться.

В результате утилита оказалась достаточно удобной и некоторые даже согласились использовать ее в качестве тестовой вместо стандартного сервиса в диспетчере задач.

Вот скриншот работающей программы

Службы Windows в C#

Код (даже основная часть) довольно объёмный, вот часть про поиск описательной информации: val = targetKey.GetValue("Описание"); если (значение == ноль) строка[1] = ""; // Без описания еще { строка s = (строка) val; Соответствие m = Regex.Match(s, @"^[@](?(.

*))\s*-(?(\d*))"); if (m.Success) // Проверяем, является ли строка ссылкой на ресурс { строка w1 = m.Groups[“путь”].

Value; // Путь к dll // Заменяем системную переменную %SystemRoot% в пути (если есть) строка w2 = Regex.Replace(w1, @"%SystemRoot%|%windir%", SystemRootPath, RegexOptions.IgnoreCase); // Заменяем системную переменную %ProgramFiles% в пути (если есть) строка DllPath = Regex.Replace(w2, @"%ProgramFiles%", ProgramFilesPath, RegexOptions.IgnoreCase); int ID = Convert.ToInt32(m.Groups["id"].

Value); // Идентификатор ресурса // Загружаем необходимую dll IntPtr hndl = DllInterop.LoadLibrary(DllPath); // Получаем описание row[1] = DllInterop.LoadStringDll(hndl, ID); // Выгружаем dll DllInterop.FreeLibrary(hndl); } еще строка[1] = с; P.S. Думаю (практически уверен), что «хардкорные» разработчики и программисты не найдут для себя ничего нового, но для людей, ранее не работавших с Windows-сервисами на C#, думаю, будет познавательно.

Если вам нужны какие-то части кода или даже сама программа, то обращайтесь к нам, мы будем очень рады помочь.

Теги: #C++ #Чулан #службы Windows

Вместе с данным постом часто просматривают:

Автор Статьи


Зарегистрирован: 2019-12-10 15:07:06
Баллов опыта: 0
Всего постов на сайте: 0
Всего комментарий на сайте: 0
Dima Manisha

Dima Manisha

Эксперт Wmlog. Профессиональный веб-мастер, SEO-специалист, дизайнер, маркетолог и интернет-предприниматель.