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"
}
}