$ErrorActionPreference = 'Stop' $projectRoot = Split-Path -Parent $PSScriptRoot $py = "$projectRoot\.venv\Scripts\python.exe" $runservicesLog = "$projectRoot\.runtime\runservices.stdout.log" $runservicesErr = "$projectRoot\.runtime\runservices.stderr.log" $pidFile = "$projectRoot\.runtime\runservices.json" $action = 'start' if ($args.Count -gt 0) { $action = $args[0] } function Get-ProjectServices { Get-CimInstance Win32_Process -Filter "Name='python.exe'" | Where-Object { $_.CommandLine -like '*manage.py runservices*' -and $_.CommandLine -like '*video_monitor*' } } function Get-Descendants([int]$ParentId) { $children = @() Get-CimInstance Win32_Process -Filter "ParentProcessId=$ParentId" -ErrorAction SilentlyContinue | ForEach-Object { $children += $_ $children += Get-Descendants $_.ProcessId } $children } switch ($action) { 'start' { $existing = Get-ProjectServices if ($existing) { Write-Host "runservices already running: PIDs $($existing.ProcessId -join ', ')" exit 0 } New-Item -ItemType Directory -Force -Path "$projectRoot\.runtime" | Out-Null $p = Start-Process -FilePath $py -ArgumentList @('manage.py','runservices') ` -WorkingDirectory $projectRoot -WindowStyle Hidden ` -RedirectStandardOutput $runservicesLog -RedirectStandardError $runservicesErr -PassThru @{ pid = $p.Id; created = (Get-Date).ToString('o') } | ConvertTo-Json | Set-Content $pidFile -Encoding UTF8 Write-Host "runservices started PID=$($p.Id)" Start-Sleep -Seconds 20 $zlm = Get-CimInstance Win32_Process -Filter "Name='monitor_zlm.exe'" -ErrorAction SilentlyContinue $sip = Get-NetUDPEndpoint -LocalPort 15060 -ErrorAction SilentlyContinue if ($zlm) { Write-Host "ZLM up PID=$($zlm.ProcessId -join ', ')" } else { Write-Host 'ZLM not up yet; inspect log' } if ($sip) { Write-Host 'SIP 15060 listening' } else { Write-Host 'SIP 15060 not listening yet' } } 'stop' { $procs = Get-ProjectServices if (-not $procs) { Write-Host 'No runservices process running' Remove-Item $pidFile -ErrorAction SilentlyContinue exit 0 } foreach ($proc in $procs) { $desc = Get-Descendants $proc.ProcessId foreach ($child in $desc) { Stop-Process -Id $child.ProcessId -Force -ErrorAction SilentlyContinue } Stop-Process -Id $proc.ProcessId -Force -ErrorAction SilentlyContinue Write-Host "stopped runservices PID=$($proc.ProcessId) (children: $($desc.ProcessId -join ', '))" } Remove-Item $pidFile -ErrorAction SilentlyContinue } 'status' { $procs = Get-ProjectServices $zlm = Get-CimInstance Win32_Process -Filter "Name='monitor_zlm.exe'" -ErrorAction SilentlyContinue $sip = Get-NetUDPEndpoint -LocalPort 15060 -ErrorAction SilentlyContinue [pscustomobject]@{ runservices = ($procs | ForEach-Object { $_.ProcessId }) -join ', ' zlm = ($zlm | ForEach-Object { $_.ProcessId }) -join ', ' sip_15060 = [bool]$sip } | Format-List } default { Write-Host "Usage: .\scripts\start-services.ps1 [start|stop|status]" exit 1 } }