Run a powershell script asynchronously

Can
Can used Ask the Experts™
on
Hi All,

I got a powershell script to export all local admin accounts from ad computers to a CSV:

$servers= Get-Content -Path 'C:\Localdata\ADcomputers.csv'
$output = 'C:\localdata\PRODadmin.csv' 

$servers | ForEach-Object {
	$server = $_
	Write-Host "Processing $($server)"
	$group = [ADSI]"WinNT://$($server)/Administrators" 
	$group.psbase.Invoke('Members') | ForEach-Object {
		New-Object PSObject -Property ([ordered]@{
			Server = $server
			Admin = $_.GetType().InvokeMember('Name', 'GetProperty', $null, $_, $null)
		})
	}
} |
	Where-Object {$_.Admin -notmatch '^(L RG.*|Locbeh|Domain Admins|Enterprise Admins|Administrator|G RB.*|SA_.*)$'} |
	Export-csv $Output -NoTypeInformation

Open in new window


Yet this is taking a very long time since its running the script synchronously. Is there a way to edit the script so it runs asynchronous?

Thanks in advance.
Comment
Watch Question

Do more with

Expert Office
EXPERT OFFICE® is a registered trademark of EXPERTS EXCHANGE®
Top Expert 2014

Commented:
try invoke-parallel
https://github.com/RamblingCookieMonster/Invoke-Parallel

You'll need to download and import the module.
CanSystem Administrator

Author

Commented:
Thank you for your reply. I have imported the module. Yet i am struggling to use it.

How can i use it with my script?

Thanks in advance.
Most Valuable Expert 2018
Distinguished Expert 2018
Commented:
Try this:
$servers = Get-Content -Path 'C:\Localdata\ADcomputers.csv'
$output = 'C:\localdata\PRODadmin.csv' 
$filter = '^(L RG.*|Locbeh|Domain Admins|Enterprise Admins|Administrator|G RB.*|SA_.*)$'
$queueSize = 20

$get_LocalAdmin = {
	Param($Server)
	Try {
		$group = [ADSI]"WinNT://$($Server)/Administrators" 
		$group.psbase.Invoke('Members') | ForEach-Object {
			New-Object PSObject -Property ([ordered]@{
				Server = $Server
				Admin = $_.GetType().InvokeMember('Name', 'GetProperty', $null, $_, $null)
				Error = $null
			})
		}
	} Catch {
		New-Object PSObject -Property ([ordered]@{
			Server = $Server
			Admin = $null
			Error = $_.Exception.Message -replace "`r?`n", ' '
		})
	}
}

$jobList = New-Object -TypeName System.Collections.ArrayList
$resultList = New-Object -TypeName System.Collections.ArrayList
$serverList = New-Object -TypeName System.Collections.ArrayList
$servers | ForEach-Object {[void]$serverList.Add($_)}
Do {
	@($jobList) | Where-Object {'Completed', 'Failed', 'Stopped', 'Blocked', 'Suspended' -contains $_.State} | ForEach-Object {
		[void]$resultList.Add((Receive-Job -Job $_ | Select-Object -Property * -ExcludeProperty RunspaceId))
		Write-Host "Receiving $(@($resultList[-1].Server)[0])" -ForegroundColor Green
		Remove-Job -Job $_ -Force
		$jobList.Remove($_)
	}
	While (($jobList.Count -lt $queueSize) -and ($serverList.Count -gt 0)) {
		Write-Host "Queuing $($serverList[0])" -ForegroundColor White
		[void]$jobList.Add((Start-Job -ScriptBlock $get_LocalAdmin -ArgumentList $serverList[0]))
		$serverList.RemoveAt(0)
	}
	Start-Sleep -MilliSeconds 500
} Until ($jobList.Count -eq 0)
$resultList |
	Where-Object {$_.Admin -notmatch $filter} |
	Sort-Object -Property Server, Admin |
	Export-Csv -Path $Output -NoTypeInformation

Open in new window

Do more with

Expert Office
Submit tech questions to Ask the Experts™ at any time to receive solutions, advice, and new ideas from leading industry professionals.

Start 7-Day Free Trial