<# .SYNOPSIS Checks a list of computers for a Windows service and reports its state, startup type and account. .DESCRIPTION Connects to each computer with a CIM session (WinRM by default, DCOM if you ask for it) and looks up the service by name or display name. Every computer gets a row: found, not installed, or unreachable, so the report accounts for the whole list. Read-only. .PARAMETER ComputerName Computers to check. Accepts pipeline input, so Get-Content .\computers.txt | ... works. .PARAMETER Name Service name or display name. Wildcards are fine, for example '*Spooler*'. .PARAMETER Protocol Wsman (the default, needs WinRM) or Dcom (older machines, needs RPC/WMI through the firewall). .PARAMETER Credential Credentials for the remote connection. .PARAMETER CsvPath Also save the results to this CSV file. .EXAMPLE Get-Content .\computers.txt | .\Get-ServiceAudit.ps1 -Name Spooler -CsvPath .\spooler.csv #> [CmdletBinding()] param( [Parameter(ValueFromPipeline, ValueFromPipelineByPropertyName)] [Alias('CN', 'DNSHostName')] [string[]]$ComputerName = $env:COMPUTERNAME, [Parameter(Mandatory)][ValidateNotNullOrEmpty()][string]$Name, [ValidateSet('Wsman', 'Dcom')][string]$Protocol = 'Wsman', [pscredential]$Credential, [string]$CsvPath ) begin { $results = [System.Collections.Generic.List[object]]::new() $wql = $Name.Replace('\', '\\').Replace("'", "\'").Replace('[', '[[]').Replace('_', '[_]').Replace('*', '%') $query = "SELECT Name, DisplayName, State, StartMode, StartName, PathName FROM Win32_Service WHERE Name LIKE '$wql' OR DisplayName LIKE '$wql'" function New-Row($Computer, $Status, $Service) { [pscustomobject]@{ ComputerName = $Computer Status = $Status ServiceName = $Service.Name DisplayName = $Service.DisplayName State = $Service.State StartMode = $Service.StartMode RunAs = $Service.StartName Path = $Service.PathName } } } process { foreach ($computer in $ComputerName) { $computer = $computer.Trim() if (-not $computer -or $computer.StartsWith('#')) { continue } $session = $null try { $sessionArgs = @{ ComputerName = $computer SessionOption = New-CimSessionOption -Protocol $Protocol ErrorAction = 'Stop' } if ($Credential) { $sessionArgs.Credential = $Credential } $session = New-CimSession @sessionArgs $services = @(Get-CimInstance -CimSession $session -Query $query -ErrorAction Stop) if ($services.Count -eq 0) { $results.Add((New-Row $computer 'Not installed' $null)) } foreach ($svc in $services) { $results.Add((New-Row $computer 'Found' $svc)) } } catch { Write-Warning "$computer : $($_.Exception.Message)" $results.Add((New-Row $computer 'Unreachable' $null)) } finally { if ($session) { Remove-CimSession -CimSession $session } } } } end { if ($CsvPath) { $results | Export-Csv -LiteralPath $CsvPath -NoTypeInformation Write-Verbose "Saved $($results.Count) row(s) to $CsvPath" } $results }