210 lines
7.9 KiB
PowerShell
210 lines
7.9 KiB
PowerShell
param(
|
|
[string]$ProjectRoot = ""
|
|
)
|
|
|
|
$ErrorActionPreference = "SilentlyContinue"
|
|
|
|
if ([string]::IsNullOrWhiteSpace($ProjectRoot)) {
|
|
$ProjectRoot = (Resolve-Path (Join-Path $PSScriptRoot "..\..")).Path
|
|
} else {
|
|
$ProjectRoot = (Resolve-Path $ProjectRoot).Path
|
|
}
|
|
|
|
$toolDir = Join-Path $ProjectRoot "tools\oem-batch-builder"
|
|
$activeRunPath = Join-Path $toolDir "active-run.json"
|
|
$runsDir = Join-Path $toolDir "runs"
|
|
$currentPid = $PID
|
|
$killed = New-Object System.Collections.Generic.List[int]
|
|
|
|
function Write-CleanupLog([string]$Message) {
|
|
$stamp = Get-Date -Format "yyyy-MM-dd HH:mm:ss"
|
|
Write-Output "[$stamp] $Message"
|
|
}
|
|
|
|
function Write-JsonNoBom($Path, $Value) {
|
|
$json = $Value | ConvertTo-Json -Depth 10
|
|
$utf8NoBom = New-Object System.Text.UTF8Encoding($false)
|
|
[System.IO.File]::WriteAllText($Path, $json, $utf8NoBom)
|
|
}
|
|
|
|
function Get-ProcByPid([int]$ProcId) {
|
|
Get-CimInstance Win32_Process -Filter "ProcessId=$ProcId"
|
|
}
|
|
|
|
function Test-IsProjectBuildProcess($Proc) {
|
|
if (-not $Proc) { return $false }
|
|
if ([int]$Proc.ProcessId -eq [int]$currentPid) { return $false }
|
|
|
|
$name = [string]$Proc.Name
|
|
$cmd = [string]$Proc.CommandLine
|
|
$exe = [string]$Proc.ExecutablePath
|
|
$text = "$cmd`n$exe"
|
|
$lower = $text.ToLowerInvariant()
|
|
$rootLower = $ProjectRoot.ToLowerInvariant()
|
|
|
|
if ($name -ieq "OEMBatchBuilderTool.exe") { return $false }
|
|
|
|
if ($lower.Contains("tools\oem-batch-builder\worker.cjs")) { return $true }
|
|
if ($lower.Contains("tools\oem-batch-builder\main.cjs")) { return $true }
|
|
if ($lower.Contains("electron-builder") -and $lower.Contains("--win") -and $lower.Contains("--x64")) { return $true }
|
|
if ($lower.Contains("npm.cmd run build:win") -or $lower.Contains("npm run build:win")) { return $true }
|
|
|
|
if (-not $lower.Contains($rootLower)) {
|
|
return $false
|
|
}
|
|
|
|
if ($lower.Contains("\dist-release-final\")) { return $true }
|
|
if ($lower.Contains("\build\oem-batch-temp\")) { return $true }
|
|
if ($lower.Contains("dist-release-final\win-unpacked")) { return $true }
|
|
if ($lower.Contains("node_modules\.bin\electron-builder")) { return $true }
|
|
if ($lower.Contains("electron-builder.cmd")) { return $true }
|
|
if ($lower.Contains("electron-builder --win")) { return $true }
|
|
if ($lower.Contains("npm.cmd run build:win")) { return $true }
|
|
if ($lower.Contains("npm run build:win")) { return $true }
|
|
if ($lower.Contains("npm.cmd run prepare-package")) { return $true }
|
|
if ($lower.Contains("npm run prepare-package")) { return $true }
|
|
if ($lower.Contains("npm.cmd run build")) { return $true }
|
|
if ($lower.Contains("npm run build")) { return $true }
|
|
if ($lower.Contains("vite build")) { return $true }
|
|
if ($lower.Contains("apply-oem.cjs")) { return $true }
|
|
if ($lower.Contains("scripts\prepare-package.cjs")) { return $true }
|
|
if ($lower.Contains("scripts\build-resource-artifacts.cjs")) { return $true }
|
|
if ($lower.Contains("scripts\fix-latest-yml.cjs")) { return $true }
|
|
if ($lower.Contains("scripts\assemble-release-artifacts.cjs")) { return $true }
|
|
if ($lower.Contains("scripts\clean-build-artifacts.cjs")) { return $true }
|
|
|
|
return $false
|
|
}
|
|
|
|
function Test-IsWorkerPidProcess($Proc) {
|
|
if (-not $Proc) { return $false }
|
|
$cmd = ([string]$Proc.CommandLine).ToLowerInvariant()
|
|
return $cmd.Contains("tools\oem-batch-builder\worker.cjs")
|
|
}
|
|
|
|
function Test-ToolInstanceIsAlive() {
|
|
$instances = @(Get-CimInstance Win32_Process | Where-Object {
|
|
if (-not $_) { return $false }
|
|
if ([int]$_.ProcessId -eq [int]$currentPid) { return $false }
|
|
if ([string]$_.Name -ine "OEMBatchBuilderTool.exe") { return $false }
|
|
$cmd = ([string]$_.CommandLine).ToLowerInvariant()
|
|
$cmd.Contains("tools\oem-batch-builder")
|
|
})
|
|
if ($instances.Count -gt 0) {
|
|
$ids = ($instances | ForEach-Object { $_.ProcessId }) -join ","
|
|
Write-CleanupLog "OEM batch builder is already running. Skip cleanup and let single-instance focus it. PIDs=$ids"
|
|
return $true
|
|
}
|
|
return $false
|
|
}
|
|
|
|
function Test-ActiveWorkerIsAlive() {
|
|
if (-not (Test-Path $activeRunPath)) { return $false }
|
|
try {
|
|
$active = Get-Content -Path $activeRunPath -Raw -Encoding UTF8 | ConvertFrom-Json
|
|
if (-not $active.running) { return $false }
|
|
|
|
$candidatePids = New-Object System.Collections.Generic.List[int]
|
|
if ($active.pid) { $candidatePids.Add([int]$active.pid) | Out-Null }
|
|
if ($active.sessionDir) {
|
|
$workerPidPath = Join-Path ([string]$active.sessionDir) "worker.pid"
|
|
if (Test-Path $workerPidPath) {
|
|
$pidText = (Get-Content -Path $workerPidPath -Raw).Trim()
|
|
if ($pidText -match "^\d+$") { $candidatePids.Add([int]$pidText) | Out-Null }
|
|
}
|
|
}
|
|
|
|
foreach ($candidatePid in $candidatePids) {
|
|
$proc = Get-ProcByPid $candidatePid
|
|
if ($proc -and (Test-IsWorkerPidProcess $proc)) {
|
|
Write-CleanupLog "Active OEM build is still running. Skip cleanup. PID=$candidatePid Session=$($active.sessionDir)"
|
|
return $true
|
|
}
|
|
}
|
|
} catch {
|
|
Write-CleanupLog "Failed to inspect active-run.json: $($_.Exception.Message)"
|
|
}
|
|
return $false
|
|
}
|
|
|
|
function Stop-Tree([int]$ProcId, [string]$Reason, [bool]$WorkerPidOnly = $false) {
|
|
if ($ProcId -le 0 -or $ProcId -eq $currentPid) { return }
|
|
if ($killed.Contains($ProcId)) { return }
|
|
|
|
$proc = Get-ProcByPid $ProcId
|
|
if (-not $proc) { return }
|
|
if ($WorkerPidOnly -and -not (Test-IsWorkerPidProcess $proc)) {
|
|
Write-CleanupLog "Skip PID $ProcId ($($proc.Name)): $Reason points to a non-worker process"
|
|
return
|
|
}
|
|
if (-not (Test-IsProjectBuildProcess $proc)) { return }
|
|
|
|
Write-CleanupLog "Killing PID $ProcId ($($proc.Name)): $Reason"
|
|
& taskkill.exe /F /T /PID $ProcId | Out-Null
|
|
$killed.Add($ProcId) | Out-Null
|
|
}
|
|
|
|
function Stop-ActiveRunState([string]$Message) {
|
|
if (-not (Test-Path $activeRunPath)) { return }
|
|
try {
|
|
$state = Get-Content -Path $activeRunPath -Raw -Encoding UTF8 | ConvertFrom-Json
|
|
if ($state.running -or $killed.Count -gt 0) {
|
|
$state | Add-Member -NotePropertyName "running" -NotePropertyValue $false -Force
|
|
$state | Add-Member -NotePropertyName "stoppedAt" -NotePropertyValue ((Get-Date).ToUniversalTime().ToString("o")) -Force
|
|
$state | Add-Member -NotePropertyName "message" -NotePropertyValue $Message -Force
|
|
Write-JsonNoBom $activeRunPath $state
|
|
Write-CleanupLog "Marked active-run stopped: $Message"
|
|
}
|
|
} catch {
|
|
Write-CleanupLog "Failed to update active-run.json: $($_.Exception.Message)"
|
|
}
|
|
}
|
|
|
|
Write-CleanupLog "Cleanup started. ProjectRoot=$ProjectRoot"
|
|
|
|
if (Test-ToolInstanceIsAlive) {
|
|
Write-CleanupLog "Cleanup skipped because the tool process is alive."
|
|
exit 0
|
|
}
|
|
|
|
if (Test-ActiveWorkerIsAlive) {
|
|
Write-CleanupLog "Cleanup skipped because an active worker is alive."
|
|
exit 0
|
|
}
|
|
|
|
if (Test-Path $activeRunPath) {
|
|
try {
|
|
$active = Get-Content -Path $activeRunPath -Raw -Encoding UTF8 | ConvertFrom-Json
|
|
if ($active.pid) { Stop-Tree ([int]$active.pid) "active-run pid" $true }
|
|
if ($active.launcherPid) { Stop-Tree ([int]$active.launcherPid) "active-run launcherPid" }
|
|
if ($active.sessionDir) {
|
|
$workerPidPath = Join-Path ([string]$active.sessionDir) "worker.pid"
|
|
if (Test-Path $workerPidPath) {
|
|
$pidText = (Get-Content -Path $workerPidPath -Raw).Trim()
|
|
if ($pidText -match "^\d+$") { Stop-Tree ([int]$pidText) "active session worker.pid" $true }
|
|
}
|
|
}
|
|
} catch {
|
|
Write-CleanupLog "Failed to read active-run.json: $($_.Exception.Message)"
|
|
}
|
|
}
|
|
|
|
Get-CimInstance Win32_Process | Where-Object { Test-IsProjectBuildProcess $_ } | ForEach-Object {
|
|
Stop-Tree ([int]$_.ProcessId) "matched OEM/build command"
|
|
}
|
|
|
|
Start-Sleep -Milliseconds 800
|
|
|
|
$remaining = @(Get-CimInstance Win32_Process | Where-Object { Test-IsProjectBuildProcess $_ })
|
|
if ($remaining.Count -gt 0) {
|
|
foreach ($proc in $remaining) {
|
|
Write-CleanupLog "Still running PID $($proc.ProcessId) ($($proc.Name))"
|
|
}
|
|
} else {
|
|
Write-CleanupLog "Cleanup finished. Killed=$($killed.Count)"
|
|
}
|
|
|
|
if ($killed.Count -gt 0) {
|
|
Stop-ActiveRunState "Stale OEM build processes were cleaned before launching the tool. Killed=$($killed.Count)"
|
|
}
|