This repo is just documenting building a windows hosted service in .NET 7, the default template was used with Top Level Statements. This configuration seems to work with no Error 1053.
By default, the current directory for your Windows service is the System folder, Not the directory that your .exe is in (C:\Path\To\My\App.exe). We need to bare this in mind when trying to access files with a relative path as the application will look for those files in the system directory and cause an exception that will cause the service to bail on start with Error 1053 or an error while running and if not handled will cost you a great deal of time trying to track it down.
- x64 C:\windows\System32
- x86 C:\Windows\SysWOW64
When you debug your service and everythinhg works as expected but then fails when you deploy the service, consider the above!
In Program.cs set the current directory, this should then point to the directory of your .exe. See this post on StackOverFlow, I can not take credit for these, I have just noted them here to help.
static void Main(string[] args)
{
Directory.SetCurrentDirectory(AppDomain.CurrentDomain.BaseDirectory);
}
- Microsoft.Extensions.Hosting (included in the template)
- Microsoft.Extensions.Hosting.WindowsServices (need to install)
Add UseWindowsService.
.UseWindowsService()
.Build();
Right click the project, select publish and create a publish profile.
Then click Show all settings.
Configuration
- Release | x64Target framework
- net7.0Deployment mode
- Self-containedTarget runtime
- win-x64Target location
- \bin\Release\net7.0\publish\win-x64\
File publish options
-
Produce single file
-
Enable ReadyToRun compilation
-
Trim unused code
The service scripts included in the Scripts directory requires CMD to be run as Administrator
- installservice.cmd
- deleteservice.cmd
- startservice.cmd
- stopservice.cmd
Please update the variables in the scripts to suit your application before you execute them. I have tested them several times and they perform as expected on my system. The scripts are provided for assistance and reference with no guarantee. It is your responsability to check before executing them that they are NOT going to alter or delete any important services on your system.
File installservice.cmd is included in the Scripts directory and requires CMD to be run as Administrator
>cd script_directory
>installservice
@echo OFF
REM Run as Administrator
SET SERVICE_NAME="ANet7DefaultService"
SET SERVICE_DESCRIPTION="Dotnet 7 default service."
SET EXE_NAME="DefaultService.exe"
SET EXE_PATH="D:\repos\DefaultService\DefaultService\bin\Releaseet7.0\publish\win-x64"
SET DISPLAY_NAME="A Default Service"
SET RESTART_MINUTES=1
SET /A SERVICE_RESTART_DELAY=%RESTART_MINUTES%*60000
SET RESET_DAYS=1
SET /A RESET_DELAY=%RESET_DAYS%*86400
REM When altering these commands there should be a required space after = but not before!
REM Create the service
sc.exe create %SERVICE_NAME% binpath= "%EXE_PATH%\\%EXE_NAME%"
IF %ERRORLEVEL% NEQ 0 (Echo "Error creating %SERVICE_NAME% service. " &Exit /b 1)
REM Update the description
sc.exe description %SERVICE_NAME% %SERVICE_DESCRIPTION%
IF %ERRORLEVEL% NEQ 0 (Echo "Error adding description to %SERVICE_NAME% service. " &Exit /b 1)
REM Update config
sc.exe config %SERVICE_NAME% type= own displayname= %DISPLAY_NAME% error= ignore start= auto
IF %ERRORLEVEL% NEQ 0 (Echo "Error updating %SERVICE_NAME% service config options. " &Exit /b 1)
REM Update recovery options
sc.exe Failure %SERVICE_NAME% actions= restart/%SERVICE_RESTART_DELAY%/restart/%SERVICE_RESTART_DELAY%/restart/%SERVICE_RESTART_DELAY%// reset= %RESET_DELAY%
IF %ERRORLEVEL% NEQ 0 (Echo "Error updating %SERVICE_NAME% service recovery options. " &Exit /b 1)
REM Start the service
FOR /F "tokens=3 delims=: " %%H IN ('sc query %SERVICE_NAME% ^| findstr " STATE"') DO (
IF /I "%%H" NEQ "RUNNING" (
NET START %SERVICE_NAME%
IF %ERRORLEVEL% NEQ 0 (Echo "Error starting %SERVICE_NAME% try manual start in services.msc. " &Exit /b 1)
)
)
File deleteservice.cmd is included in the Scripts directory and requires CMD to be run as Administrator
>cd script_directory
>deleteservice
@echo OFF
REM Run as Administrator
REM Stop the service before delete or you will have to reboot for it to be removed
SET SERVICE_NAME="ANet7DefaultService"
ECHO "Trying to stop %SERVICE_NAME%"
REM Stop the service
FOR /F "tokens=3 delims=: " %%H IN ('sc query %SERVICE_NAME% ^| findstr " STATE"') DO (
IF /I "%%H" NEQ "STOPPED" (
NET STOP %SERVICE_NAME%
IF %ERRORLEVEL% NEQ 0 (Echo "Error stopping %SERVICE_NAME% try manual stop in services.msc." &Exit /b 1)
)
)
REM Delete the service
ECHO "Trying to delete %SERVICE_NAME%"
FOR /F "tokens=3 delims=: " %%H IN ('sc query %SERVICE_NAME% ^| findstr " STATE"') DO (
IF /I "%%H" NEQ "RUNNING" (
sc.exe delete %SERVICE_NAME%
IF %ERRORLEVEL% NEQ 0 (Echo "Error deleting %SERVICE_NAME% service." &Exit /b 1)
)
)
File startservice.cmd is included in the Scripts directory and requires CMD to be run as Administrator
>cd script_directory
>startservice
@echo OFF
REM Run as Administrator
SET SERVICE_NAME="ANet7DefaultService"
ECHO "Trying to start %SERVICE_NAME%"
REM Start the service
FOR /F "tokens=3 delims=: " %%H IN ('sc query %SERVICE_NAME% ^| findstr " STATE"') DO (
IF /I "%%H" NEQ "RUNNING" (
NET START %SERVICE_NAME%
IF %ERRORLEVEL% NEQ 0 (Echo "Error starting %SERVICE_NAME% try manual start in services.msc. " &Exit /b 1)
)
)
File stopservice.cmd is included in the Scripts directory and requires CMD to be run as Administrator
>cd script_directory
>stopservice
@echo OFF
REM Run as Administrator
SET SERVICE_NAME="ANet7DefaultService"
REM Stop the service
ECHO "Trying to stop %SERVICE_NAME%"
FOR /F "tokens=3 delims=: " %%H IN ('sc query %SERVICE_NAME% ^| findstr " STATE"') DO (
IF /I "%%H" NEQ "STOPPED" (
NET STOP %SERVICE_NAME%
IF %ERRORLEVEL% NEQ 0 (Echo "Error stopping %SERVICE_NAME% try manual stop in services.msc." &Exit /b 1)
)
)