Запуск PowerShell скрипта як служби Windows

З будь-якого скрипта PowerShell можна зробити службу Windows, яка працює у фоновому режимі і запускається автоматично при завантаженні сервера. Ви можете створити службу Windows за допомогою утиліт srvany.exe і instsrv.exe (зі складу Windows Server Resource 2003 Kit), що дозволяють запустити процес powershell.exe з параметром у вигляді шляху до ps1 файлу скрипта. Основний недолік такого способу створення служби - srvany.exe не контролює виконання програми (скрипта PowerShell в нашому випадку) і, якщо додаток падає (зависає), то служба це не бачить і продовжує працювати. У цій статті для створення служби Windows з файлу зі скриптом PowerShell ми будемо використовувати утиліту NSSM (Non-Sucking Service Manager - залишимо без перекладу ... :)), яка позбавлена ​​цих недоліків.

Ви можете завантажити і встановити NSSM вручну або через Chocolately. Спочатку потрібно встановити сам Choco:

Set-ExecutionPolicy Bypass -Scope Process -Force; '
iex ((New-Object System.Net.WebClient) .DownloadString ( 'https://chocolatey.org/install.ps1'))

Потім встановимо пакет NSSM:

choco install nssm

У цьому прикладі ми будемо в реальному часі відстежувати зміни певної групи AD (скрипт з цієї статті) і при зміні сповіщати адміністратора безпеки спливаючих повідомленням і листом.

Отже, у нас є код, який потрібно зберегти в PS1 файл. Додамо нескінченний цикл, який раз у хвилину виконує перевірку:

while ($ true)
# Ваш PS код
Start-Sleep -Seconds 60

Звичайно, для реалізації подібного сценарію можна створити і завдання в планувальнику (Task Scheduler), але якщо вам потрібно реагувати на будь-які зміни в реальному часі, метод з окремою службою набагато правильніше.

Створити службу з скрипта PowerShell за допомогою NSSM можна прямо з PowerShell :):

$ NSSMPath = (Get-Command "C: \ tools \ nssm \ win64 \ nssm.exe"). Source
$ NewServiceName = "CheckADGroupSrv"
$ PoShPath = (Get-Command powershell) .Source
$ PoShScriptPath = "C: \ tools \ CheckADGroup \ checkad.ps1"
$ Args = '-ExecutionPolicy Bypass -NoProfile -File "0"' -f $ PoShScriptPath
& $ NSSMPath install $ NewServiceName $ PoShPath $ args
& $ NSSMPath status $ NewServiceName

Запустимо нову службу:

Start-Service $ NewServiceName

Перевіримо статус служби за допомогою PowerShell:

Get-Service $ NewServiceName

Отже, ви створили і запустили нову службу Windows. Перевіримо, що вона з'явилася в консолі управління службами services.msc

Служба CheckADGroupSrv дійсно з'явилася, вона налаштована на автоматичний запус і в даний момент запущена (Running). Як ви бачите, ваш PowerShell скрипт запущений всередині процесу nssm.exe.

Зверніть увагу, що служба запущена з-під облікового запису System. Якщо ви використовуєте в своїх PS скриптах інші модулі (в моєму випадку для отримання складу доменної групи безпеки використовується командлет Get-ADGroupMember з модуля Active Directory для Windows PowerShell), цей акаунт повинен мати доступ до файлів модуля і права на підключення до AD (в моєму випадку). Ви так само можете запустити цю служби під інший обліковим записом (або аккаунтом gMSA) і надати користувачам права на зупинку / перезапуск служби, якщо у них немає прав локального адміністратора.

Щоб служба могла відображати повідомлення в сеанс користувача (взаємодіяти з робочим столом) потрібно на вкладці "Вхід у систему"(Log on) включити опцію"Дозволити взаємодію з робочим столом"(Allow service to interact with desktop).

Щоб це працювало в Windows 10 / Windows Server 2012 R2 / 2016 потрібно змінити значення DWORD параметра реєстру NoInteractiveServices в гілці HKLM \ System \ CurrentControlSet \ Control \ Windows на 0 і включити службу оглядача інтерактивних служб (Interactive Services Detection Service):

Start-Service -Name ui0detect

Однак в Windows 10 1803 службу Interactive Services Detection Service повністю прибрали з системи, і ви більше не можете переключитися в нульову сесію (Session 0), так що ви просто не побачите вікна, які виводяться з-під аккаунта System.

Ви можете змінити опис служби командою:

& $ NSSMPath set $ NewServiceName description "Моніторинг змін групи AD"

Щоб видалити створену службу можете скористатися командою sc delete або

nssm remove CheckADGroupSrv