Add Windows service host and system tray controller
All checks were successful
CI / test (push) Successful in 7s
All checks were successful
CI / test (push) Successful in 7s
This commit is contained in:
112
install_backend_service.ps1
Normal file
112
install_backend_service.ps1
Normal file
@@ -0,0 +1,112 @@
|
||||
[CmdletBinding(SupportsShouldProcess = $true)]
|
||||
param(
|
||||
[string]$ServiceName = "ScreenJobBackend",
|
||||
[string]$DisplayName = "ScreenJob Backend",
|
||||
[string]$Description = "Runs the ScreenJob backend (start_backend.ps1) as a Windows service.",
|
||||
[ValidateSet("Automatic", "Manual", "Disabled")]
|
||||
[string]$StartupType = "Automatic",
|
||||
[switch]$DelayedAutoStart,
|
||||
[switch]$ForceReinstall,
|
||||
[switch]$StartAfterInstall
|
||||
)
|
||||
|
||||
Set-StrictMode -Version Latest
|
||||
$ErrorActionPreference = "Stop"
|
||||
|
||||
function Test-IsAdministrator {
|
||||
$identity = [Security.Principal.WindowsIdentity]::GetCurrent()
|
||||
$principal = New-Object Security.Principal.WindowsPrincipal($identity)
|
||||
return $principal.IsInRole([Security.Principal.WindowsBuiltInRole]::Administrator)
|
||||
}
|
||||
|
||||
if (-not (Test-IsAdministrator)) {
|
||||
throw "Run this script from an elevated PowerShell session (Run as Administrator)."
|
||||
}
|
||||
|
||||
$scriptDir = Split-Path -Parent $PSCommandPath
|
||||
$backendScript = Join-Path $scriptDir "start_backend.ps1"
|
||||
if (-not (Test-Path -LiteralPath $backendScript)) {
|
||||
throw "Backend launcher script not found: $backendScript"
|
||||
}
|
||||
|
||||
$projectFile = Join-Path $scriptDir "service_host\ScreenJob.WindowsServiceHost\ScreenJob.WindowsServiceHost.csproj"
|
||||
if (-not (Test-Path -LiteralPath $projectFile)) {
|
||||
throw "Windows service host project not found: $projectFile"
|
||||
}
|
||||
|
||||
$dotnetCmd = Get-Command dotnet -ErrorAction SilentlyContinue
|
||||
if ($null -eq $dotnetCmd) {
|
||||
throw "dotnet SDK was not found in PATH. Install .NET SDK 10+ and retry."
|
||||
}
|
||||
|
||||
$publishDir = Join-Path $scriptDir "service_host\publish"
|
||||
$serviceExe = Join-Path $publishDir "ScreenJob.WindowsServiceHost.exe"
|
||||
$logDir = Join-Path $scriptDir "screenjob_runs\service"
|
||||
|
||||
if ($PSCmdlet.ShouldProcess($projectFile, "Publish Windows service host")) {
|
||||
& $dotnetCmd.Source publish `
|
||||
$projectFile `
|
||||
-c Release `
|
||||
-r win-x64 `
|
||||
--self-contained false `
|
||||
-p:PublishSingleFile=true `
|
||||
-o $publishDir
|
||||
|
||||
if ($LASTEXITCODE -ne 0) {
|
||||
throw "dotnet publish failed with exit code $LASTEXITCODE."
|
||||
}
|
||||
}
|
||||
|
||||
if (-not (Test-Path -LiteralPath $serviceExe)) {
|
||||
throw "Published service executable not found: $serviceExe"
|
||||
}
|
||||
|
||||
$binaryPath = "`"$serviceExe`" --backend-script `"$backendScript`" --working-dir `"$scriptDir`" --log-dir `"$logDir`""
|
||||
|
||||
$existingService = Get-Service -Name $ServiceName -ErrorAction SilentlyContinue
|
||||
if ($null -ne $existingService) {
|
||||
if (-not $ForceReinstall) {
|
||||
throw "Service '$ServiceName' already exists. Re-run with -ForceReinstall to replace it."
|
||||
}
|
||||
|
||||
if ($PSCmdlet.ShouldProcess($ServiceName, "Remove existing service")) {
|
||||
if ($existingService.Status -ne "Stopped") {
|
||||
Stop-Service -Name $ServiceName -Force -ErrorAction Stop
|
||||
}
|
||||
|
||||
& sc.exe delete $ServiceName | Out-Null
|
||||
if ($LASTEXITCODE -ne 0) {
|
||||
throw "Failed to delete existing service '$ServiceName' (sc.exe exit code $LASTEXITCODE)."
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if ($PSCmdlet.ShouldProcess($ServiceName, "Create service")) {
|
||||
New-Service `
|
||||
-Name $ServiceName `
|
||||
-BinaryPathName $binaryPath `
|
||||
-DisplayName $DisplayName `
|
||||
-Description $Description `
|
||||
-StartupType $StartupType
|
||||
|
||||
if ($StartupType -eq "Automatic" -and $DelayedAutoStart) {
|
||||
& sc.exe config $ServiceName start= delayed-auto | Out-Null
|
||||
if ($LASTEXITCODE -ne 0) {
|
||||
throw "Failed to enable delayed auto-start for '$ServiceName' (sc.exe exit code $LASTEXITCODE)."
|
||||
}
|
||||
}
|
||||
|
||||
# Restart on first/second/subsequent failure after 5 seconds.
|
||||
& sc.exe failure $ServiceName reset= 86400 actions= restart/5000/restart/5000/restart/5000 | Out-Null
|
||||
if ($LASTEXITCODE -ne 0) {
|
||||
throw "Failed to configure failure actions for '$ServiceName' (sc.exe exit code $LASTEXITCODE)."
|
||||
}
|
||||
|
||||
if ($StartAfterInstall) {
|
||||
Start-Service -Name $ServiceName -ErrorAction Stop
|
||||
}
|
||||
}
|
||||
|
||||
Write-Host "Service '$ServiceName' installed successfully." -ForegroundColor Green
|
||||
Write-Host "Check status with: Get-Service -Name $ServiceName"
|
||||
Write-Host "View logs in: $logDir"
|
||||
Reference in New Issue
Block a user