I am a sysadmin for my network, but we are in a tiered enterprise domain. Our McAfee ePO server is controlled above us, and they are holding on to all permissions (job security). So I came up with the below script to parse through a list of computers and get their McAfee Dat version and write it to a text file.
When I run it across 3000 machines, it takes a long time. So I was hoping someone could help me convert it to multithreading.
$ErrorActionPreference = "silentlycontinue" filter Check-Online { trap { continue } . { $timeout = 2000 $obj = New-Object system.Net.NetworkInformation.Ping $result = $obj.Send($_, $timeout) if ($result.status -eq 'Success') {1 } } } function Get-WebPage { [cmdletbinding( DefaultParameterSetName = 'url', ConfirmImpact = 'low' )] Param( [Parameter( Mandatory = $True, Position = 0, ParameterSetName = '', ValueFromPipeline = $True)] [string][ValidatePattern("^(http|https)\://*")]$Url, [Parameter( Position = 1, Mandatory = $False, ParameterSetName = 'defaultcred')] [switch]$UseDefaultCredentials, [Parameter( Mandatory = $False, ParameterSetName = '')] [string]$Proxy, [Parameter( Mandatory = $False, ParameterSetName = 'altcred')] [switch]$Credential, [Parameter( Mandatory = $False, ParameterSetName = '')] [switch]$ShowSize ) Begin { $psBoundParameters.GetEnumerator() | % { Write-Verbose "Parameter: $_" } #Create the initial WebClient object Write-Verbose "Creating web client object" $wc = New-Object Net.WebClient #Use Proxy address if specified If ($PSBoundParameters.ContainsKey('Proxy')) { #Create Proxy Address for Web Request Write-Verbose "Creating proxy address and adding into Web Request" $wc.Proxy = New-Object -TypeName Net.WebProxy($proxy,$True) } #Determine if using Default Credentials If ($PSBoundParameters.ContainsKey('UseDefaultCredentials')) { #Set to True, otherwise remains False Write-Verbose "Using Default Credentials" $wc.UseDefaultCredentials = $True } #Determine if using Alternate Credentials If ($PSBoundParameters.ContainsKey('Credentials')) { #Prompt for alternate credentals Write-Verbose "Prompt for alternate credentials" $wc.Credential = (Get-Credential).GetNetworkCredential() } } Process { Try { If ($ShowSize) { #Get the size of the webpage Write-Verbose "Downloading web page and determining size" "{0:N0}" -f ($wr.DownloadString($url) | Out-String).length -as [INT] } Else { #Get the contents of the webpage Write-Verbose "Downloading web page and displaying source code" $wc.DownloadString($url) } } Catch { Write-Warning "$($Error[0])" } } } Function Get-RemoteRegistry { #This Function is read remote registry param( [string]$computer = $(Read-Host "Remote Computer Name") ,[string]$Path = $(Read-Host "Remote Registry Path (must start with HKLM,HKCU,etc)") ,[string[]]$Properties ,[switch]$Verbose ) if ($Verbose) { $VerbosePreference = 2 } # Only affects this script. $root, $last = $Path.Split("\") $last = $last[-1] $Path = $Path.Substring($root.Length + 1,$Path.Length - ( $last.Length + $root.Length + 2)) $root = $root.TrimEnd(":") #split the path to get a list of subkeys that we will need to access # ClassesRoot, CurrentUser, LocalMachine, Users, PerformanceData, CurrentConfig, DynData switch($root) { "HKLM" { $root = "LocalMachine" } default { return "Path argument is not valid" } } #Access Remote Registry Key using the static OpenRemoteBaseKey method. Write-Verbose "Accessing $root from $computer" #Add-Content $loglocation "Accessing $root from $computer" $rootkey = [Microsoft.Win32.RegistryKey]::OpenRemoteBaseKey($root,$computer) if(-not $rootkey) { Write-Error "Can't open the remote $root registry hive" } Write-Verbose "Opening $Path" #Add-Content $loglocation "Opening $Path" $key = $rootkey.OpenSubKey( $Path ) if(-not $key) { Write-Error "Can't open $($root + '\' + $Path) on $computer" #Add-Content $loglocation "Can't open $($root + '\' + $Path) on $computer" } $subkey = $key.OpenSubKey( $last ) $output = new-object object if($subkey -and $Properties -and $Properties.Count) { foreach($property in $Properties) { Add-Member -InputObject $output -Type NoteProperty -Name $property -Value $subkey.GetValue($property) } Write-Output $output } elseif($subkey) { Add-Member -InputObject $output -Type NoteProperty -Name "Subkeys" -Value @($subkey.GetSubKeyNames()) foreach($property in $subkey.GetValueNames()) { Add-Member -InputObject $output -Type NoteProperty -Name $property -Value $subkey.GetValue($property) } Write-Output $output } else { $key.GetValue($last) } } $loglocation = Read-Host "Please input a local path to save the logs to. Ex: C:\mylog.txt" $Computerlist = Read-Host "Please input the path to local file that contains the computer's names. Ex: C:\computernames.txt" $webpage = Get-WebPage -url "ftp://ftp.mcafee.com/commonupdater/" $val1 = $webpage.indexof("avvdat-") + 4 $val2 = $webpage.indexof(".zip") $output = $webpage.substring($val1,$val2-$val1) $output = $output.replace("at-", "") write-host "The current DAT file version is: $output" Add-Content $loglocation "The current DAT file version is: $output" $servers = get-content $Computerlist #read the computers from the text file foreach($s in $servers){ #This foreach loops through the text file of computers and performs the below actions on each computer. #Check if they are online if (($s | Check-Online) -eq 1) { write-host "$s is online" $Regvalue = Get-RemoteRegistry $s "HKLM\SOFTWARE\Wow6432Node\McAfee\AVEngine\AVDatDate" $Regvalue2 = Get-RemoteRegistry $s "HKLM\SOFTWARE\Wow6432Node\McAfee\AVEngine\AVDatVersion" $Regvalue3 = Get-RemoteRegistry $s "HKLM\SOFTWARE\McAfee\AVEngine\AVDatDate" $Regvalue4 = Get-RemoteRegistry $s "HKLM\SOFTWARE\McAfee\AVEngine\AVDatVersion" $aValue = $Regvalue $bValue = $Regvalue2 if($Regvalue -eq $null){ $aValue = $Regvalue3 } if($Regvalue2 -eq $null){ $bValue = $Regvalue4 } write-host $Regvalue write-host $Regvalue2 write-host $Regvalue3 write-host $Regvalue4 Add-Content $loglocation "$s,$aValue,$bValue" }else{ Write-Error "$s is offline" } }