35 lines
2.2 KiB
PowerShell
35 lines
2.2 KiB
PowerShell
# Read-only snapshot or identity-checked termination. Input is JSON over stdin;
|
|
# repository paths/commands are never evaluated as PowerShell source.
|
|
$ErrorActionPreference = 'Stop'
|
|
$request = [Console]::In.ReadToEnd() | ConvertFrom-Json
|
|
function Identity($p) {
|
|
[PSCustomObject]@{ pid = [int]$p.ProcessId; parentPid = [int]$p.ParentProcessId; name = $p.Name; commandLine = [string]$p.CommandLine; created = $(if ($null -ne $p.CreationDate) { $p.CreationDate.ToUniversalTime().ToString('o') } else { '' }) }
|
|
}
|
|
if ($request.action -eq 'stop') {
|
|
$stopped = @()
|
|
foreach ($expected in $request.processes) {
|
|
$p = Get-CimInstance Win32_Process -Filter ('ProcessId = ' + [int]$expected.pid)
|
|
if ($null -eq $p) { continue }
|
|
$actual = Identity $p
|
|
if (-not $expected.created -or -not $expected.commandLine -or $actual.created -ne $expected.created -or $actual.commandLine -cne $expected.commandLine) { throw ('PROCESS_IDENTITY_CHANGED:' + $expected.pid) }
|
|
# Open a handle before the final identity check so termination cannot select a reused PID.
|
|
$handle = [System.Diagnostics.Process]::GetProcessById([int]$expected.pid)
|
|
$null = $handle.Handle
|
|
$again = Get-CimInstance Win32_Process -Filter ('ProcessId = ' + [int]$expected.pid)
|
|
if ($null -eq $again) { $handle.Dispose(); continue }
|
|
$identity = Identity $again
|
|
if ($identity.created -ne $expected.created -or $identity.commandLine -cne $expected.commandLine) { $handle.Dispose(); throw ('PROCESS_IDENTITY_CHANGED:' + $expected.pid) }
|
|
$handle.Kill()
|
|
$handle.Dispose()
|
|
$stopped += [int]$expected.pid
|
|
}
|
|
@{ stopped = $stopped } | ConvertTo-Json -Compress
|
|
exit
|
|
}
|
|
$processes = @(Get-CimInstance Win32_Process | ForEach-Object { Identity $_ })
|
|
$windows = @(Get-Process electron -ErrorAction SilentlyContinue | Where-Object { $_.MainWindowHandle -ne 0 } | ForEach-Object {
|
|
@{ pid = $_.Id; title = $_.MainWindowTitle; responding = $_.Responding }
|
|
})
|
|
$listeners = @(Get-NetTCPConnection -State Listen -ErrorAction Stop | ForEach-Object { @{ pid = $_.OwningProcess; port = $_.LocalPort; address = $_.LocalAddress } })
|
|
@{ processes = $processes; windows = $windows; listeners = $listeners } | ConvertTo-Json -Depth 5 -Compress
|