Files
Artemis-Eapil/scripts/upgrade_processes.ps1

66 lines
3.4 KiB
PowerShell

# Process ownership is determined by checkout paths, never by a port or name alone.
function Get-ArtemisUpgradeProcesses {
param([string]$ProjectRoot, [object[]]$Processes, [int[]]$ProtectedIds = @())
$root = [IO.Path]::GetFullPath($ProjectRoot).TrimEnd('\') + '\'
$venv = $root + '.venv\'
$selected = @{}
foreach ($process in $Processes) {
if ($ProtectedIds -contains [int]$process.ProcessId) { continue }
$executable = [string]$process.ExecutablePath
$command = [string]$process.CommandLine
$python = $process.Name -match '^(python(w)?|artemis(-admin)?)\.exe$'
$inVenv = $executable.StartsWith($venv, [StringComparison]::OrdinalIgnoreCase)
$explicitRoot = $command.Replace('/', '\').IndexOf($root, [StringComparison]::OrdinalIgnoreCase) -ge 0
$entrypoint = $command -match '(?i)(?:-m\s+(?:artemis(?:\s|\.|$)|apps\.admin_console(?:\.|\s)|mcp_server(?:\.|\s|$))|[\\/]artemis(?:\.exe|[\\/]__main__\.py)|[\\/]mcp_server[\\/])'
if (($python -and $inVenv) -or ($explicitRoot -and $entrypoint -and ($python -or $process.Name -eq 'uv.exe'))) {
$selected[[int]$process.ProcessId] = $process
}
}
do {
$added = $false
foreach ($process in $Processes) {
$id = [int]$process.ProcessId
if ($selected.ContainsKey($id) -or $ProtectedIds -contains $id) { continue }
# Shared device services and desktop applications can outlive a task.
if ($process.Name -match '^(adb|codex|chrome|msedge|firefox|emulator|MuMu.*|Nemu.*|Nox.*|MEmu.*|LdVBox.*|HD-Player)\.exe$') { continue }
if ($selected.ContainsKey([int]$process.ParentProcessId)) {
$selected[$id] = $process
$added = $true
}
}
} while ($added)
return @($selected.Values)
}
function Stop-ArtemisUpgradeProcesses {
param([string]$ProjectRoot)
$snapshot = @(Get-CimInstance Win32_Process -ErrorAction Stop)
$protected = @($PID)
$parentId = $PID
do {
$parent = $snapshot | Where-Object { [int]$_.ProcessId -eq $parentId } | Select-Object -First 1
$parentId = if ($parent) { [int]$parent.ParentProcessId } else { 0 }
if ($parentId -and $protected -notcontains $parentId) { $protected += $parentId } else { break }
} while ($true)
$deadline = [DateTime]::UtcNow.AddSeconds(10)
do {
$targets = @(Get-ArtemisUpgradeProcesses -ProjectRoot $ProjectRoot -Processes $snapshot -ProtectedIds $protected)
if (-not $targets.Count) { return }
foreach ($target in $targets) {
$id = [int]$target.ProcessId
$current = Get-CimInstance Win32_Process -Filter "ProcessId = $id" -ErrorAction Stop
if (-not $current -or $current.CreationDate -ne $target.CreationDate) { continue }
Write-Host "[STOP] ARTEMIS PID $id ($($target.Name))"
try { Stop-Process -Id $id -Force -ErrorAction Stop }
catch {
if (Get-CimInstance Win32_Process -Filter "ProcessId = $id" -ErrorAction Stop) { throw }
}
}
Start-Sleep -Milliseconds 200
$snapshot = @(Get-CimInstance Win32_Process -ErrorAction Stop)
} while ([DateTime]::UtcNow -lt $deadline)
if (@(Get-ArtemisUpgradeProcesses -ProjectRoot $ProjectRoot -Processes $snapshot -ProtectedIds $protected).Count) {
throw 'ARTEMIS processes are still running. Source/dependency updates were not started.'
}
}