This PowerShell script generates an html report listing all accounts used as logon account by services on servers in an Active Directory domain.

The script has filters to ignore accounts : NT Service, NT AUTHORITY and LocalSystem

https://github.com/sozezzo/Powershell/blob/master/Report/report-service-server.ps1

Apply filter by servers and services

1
2$FilterServerLike  = "*"   ## Select all servers
3$FilterServiceLike = "*"   ## Select all services

Ignore accounts

1
2$IgnoreAccount_NT_Service   = 1  ## NT Service
3$IgnoreAccount_NT_AUTHORITY = 1  ## NT AUTHORITY
4$IgnoreAccount_LocalSystem  = 1  ## LocalSystem

Powershell script to find servers and services

  1
  2<#
  3
  4    report-service-server.ps1
  5
  6     Reads service configuration from all Windows servers in the current domain
  7     and generates report listing all service logon account.
  8
  9     Version history:
 10         08.08.2020 First release
 11
 12    #Reference : https://gallery.technet.microsoft.com/scriptcenter/PowerShell-script-to-find-6fc15ecb
 13                  * Use Job and missing nice features
 14
 15#>
 16
 17Clear
 18
 19## Begin Configuration ##
 20
 21$FilterServerLike  = "*"   ## Filter server
 22$FilterServiceLike = "*"   ## Filter service
 23
 24## Search for all server and all services ##
 25#$FilterServerLike = "**"   ## Search all server : "*"
 26#$FilterServiceLike = "*"     ## Search all service
 27
 28## Search for all server *sql* and all services mssql* ##
 29#$FilterServerLike = "*sql*"   ## Search all server with name *SQL*
 30#$FilterServiceLike = "MSSQL*"     ## Search service MSSQL*
 31
 32$IgnoreAccount_NT_Service   = 1  ## NT Service
 33$IgnoreAccount_NT_AUTHORITY = 1  ## NT AUTHORITY
 34$IgnoreAccount_LocalSystem  = 1  ## LocalSystem
 35$ListServer                 = 1  ## Create table -- Server | #Services | Access status
 36$reportFile = "$env:TEMP\report_service_server.html"
 37## End Configuration ##
 38
 39## Global variables ##
 40$ErrorActionPreference = "Stop"
 41$currentDomain = $env:USERDOMAIN.ToUpper()
 42$ServiceList = @{}
 43$ServerList = @{}
 44[string[]]$warnings = @()
 45
 46function get-server-info()
 47{
 48     param( $hostname )
 49
 50     if ( Test-Connection -ComputerName $hostname -Count 3 -Quiet ){
 51         try {
 52             # retrieve service list form a remove machine
 53             $serviceList = @( gwmi -Class Win32_Service -ComputerName $hostname -Property Name,StartName,SystemName -ErrorAction Stop )
 54             ##$serviceList
 55
 56            ##############################
 57             # reads service list
 58
 59             if ( $serviceList.GetType() -eq [Object[]] ){
 60                 try
 61                 {
 62                     $serviceList = $serviceList | ? { $_.StartName.toUpper() }
 63
 64                    if ($serviceList.Count -ge 1)
 65                     {
 66                         $arrID = $script:ServerList.Count+1
 67                         $ItemInfo    = $hostname, $($serviceList.Count), ""
 68                         $script:ServerList.Add( $arrID, @( $ItemInfo ) )
 69                     } else
 70                     {
 71                         $arrID = $script:ServerList.Count+1
 72                         $ItemInfo    = $hostname, "", "no services"
 73                         $script:ServerList.Add( $arrID, @( $ItemInfo ) )
 74                     }
 75
 76                    #Apply Filter
 77                     if ($IgnoreAccount_NT_Service   -eq 1) { $serviceList = $serviceList | Where-Object {$_.StartName -notlike "NT Service*" }   | ? { $_.StartName } }
 78                     if ($IgnoreAccount_NT_AUTHORITY -eq 1) { $serviceList = $serviceList | Where-Object {$_.StartName -notlike "NT AUTHORITY*" } | ? { $_.StartName } }
 79                     if ($IgnoreAccount_LocalSystem  -eq 1) { $serviceList = $serviceList | Where-Object {$_.StartName -notlike "LocalSystem" }    | ? { $_.StartName } }
 80
 81                    if ($FilterServiceLike -ne "*") { $serviceList = $serviceList | Where-Object {$_.Name -like $FilterServiceLike } }
 82
 83                    foreach( $service in $serviceList ){
 84
 85                        $arrID = $script:ServiceList.Count+1
 86                         $ItemInfo    = $service.StartName, $($service.Name), $($service.SystemName)
 87
 88                         $script:ServiceList.Add( $arrID, @( $ItemInfo ) )
 89
 90                    }
 91                 }
 92                 catch {}
 93             }
 94             elseif ( $data.GetType() -eq [String] )
 95             {
 96                 $script:warnings += "Fail to read service info"
 97             }
 98
 99        }
100         catch
101         {
102             $global:warnings += @("$hostname | Failed to retrieve data $($_.toString())")
103             $arrID = $script:ServerList.Count+1
104             $ItemInfo    = $hostname, "", "Failed"
105             $script:ServerList.Add( $arrID, @( $ItemInfo ) )
106         }
107     }
108     else
109     {
110         $global:warnings += @("$hostname | unreachable")
111         $arrID = $script:ServerList.Count+1
112         $ItemInfo    = $hostname, "", "Unreachable"
113         $script:ServerList.Add( $arrID, @( $ItemInfo ) )
114     }
115}
116
117#################    MAIN   #################
118
119## Add-WindowsFeature RSAT-AD-PowerShell
120Import-Module ActiveDirectory
121
122# read computer accounts from current domain
123Write-Progress -Activity "Retrieving server list from ActiveDirectory" -Status "Processing..." -PercentComplete 0
124$serverServiceList = Get-ADComputer -Filter {OperatingSystem -like "Windows Server*"} -Properties DNSHostName, cn | Where-Object {$_.Name -like $FilterServerLike } | ? { $_.enabled }
125
126$count_servers = 0
127foreach( $server in $serverServiceList ){
128
129    $dnshostname = $server.dnshostname
130     $dnshostname
131
132    ++$count_servers
133     Write-Progress -Activity "Retrieving data from server $dnshostname ( $count_servers / $($serverServiceList.Count) ) " -Status "Processing..." -PercentComplete ( $count_servers * 100 / $serverServiceList.Count )
134
135     get-server-info $server.dnshostname
136
137}
138
139# prepare data table for report
140Write-Progress -Activity "Generating report" -Status "Please wait..." -PercentComplete 0
141
142$ServiceTable = @()
143foreach( $value in $serviceList.Values )
144{
145
146        $row = new-object psobject
147         Add-Member -InputObject $row -MemberType NoteProperty -Name "Account" -Value $(($value)[0])
148         Add-Member -InputObject $row -MemberType NoteProperty -Name "Service" -Value $(($value)[1])
149         Add-Member -InputObject $row -MemberType NoteProperty -Name "Server"  -Value $(($value)[2])
150         $ServiceTable  += $row
151}
152
153$ServerTable = @()
154foreach( $value in $ServerList.Values )
155{
156
157        $row = new-object psobject
158         Add-Member -InputObject $row -MemberType NoteProperty -Name "Server"    -Value $(($value)[0])
159         Add-Member -InputObject $row -MemberType NoteProperty -Name "Services"  -Value $(($value)[1])
160         Add-Member -InputObject $row -MemberType NoteProperty -Name "Status"    -Value $(($value)[2])
161         $ServerTable  += $row
162}
163
164#################
165# create report
166$datenow = Get-Date -format "yyyy-MMM-dd HH:mm"
167$report = "
168<!DOCTYPE html>
169<html>
170<head>
171<style>
172TABLE{border-width: 1px;border-style: solid;border-color: black;border-collapse: collapse;white-space:nowrap;}
173TH{border-width: 1px;padding: 4px;border-style: solid;border-color: black}
174TD{border-width: 1px;padding: 2px 10px;border-style: solid;border-color: black}
175</style>
176</head>
177<body>
178<H1>Service &amp; Server report for $currentDomain domain</H1>
179<H3>Server Filter : $FilterServerLike</br>
180Service Filter : $FilterServiceLike</br>
181Login : $env:UserDomain$env:UserName</br>
182Date : $datenow
183</H3>
184
185<H2>Discovered service accounts</H2>
186$( $ServiceTable | Sort Account | ConvertTo-Html Account, Service, Server -Fragment )
187Discovered $($ServiceTable.count) services.
188</br>
189
190<H2>Discovered servers</H2>
191$( $ServerTable | Sort Status, Server   | ConvertTo-Html Server, Services, Status -Fragment )
192$($serverList.count) servers processed.
193</br>
194
195<H2>Warning messages</H2>
196$( $warnings | % { "<p>$_</p>" } )
197
198</body>
199</html>"
200
201Write-Progress -Activity "Generating report" -Status "Please wait..." -Completed
202$report  | Set-Content $reportFile -Force
203Invoke-Expression $reportFile

Sources :

https://gallery.technet.microsoft.com/scriptcenter/PowerShell-script-to-find-6fc15ecb

https://devblogs.microsoft.com/scripting/the-scripting-wife-uses-powershell-to-find-service-accounts/