90 lines
3.7 KiB
PowerShell
90 lines
3.7 KiB
PowerShell
# Beendet alle laufenden Prozesse dieses Projekts (Electron, Node/Vite, und
|
|
# einen verwaisten lokalen Input-Helper-Kindprozess), bevor eine neue Instanz
|
|
# startet.
|
|
#
|
|
# Warum das noetig ist: Ein normales Schliessen der App (X-Button) raeumt
|
|
# sauber auf (main.ts: app.on("will-quit") beendet den gespawnten
|
|
# input-helper.ps1-Kindprozess). Wird die App aber gewaltsam beendet - z.B.
|
|
# ueber Task-Manager "Task beenden" oder ein Skript, das Stop-Process -Force
|
|
# auf den Electron-Prozess anwendet - greift dieser Cleanup-Handler NICHT,
|
|
# und der Kindprozess (PowerShell mit dem Input-Helper) bleibt als Waise
|
|
# aktiv, obwohl das Hauptfenster laengst weg ist. Dieses Skript faengt genau
|
|
# das ab: es wird vor JEDEM Start (npm run dev und npm run dev:admin, ueber
|
|
# den "predev"-Hook) ausgefuehrt und raeumt vorherige Instanzen kompromisslos
|
|
# weg, egal wie sie beendet wurden.
|
|
|
|
$ErrorActionPreference = "Stop"
|
|
$project = (Resolve-Path -LiteralPath (Join-Path $PSScriptRoot "..")).Path
|
|
$electronPath = Join-Path $project "node_modules\electron\dist\electron.exe"
|
|
$devControlPort = 17317
|
|
|
|
$killed = 0
|
|
$candidatePids = @{}
|
|
|
|
try {
|
|
$health = Invoke-RestMethod -Method Get -Uri "http://127.0.0.1:$devControlPort/health" -TimeoutSec 2 -ErrorAction Stop
|
|
if ($health.appBuild -and $health.appBuild.cwd -eq $project) {
|
|
Write-Host "Dev-Control-Port $devControlPort gehoert zu diesem Projekt (PID $($health.appBuild.pid), Signatur $($health.appBuild.signature)). Versuche Self-Shutdown..."
|
|
try {
|
|
Invoke-RestMethod -Method Get -Uri "http://127.0.0.1:$devControlPort/dev/shutdown?reason=restart" -TimeoutSec 2 -ErrorAction Stop | Out-Null
|
|
Start-Sleep -Milliseconds 900
|
|
} catch {
|
|
Write-Host "Self-Shutdown nicht verfuegbar oder fehlgeschlagen: $($_.Exception.Message)" -ForegroundColor Yellow
|
|
}
|
|
}
|
|
} catch {
|
|
# No dev-control server or an older/stuck process; continue with process scan.
|
|
}
|
|
|
|
Get-CimInstance Win32_Process |
|
|
Where-Object {
|
|
($_.Name -eq "electron.exe" -and $_.ExecutablePath -eq $electronPath) -or
|
|
($_.Name -eq "node.exe" -and $_.CommandLine -like "*$project*") -or
|
|
($_.Name -eq "powershell.exe" -and $_.CommandLine -like "*input-helper.ps1*")
|
|
} |
|
|
ForEach-Object {
|
|
$candidatePids[[int]$_.ProcessId] = $_.Name
|
|
}
|
|
|
|
try {
|
|
Get-NetTCPConnection -LocalPort $devControlPort -State Listen -ErrorAction Stop |
|
|
ForEach-Object {
|
|
if ($_.OwningProcess -gt 0) {
|
|
$owner = Get-Process -Id $_.OwningProcess -ErrorAction SilentlyContinue
|
|
$candidatePids[[int]$_.OwningProcess] = if ($owner) { "$($owner.ProcessName) port $devControlPort" } else { "port $devControlPort owner" }
|
|
}
|
|
}
|
|
} catch {
|
|
# Get-NetTCPConnection can be unavailable on some machines; process matching
|
|
# above still handles the normal non-elevated path.
|
|
}
|
|
|
|
$failed = 0
|
|
foreach ($entry in $candidatePids.GetEnumerator()) {
|
|
Write-Host "Beende alte Instanz: $($entry.Value) (PID $($entry.Key))"
|
|
try {
|
|
Stop-Process -Id $entry.Key -Force -ErrorAction Stop
|
|
$killed++
|
|
} catch {
|
|
Write-Host "WARNUNG: Konnte PID $($entry.Key) nicht beenden: $($_.Exception.Message)" -ForegroundColor Yellow
|
|
$failed++
|
|
}
|
|
}
|
|
|
|
if ($killed -gt 0) {
|
|
# Windows braucht einen Moment, um Ports/Handles wirklich freizugeben.
|
|
Start-Sleep -Milliseconds 500
|
|
Write-Host "$killed alte Prozess(e) beendet."
|
|
}
|
|
|
|
if ($failed -gt 0) {
|
|
Write-Host "$failed alte Prozess(e) konnten nicht beendet werden. Wenn das ein Admin-Prozess ist, starte npm run dev:admin und bestaetige UAC oder schliesse die alte App manuell." -ForegroundColor Yellow
|
|
throw "$failed alte Prozess(e) konnten nicht beendet werden."
|
|
}
|
|
|
|
if ($killed -eq 0 -and $failed -eq 0) {
|
|
Write-Host "Keine alten Instanzen gefunden."
|
|
} else {
|
|
Start-Sleep -Milliseconds 300
|
|
}
|