# Wird vom Aufgabenplaner bei der Anmeldung gestartet. # # Zwei Aufgaben, in dieser Reihenfolge: # 1. Ein bereitgelegtes Update anwenden. # 2. Die Anwendung starten. # # Warum getrennt: Windows sperrt laufende Programmdateien. Solange node.exe # laeuft, laesst es sich nicht ersetzen. Der Updater legt das neue Paket # deshalb nur unter `pending\` ab; ausgetauscht wird hier, bevor irgendetwas # startet. So gibt es nie einen halb ausgetauschten Ordner. Siehe ADR-0007. $ErrorActionPreference = 'Stop' $root = Split-Path -Parent $MyInvocation.MyCommand.Path $pending = Join-Path $root 'pending' $log = Join-Path $env:LOCALAPPDATA 'abdulive\logs' New-Item -ItemType Directory -Force -Path $log | Out-Null function Write-Log($text) { $line = "{0} {1}" -f (Get-Date -Format 'yyyy-MM-dd HH:mm:ss'), $text Add-Content -Path (Join-Path $log 'starter.log') -Value $line -Encoding utf8 Write-Output $line } # ---------------------------------------------------------------- Update if (Test-Path $pending) { Write-Log 'Update liegt bereit - wende es an.' try { # Sicherheitshalber: laeuft noch etwas aus diesem Ordner? Get-Process node -ErrorAction SilentlyContinue | Where-Object { $_.Path -and $_.Path.StartsWith($root, 'OrdinalIgnoreCase') } | ForEach-Object { Write-Log " beende noch laufende node.exe (PID $($_.Id))" Stop-Process -Id $_.Id -Force } Start-Sleep -Milliseconds 500 foreach ($item in @('app', 'bin', 'fonts', 'node.exe', 'version.json', 'abdulive.cmd', 'launcher.ps1', 'install.ps1', 'backup.ps1')) { $new = Join-Path $pending $item if (-not (Test-Path $new)) { continue } $old = Join-Path $root $item if (Test-Path $old) { Remove-Item -Recurse -Force $old } Move-Item -Path $new -Destination $old } Remove-Item -Recurse -Force $pending $v = (Get-Content (Join-Path $root 'version.json') -Raw | ConvertFrom-Json).version Write-Log "Update angewendet, jetzt Version $v." } catch { # Ein misslungenes Update darf den Stream nicht kosten: der alte # Stand ist noch da, also einfach damit weiterlaufen. Write-Log "Update fehlgeschlagen, starte die vorhandene Version: $_" } } # ---------------------------------------------------------------- Start $node = Join-Path $root 'node.exe' $main = Join-Path $root 'app\apps\cli\main.ts' if (-not (Test-Path $node)) { Write-Log "node.exe fehlt in $root"; exit 1 } # Experimentelle Warnungen abschalten. node:sqlite meldet sich sonst bei # jedem Start auf stderr - im Container stand das in der Dockerfile. $env:NODE_OPTIONS = '--disable-warning=ExperimentalWarning' $aus = Join-Path $log 'abdulive.log' $fehler = Join-Path $log 'abdulive-fehler.log' # Vorherigen Lauf beiseitelegen statt anzuhaengen: Start-Process kann nicht # anhaengen, und ein Protokoll pro Lauf ist beim Suchen ohnehin angenehmer. foreach ($f in @($aus, $fehler)) { if (Test-Path $f) { Move-Item $f "$f.1" -Force } } Write-Log 'Starte den Daemon.' # NICHT `& $node ... 2>&1 | ...` verwenden. Windows PowerShell 5.1 verpackt # jede stderr-Zeile eines nativen Programms in einen ErrorRecord, und mit # $ErrorActionPreference = 'Stop' beendet das sofort das ganze Skript. Der # Daemon schreibt aber im Normalbetrieb Warnungen auf stderr ("Kein # Broadcaster-Token ..."), und genau daran ist er beim ersten Versuch # gestorben - noch bevor eine einzige Zeile im Protokoll stand. $p = Start-Process -FilePath $node -ArgumentList @($main, 'ingest') ` -NoNewWindow -PassThru -Wait ` -RedirectStandardOutput $aus -RedirectStandardError $fehler Write-Log "Daemon beendet (Code $($p.ExitCode))." exit $p.ExitCode