Plan service corrections from an export
Compare host-specific service states and produce proposals without pretending to manage live services.
A service name needs a computer
Many computers run a service with the same name. Join each desired entry to the observed export using both Computer and Name. A running backup agent on one server does not establish that another server's agent is running.
The desired list defines what this policy manages. Ignore observed services absent from the desired list. A matching state produces no action; a mismatch needs an explicit proposal.
Propose only what the evidence supports
For this simplified model, Stopped → Running proposes Start, and Running → Stopped proposes Stop. Missing records or other observed states, such as Paused, propose Investigate. Do not turn every non-running state into a Start command: real service transitions have more possibilities and prerequisites.
Import-Csv '/home/user/services.csv' | Select-Object Computer, Name, State
Keep Current, Desired, and Action together. That lets a reviewer see both the observed difference and the proposed response. Missing means “not present in this export,” not proof that the service is uninstalled.
This exercise never calls Get-Service, Start-Service, or a remote computer. The browser works from supplied snapshots. Applying a plan later requires fresh state, permissions, dependency checks, change approval where applicable, and a rollback strategy in the actual environment.
Get-Content '/home/user/desired-services.json' -Raw | ConvertFrom-Json
Put it into practice.
For each desired-services.json entry, match services.csv by Computer plus Name. Emit mismatches only with Computer, Name, Current, Desired, Action. Stopped→Running proposes Start; Running→Stopped proposes Stop; missing or other states propose Investigate (Current Missing if absent). Ignore unmanaged observed services. Apply no service changes.
See an explained solution
$actual = @(Import-Csv '/home/user/services.csv')
foreach ($desired in Get-Content '/home/user/desired-services.json' -Raw | ConvertFrom-Json) {
$service = $actual | Where-Object { $_.Computer -eq $desired.Computer -and $_.Name -eq $desired.Name }
$action = $null
$observed = if ($service) { $service.State } else { 'Missing' }
if (-not $service) { $action = 'Investigate' }
elseif ($service.State -eq $desired.State) { continue }
elseif ($service.State -eq 'Stopped' -and $desired.State -eq 'Running') { $action = 'Start' }
elseif ($service.State -eq 'Running' -and $desired.State -eq 'Stopped') { $action = 'Stop' }
else { $action = 'Investigate' }
[pscustomobject]@{ Computer=$desired.Computer; Name=$desired.Name; Current=$observed; Desired=$desired.State; Action=$action }
}
The composite join keeps each server independent. Only known Running/Stopped transitions become concrete proposals; paused and missing observations remain review tasks.