#Requires -RunAsAdministrator <# .SYNOPSIS Registriert das Holzleitner-Backend als Windows-Dienst "Holzleitner Backend". .DESCRIPTION Muss als Administrator ausgeführt werden. Erwartet die kompilierte EXE (Default: neben diesem Skript) und eine config.toml IM SELBEN Verzeichnis wie die EXE (der Dienst setzt sein Arbeitsverzeichnis auf das EXE-Verzeichnis, daher werden config.toml, data/ und logs/ relativ zur EXE aufgelöst). Release-Build erzeugen: cargo build --release -p holzleitner-api Die EXE liegt dann unter target\release\holzleitner-server.exe. .PARAMETER ExePath Pfad zu holzleitner-server.exe. Default: neben diesem Skript. .PARAMETER Credential Optionales Dienstkonto. Ohne Angabe läuft der Dienst als LocalSystem. Für Zugriff auf Postgres/Keycloak/ERPframe-MSSQL/GSD im Netzwerk ist oft ein echtes Domänen-/Benutzerkonto nötig. Das Konto braucht das Recht "Als Dienst anmelden". .EXAMPLE .\install-service.ps1 .EXAMPLE .\install-service.ps1 -ExePath "C:\HolzleitnerBackend\holzleitner-server.exe" -Credential (Get-Credential) #> [CmdletBinding()] param( [string]$ExePath, [string]$ServiceName = "HolzleitnerBackend", [string]$DisplayName = "Holzleitner Backend", [pscredential]$Credential ) $ErrorActionPreference = 'Stop' $ScriptDir = Split-Path -Parent $MyInvocation.MyCommand.Definition if (-not $ExePath) { $ExePath = Join-Path $ScriptDir 'holzleitner-server.exe' } if (-not (Test-Path $ExePath)) { throw "EXE nicht gefunden: $ExePath (zuerst 'cargo build --release -p holzleitner-api' und die EXE aus target\release\ neben dieses Skript kopieren)" } $ExePath = (Resolve-Path $ExePath).Path $ExeDir = Split-Path $ExePath -Parent if (-not (Test-Path (Join-Path $ExeDir 'config.toml'))) { Write-Warning "config.toml fehlt neben der EXE ($ExeDir) - der Dienst startet sonst nicht (cp config.example.toml config.toml)." } # Vorhandenen Dienst stoppen & entfernen (Neuinstallation) $existing = Get-Service -Name $ServiceName -ErrorAction SilentlyContinue if ($existing) { Write-Host "Dienst '$ServiceName' existiert bereits - stoppe & entferne..." if ($existing.Status -ne 'Stopped') { Stop-Service -Name $ServiceName -Force } & sc.exe delete $ServiceName | Out-Null Start-Sleep -Seconds 2 } # binPath in doppelten Quotes (Pfad kann Leerzeichen enthalten) $bin = "`"$ExePath`"" $params = @{ Name = $ServiceName DisplayName = $DisplayName BinaryPathName = $bin StartupType = 'Automatic' Description = 'HTTP-Backend der Holzleitner-Lieferservice-App (REST-API, ERP-Sync, Lieferreports). Bindet standardmaessig auf den in config.toml gesetzten Port.' } if ($Credential) { $params['Credential'] = $Credential } Write-Host "Registriere Dienst '$DisplayName' ($ServiceName) -> $ExePath" New-Service @params | Out-Null # Auto-Restart bei Absturz: 3x mit 60s Abstand, Fehlerzaehler nach 1 Tag zuruecksetzen & sc.exe failure $ServiceName reset= 86400 actions= restart/60000/restart/60000/restart/60000 | Out-Null # Verzoegerter Autostart (startet nach den System-Diensten, z. B. nach der DB) & sc.exe config $ServiceName start= delayed-auto | Out-Null Write-Host "Starte Dienst..." Start-Service -Name $ServiceName Start-Sleep -Seconds 1 Get-Service -Name $ServiceName | Format-List Name, DisplayName, Status, StartType Write-Host "Config: $(Join-Path $ExeDir 'config.toml')" Write-Host "Logs: $(Join-Path $ExeDir 'logs')" Write-Host "Fertig."