[CmdletBinding()] param( [Parameter(Mandatory = $true)][string]$StableArtifact, [int]$StablePid = 0, [string]$ServiceName, [string[]]$Configuration = @(), [Parameter(Mandatory = $true)][string]$OutputJson ) $ErrorActionPreference = 'Stop' Set-StrictMode -Version Latest . (Join-Path $PSScriptRoot 'ShadowScriptCommon.ps1') $artifact = Resolve-ShadowFile $StableArtifact $service = $null if ($ServiceName) { $service = Get-CimInstance Win32_Service -Filter "Name='$ServiceName'" ` -ErrorAction Stop if ($StablePid -eq 0) { $StablePid = [int]$service.ProcessId } } elseif ($StablePid -gt 0) { try { $service = Get-CimInstance Win32_Service -Filter "ProcessId=$StablePid" ` -ErrorAction Stop | Select-Object -First 1 } catch { $service = $null } } if ($StablePid -le 0) { throw 'STABLE_PID_OR_SERVICE_REQUIRED' } $process = Get-Process -Id $StablePid -ErrorAction Stop $configurationEvidence = @($Configuration | ForEach-Object { $path = Resolve-ShadowFile $_ [pscustomobject]@{ path = $path sha256 = Get-ShadowSha256 $path } }) $manifest = [pscustomobject]@{ schemaVersion = 1 capturedAtUtc = [DateTime]::UtcNow.ToString('o') status = 'PASS' artifactPath = $artifact artifactSha256 = Get-ShadowSha256 $artifact pid = [int]$process.Id processStartTimeUtc = $process.StartTime.ToUniversalTime().ToString('o') executablePath = $process.Path commandLine = Get-ShadowCommandLine $process.Id serviceName = if ($null -eq $service) { $null } else { $service.Name } serviceState = if ($null -eq $service) { $null } else { $service.State } configuration = $configurationEvidence listeningPorts = @(Get-ShadowListeningPorts $process.Id) } Write-ShadowJson -Value $manifest -Path $OutputJson return $manifest