Службы в Windows — особые процессы, выполняемые в фоновом режиме, в том числе от учетной записи «СИСТЕМА», которые могут быть запущены в том числе до входа в систему. При желании вы можете создать свою собственную службу, которая будет работать таким же образом.
В этой инструкции подробно о том, как создать службу в Windows 11 или Windows 10 средствами системы, ограничениях методов и одном дополнительном способе заставить работать ваш процесс в качестве службы.
Создание службы в командной строке
Первый способ — использование команды командной строки для создания своей службы, шаги будут следующими:
- Запустите командную строку от имени Администратора (способы запуска командной строки от Администратора).
- Используйте команду, заменив текстовые описания и пути на свои:
sc create Имя_службы binPath="C:\service-file.exe" DisplayName= "Описание_службы" type=own start=auto
- После нажатия Enter вы получите сообщение: CreateService: успех, что означает, что служба была успешно создана.
В указанной команде используются следующие параметры:
- binPath — путь к исполняемому файлу службы.
- DisplayName — отображаемое в списке служб имя службы.
- start — тип запуска, возможные значения: boot, auto, demand (значение по умолчанию), disabled, delayed-auto
- type — тип службы, по умолчанию own, возможны другие значения: share (делит исполняемый файл с другими службами), kernel (драйвер), filesys (драйвер файловой системы), interact (интерактивная служба с возможность взаимодействия с пользователем, поддержка этого типа служб прекращается).
После создания службы вы сможете увидеть её в списке служб (Win+R — services.msc), а автоматический запуск произойдет при следующей перезагрузке системы.
Создание службы в Windows PowerShell
Создать службу можно и в PowerShell, запущенном от имени администратора (или в Терминале Windows). Базовый вариант команды с параметрами по умолчанию:
New-Service -Name "Имя_Службы" -BinaryPathName '"C:\путь_к_файлу параметры_запуска"'
Расширенный вариант с указанием описания и типа запуска:
New-Service -Name MyService -BinaryPathName '"C:\путь_к_файлу параметры_запуска"' -DisplayName "Имя_службы" -Description "Описание службы" -StartupType "Automatic"
В случае, если выполняется запуск исполняемого файла без параметров, а путь не содержит пробелов, использование кавычек не обязательно, например:
-BinaryPathName C:\remontka.exe
При создании служб в PowerShell доступны и ряд дополнительных параметров, описанных в официальной справке на сайте Майкрософт.
Удаление созданной службы
Удалить созданную службы вы можете также в командной строке, запущенной от имени Администратора с помощью команды:
sc delete Имя_службы
Или в Windows PowerShell:
Remove-Service -Name MyService
После выполнения указанных команд созданная вами служба будет удалена из Windows.
Созданная служба не работает, варианты решения
Из описания можно предположить, что любой файл .exe может быть службой, однако, при попытке добавить свои фоновые утилиты и заставить их работать в виде службы рядовые пользователи обычно сталкиваются с ситуацией, когда процесс запускается, а затем закрывается сам. А при запуске службы вручную через некоторое время сообщает, что служба не ответила на запрос своевременно или о других ошибках.
Причина в том, что исполняемые файлы служб — не совсем обычные программы, они, помимо прочего, обмениваются данными с системой. Если ваш EXE не отвечает на соответствующие запросы системы, Windows «делает вывод» о том, что со службой что-то не так.
Как быть, если вы всё-таки настойчиво хотите использовать свой прикладной исполняемый файл в качестве службы?
- Использовать планировщик заданий и запуск от соответствующего пользователя — это не будет в полной мере службой, но почти то, что нужно.
- Ранее существовала программа RunAsSvc, позволяющая запускать любые процессы в качестве службы, но для современных ОC он не применима, а разработка была прекращена.
- Использовать инструменты INSTSRV.EXE и SRVANY.EXE из Windows Server 2003 Resource Kit Tools при создании службы Windows.
Создание пользовательской службы с помощью INSTSRV.EXE и SRVANY.EXE
Последний вариант из приведённого выше списка рассмотрим подробнее. Шаги будут следующими:
- Загрузите (вероятнее всего, придется найти в Интернете на сторонних сайтах) Windows Server 2003 Resource Kit полностью или только файлы INSTSRV.EXE и SRVANY.EXE, располагаем их у себя на диске, в моем примере путь — C:\Windows
- В командной строке от имени администратора используйте команду (пути меняем на свои):
C:\Windows\instsrv.exe Имя_службы C:\Windows\srvany.exe
- Если вы получили сообщение о том, что The service was successfully added, всё прошло успешно. Теперь требуется запустить редактор реестра (Win+R — regedit).
- В редакторе реестра перейдите по пути
HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Services\
и найдите раздел с вашим именем службы. Нажимаем по нему правой кнопкой мыши и выбираем пункт «Создать» — «Раздел», задаем имя «Parameters» для раздела.
- Выберите созданный раздел, нажмите правой кнопкой мыши в правой панели редактора реестра и создайте новый строковый параметр с именем Application
- Дважды нажмите по параметру и в поле «Значение» укажите путь к вашему файлу exe для запуска службы.
Закройте редактор реестра — служба создана, её можно запустить из services.msc или она будет автоматически запущена после перезагрузки компьютера.
Учитывайте, что во всех приведенных примерах служба по умолчанию запускается с учетной записью «СИСТЕМА». В некоторых случаях это может приводить к неправильной работе. В этом случае может иметь смысл зайти в свойства службы в services.msc и изменить параметры на вкладке «Вход в систему».
July 21, 2023
1 min read
views 2838
Engineering
.Net
In this tutorial, we will walk through the steps to create and deploy a Windows Service using Visual Studio. A Windows Service program operates in the background and starts automatically when your computer boots up. They are ideal for use in server environments or when you need a program that runs continuously, even if no one is logged into the system.
Step 1: Creating a New Windows Service Project
Fire up your Visual Studio and go to File > New > Project. In the ‘New Project’ dialog box, search for ‘Windows Service’ and select ‘Windows Service (.NET Framework)’ template.
public class MyWindowsService : ServiceBase
{
public MyWindowsService()
{
this.ServiceName = "My Windows Service";
}
}
This creates a basic service with no functionality. You would override the ‘OnStart’ and ‘OnStop’ methods to add functionality.
Step 2: Implementing the OnStart and OnStop Methods
The ‘OnStart’ method is called when the service starts, and the ‘OnStop’ method is called when the service stops.
protected override void OnStart(string[] args)
{
// TODO: Add code here to start your service.
}
protected override void OnStop()
{
// TODO: Add code here to perform any tear-down necessary to stop your service.
}
Step 3: Building and Installing the Windows Service
After adding functionality to your service, it’s time to install it. First, build the service by clicking on Build > Build Solution. Then, open the Developer Command Prompt for VS and navigate to the directory containing your project’s output files.
cd path\to\project\bin\Debug
installutil MyWindowsService.exe
This will install your service on the local machine. You can view your service by opening the Services management console (services.msc).
Step 4: Deploying the Windows Service
Deploying the service to another machine involves copying the executable and using InstallUtil on the target machine. Alternatively, you can create a setup project in Visual Studio to handle the installation process.
If you’re looking for experienced .NET developers for your project, consider hiring .NET remote developers.
Search code, repositories, users, issues, pull requests…
Provide feedback
Saved searches
Use saved searches to filter your results more quickly
Sign up
Время на прочтение
6 мин
Количество просмотров 66K
Однажды вы задумаетесь, как превратить скрипт или приложение в Windows-службу. Скорее всего, задача окажется не такой уж тривиальной – приложению как минимум потребуется специальный интерфейс для получения команд от системы. А раз есть требования и ограничения, то есть и скрипты, и милые сердцу костылики для преодоления.
Статья будет полезна тем, кто, как и я — «программист не настоящий».
Зачем нужна служба, если есть назначенные задания
В отличие от назначенных заданий служба работает постоянно, запускается при старте ПК и может управляться средствами Windows. А еще регулярно запускаемому скрипту могут понадобиться данные с предыдущего запуска, и может быть полезно получение данных из внешних источников — например, в случае TCP или Web сервера.
Лично мне за последние пять лет приходилось создавать службу три с половиной раза:
- Потребовалось создать сервис на fail2ban для Windows 2003., который работал с логами FileZilla и Apache, а при подозрении на брутфорс блокировал IP штатными средствами Windows — ipsec.
- Аналог телнет-сервера для домашних версий Windows. Понадобилось выполнять команды на удаленных рабочих станциях, которые были под управлением Windows 7 Home. По сути, вторая попытка поиграть в службы.
- Музыкальный проигрыватель для торгового зала под Windows. Задачу по ТЗ можно было решить при помощи mpd и пачки скриптов, но я решил — если уж делать скрипты, то почему бы и не «сваять» проигрыватель самому. За основу взял библиотеку BASS.dll.
- Когда выбирали веб-сервер с поддержкой загрузки файлов под Windows, одним из вариантов был HFS. Сам по себе работать он не может, поэтому пришлось «запихивать» его в службу. В результате решение не понравилось, и просто установили «тему» Apaxy на web-сервере Apache.
Для создания службы можно использовать взрослые языки программирования вроде C. Но если вы не хотите связываться с Visual Studio, то возьмите готовые утилиты. Существуют платные решения вроде FireDaemon Pro или AlwaysUp, но мы традиционно сосредоточимся на бесплатных.
Способ первый. От Microsoft
Этот уже немолодой механизм состоит из двух компонентов: утилиты instsrv.exe для установки сервиса и srvany.exe — процесса для запуска любых исполняемых файлов. Предположим, что мы создали веб-сервер на PowerShell при помощи модуля Polaris. Скрипт будет предельно прост:
New-PolarisGetRoute -Path '/helloworld' -Scriptblock {
$Response.Send('Hello World!')
}
Start-Polaris -Port 8080
while($true) {
Start-Sleep -Milliseconds 10
}
Работа так называемого «сервера».
Теперь попробуем превратить скрипт в службу. Для этого скачаем Windows Resource Kit Tools, где будут наши утилиты. Начнем с того, что установим пустой сервис командой:
instsrv WebServ C:\temp\rktools\srvany.exe
Где WebServ — имя нашего нового сервиса. При необходимости через оснастку services.msc можно задать пользователя, под которым будет запускаться служба, и разрешить взаимодействие с рабочим столом.
Теперь пропишем путь к нашему скрипту при помощи магии реестра. Параметры службы есть в разделе реестра HKLM\SYSTEM\CurrentControlSet\Services\WebServ. В нем нам нужно добавить новый раздел Parameters и создать там строковый параметр Application, указав в нем путь к исполняемому файлу. В случае скрипта PowerShell он будет выглядеть так:
C:\Windows\System32\WindowsPowerShell\v1.0\powershell.exe -ExecutionPolicy Bypass -NoProfile -File C:\temp\Polaris\server.ps1
Настроенная служба.
Можно запустить и радоваться.
Работающая служба.
Однако у этого способа есть недостатки:
- Утилиты старые, разработаны до изобретения PowerShell, UAC и прочих вещей.
- Srvany не контролирует работу приложения. Даже если оно выпадет в ошибку, служба продолжит свое дело как ни в чем не бывало.
- Придется донастраивать и копаться в реестре. Вы же помните, что копаться в реестре небезопасно?
Поэтому перейдем к методу, частично лишенному этих проблем.
Способ второй, почти взрослый
Существует утилита под названием NSSM — Non-Sucking Service Manager, что можно перевести как не-плохой менеджер служб. В отличие от предыдущей, она поддерживается разработчиком, и исходный код опубликован на сайте. Помимо обычного способа, доступна и установка через пакетный менеджер Chocolately.
Создать сервис можно из обычной командной строки, вооружившись документацией на сайте разработчика. Но мы воспользуемся PowerShell. Потому что можем, разумеется.
$nssm = (Get-Command ./nssm).Source
$serviceName = 'WebServ'
$powershell = (Get-Command powershell).Source
$scriptPath = 'C:\temp\Polaris\server.ps1'
$arguments = '-ExecutionPolicy Bypass -NoProfile -File "{0}"' -f $scriptPath
& $nssm install $serviceName $powershell $arguments
& $nssm status $serviceName
Start-Service $serviceName
Get-Service $serviceName
Установка через PowerShell.
Для разнообразия проверим работу службы не браузером, а тоже через PowerShell командой Invoke-RestMethod.
И вправду работает.
В отличие от srvany, этот метод позволяет перезапускать приложение на старте, перенаправлять stdin и stdout и многое другое. В частности, если не хочется писать команды в командную строку, то достаточно запустить GUI и ввести необходимые параметры через удобный интерфейс.
GUI запускается командой:
nssm.exe install ServiceName
Настроить можно даже приоритет и использование ядер процессора.
Действительно, возможностей куда больше, чем у srvany и ряда других аналогов. Из минусов бросается в глаза недостаточный контроль над всем процессом.
Налицо нехватка «жести». Поэтому я перейду к самому хардкорному методу из всех опробованных.
Способ третий. AutoIT
Поскольку я давний любитель этого скриптового языка, то не смог пройти мимо библиотеки под названием _Services_UDF v4. Она снабжена богатой документацией и примерами, поэтому под спойлером сразу приведу полный текст получившегося скрипта.
Листинг скрипта
Итак, попробуем «завернуть» в нее наш веб-сервис:
#NoTrayIcon
#RequireAdmin
#Region
#AutoIt3Wrapper_Version=Beta
#AutoIt3Wrapper_UseUpx=n
#AutoIt3Wrapper_Compile_Both=y
#AutoIt3Wrapper_UseX64=y
#EndRegion
Dim $MainLog = @ScriptDir & "\test_service.log"
#include <services.au3>
#include <WindowsConstants.au3>
$sServiceName="WebServ"
If $cmdline[0] > 0 Then
Switch $cmdline[1]
Case "install", "-i", "/i"
InstallService()
Case "remove", "-u", "/u", "uninstall"
RemoveService()
Case Else
ConsoleWrite(" - - - Help - - - " & @CRLF)
ConsoleWrite("params : " & @CRLF)
ConsoleWrite(" -i : install service" & @CRLF)
ConsoleWrite(" -u : remove service" & @CRLF)
ConsoleWrite(" - - - - - - - - " & @CRLF)
Exit
EndSwitch
Else
_Service_init($sServiceName)
Exit
EndIf
Func _main($iArg, $sArgs)
If Not _Service_ReportStatus($SERVICE_RUNNING, $NO_ERROR, 0) Then
_Service_ReportStatus($SERVICE_STOPPED, _WinAPI_GetLastError(), 0)
Exit
EndIf
$bServiceRunning = True
$PID=Run("C:\Windows\System32\WindowsPowerShell\v1.0\powershell.exe -ExecutionPolicy Bypass -NoProfile -File C:\temp\Polaris\server.ps1")
While $bServiceRunning
_sleep(1000)
WEnd
ProcessClose($PID)
_Service_ReportStatus($SERVICE_STOP_PENDING, $NO_ERROR, 1000)
DllCallbackFree($tServiceMain)
DllCallbackFree($tServiceCtrl)
_Service_ReportStatus($SERVICE_STOPPED, $NO_ERROR, 0)
DllClose($hAdvapi32_DLL)
DllClose($hKernel32_DLL)
EndFunc
Func _Sleep($delay)
Local $result = DllCall($hKernel32_DLL, "none", "Sleep", "dword", $delay)
EndFunc
Func InstallService()
#RequireAdmin
Local $bDebug = True
If $cmdline[0] > 1 Then
$sServiceName = $cmdline[2]
EndIf
If $bDebug Then ConsoleWrite("InstallService("&$sServiceName &"): Installing service, please wait")
_Service_Create($sServiceName, $sServiceName, $SERVICE_WIN32_OWN_PROCESS, $SERVICE_AUTO_START, $SERVICE_ERROR_SEVERE, '"' & @ScriptFullPath & '"');,"",False,"","NT AUTHORITY\NetworkService")
If @error Then
Msgbox("","","InstallService(): Problem installing service, Error number is " & @error & @CRLF & " message : " & _WinAPI_GetLastErrorMessage())
Else
If $bDebug Then ConsoleWrite("InstallService(): Installation of service successful")
EndIf
Exit
EndFunc
Func RemoveService()
_Service_Stop($sServiceName)
_Service_Delete($sServiceName)
If Not @error Then
EndIf
Exit
EndFunc
Func _exit()
_Service_ReportStatus($SERVICE_STOPPED, $NO_ERROR, 0);
EndFunc
Func StopTimer()
_Service_ReportStatus($SERVICE_STOP_PENDING, $NO_ERROR, $iServiceCounter)
$iServiceCounter += -100
EndFunc
Func _Stopping()
_Service_ReportStatus($SERVICE_STOP_PENDING, $NO_ERROR, 3000)
EndFunc
Разберу подробнее момент запуска приложения. Он начинается после операции $bServiceRunning = True и превращается в, казалось бы, бесконечный цикл. На самом деле этот процесс прервется, как только служба получит сигнал о завершении — будь то выход из системы или остановка вручную.
Поскольку программа для скрипта является внешней (powershell.exe), то после выхода из цикла нам нужно закончить ее работу с помощью ProcessClose.
Для этого скрипт необходимо скомпилировать в .exe, а затем установить службу, запустив exe с ключом -i.
Оно работает!
Разумеется, этот способ не самый удобный, и все дополнительные возможности придется реализовывать самостоятельно, будь то повторный запуск приложения при сбое или ротация логов. Но зато он дает полный контроль над происходящим. Да и сделать в итоге можно куда больше — от уведомления в Telegram о сбое службы до IPC-взаимодействия с другими программами. И вдобавок — на скриптовом языке, без установки и изучения Visual Studio.
Расскажите, а вам приходилось превращать скрипты и приложения в службы?
Sometimes you need an app or script to keep running whether you’re logged into your computer or not. Maybe it’s a PowerShell script to monitor ports or a web server hosting a page on your home network.
The point is that if you want a process, script, or program to run as long as the computer is on, you’ll need to create a Windows Service.
What Do I Need to Create a Windows Service?
To create a Windows service in Windows 10, there are a few prerequisites:
- Administrator access on the computer
- Something to run as a service (PowerShell Script, program, etc.)
- Non-Sucking Service Manager (NSSM) installed
What Is the Non-Sucking Service Manager?
Yes, you can’t drop a name like that without explaining it. Sure the name is unfortunate, yet it is accurate. The Non-Sucking Service Manager (NSSM) is arguably the easiest way to create a Windows service that is both highly reliable and configurable. Plus, it’s free and Open Source Software (OSS).
NSSM can be used through the Windows Command Prompt, or a graphical user interface (GUI). This means anyone can use it. NSSM can be used on any version of Windows going back to, and including, Windows 2000. There are 32-bit and 64-bit versions. If you’re using a 64-bit computer, try that version first. If it doesn’t work, fall back to the 32-bit version.
You can download NSSM from the website, clone NSSM from Git, or install NSSM with Chocolatey. Chocolatey is a package manager for Windows. Installation methods will vary depending on which route you take. Please consult NSSM’s instructions. For our example, we’re downloading from the NSSM website and installing it in C:\WINDOWS\system32.
Create a Windows Service With NSSM
For this example, we’ll create a service out of a PowerShell script to log CPU average load percentage.
- Copy and save this script as log-CPULoadPercentage.ps1 to a place that’s not likely to be accessed by anyone else. Try creating the directory C:/Scripts and storing it there. Also, create a folder in Scripts called Logs. Note that the path to the script is C:/Scripts/log-CPULoadPercentage.ps1. You’ll need that later.
Note: All lines below followed by the # symbol are comments and won’t affect the script.
CLS #Optional. I like to use this to clear the terminal when testing. #Make sure you have a folder called Logs in the same directory as this script #The log is where the records will be stored. Start-Transcript -Path "$PSScriptRoot\Logs\log-CPULoadPercentage-$(get-date -f yyyy-MM-dd).txt" -Append #While loop keeps it running until manually stopped While ($True){ #Creates a timestamp to know when the measurement was taken $timeStamp = get-date -f yyyy-MM-h:mm:ss #Gets the average load percentage at that time, then waits 5 seconds to do it again. $cpuLoadPercent = Get-CimInstance win32_processor | Measure-Object -Property LoadPercentage -Average | Select-Object Average;Start-Sleep -Seconds 5 #Isolates just the average so there isn't a weird @{Average=13} string $cpuLoadPercent = $cpuLoadPercent.Average #writes results to screen, or in this case to the log Write-Host "$timeStamp CPU Load Percentage $cpuLoadPercent" } Stop-Transcript
- This can be done in either the Windows Command Prompt or PowerShell. Open it as Administrator.
- Enter the command nssm install logCPUAvg and run it. The NSSM service installer window will open.
- Click on the ellipses button next to the Path: field, navigate to the powershell.exe that’s normally located at C:\Windows\System32\. Select powershell.exe. The Path: and Startup directory: fields will be automatically populated.
- Enter the following in the Arguments: field: -ExecutionPolicy Bypass -NoProfile -File “C:\PathToScript\get-Script.ps1”, where the last part is the path to your PowerShell script and the script name.
- Select the Details tab. Enter what you’d like the service to show up as in the Windows Services manager into the Display name: field. Then, enter what it does in the Description: field. The Startup type: can be set as Automatic, Automatic (Delayed Start), Manual, or Disabled. For this exercise, Automatic is good.
- Select the Log on tab. Select This account: radio button and enter the account and password that the service will run as. You’ll need to choose an account under which the service will run. Ideally, you’ll have a Windows account created just for running this service. This account’s permissions should be limited to only what the service needs to do. You can choose the Local System account, but it’s not recommended for security reasons.
There are several other tabs that can be used to customize the service. For this exercise, the default values in those tabs are sufficient. Select the Install service button.
- When the service is installed, you’ll see the Service “logCPUAvg” installed successfully! window. Select OK to close it. That concludes the installation.
- Open the Windows Services Manager and ensure the service is there.
- Run the service to ensure it will run.
- To verify that this service is running, use File Explorer to navigate to where the log is supposed to be saved to see if it exists.
nssm-check-log.png
Removing a Windows Service With NSSM
Maybe you don’t need to monitor your CPU load anymore, so you’d like to get rid of the service. Fortunately, NSSM makes that easy.
- In the Windows Services Manager, stop the service. Do this by selecting the Log CPU Average Load service then either selecting the square stop button in the toolbar or the Stop the service link on the left side.
- Open either the Windows Command Prompt or PowerShell as Administrator.
- Enter the command nssm remove logCPUAvg and execute the command.
- NSSM will ask you to confirm. Select Yes.
- When the service is removed, you’ll see the Service “logCPUAvg” removed successfully! Confirmation. Select OK and you’re done.
That’s all. It’s a good idea to check the services manager to ensure the service is no longer there. If you still see the service, you may need to refresh the screen and it should be gone.
Services are a great way to run apps or scripts that need to run all the time, restart themselves if they fail, or need privileges different from the current user. If you don’t need your app or script to do all of those things, consider using a Scheduled Task instead.