Convert to multithreading

Welcome Forums General PowerShell Q&A Convert to multithreading

This topic contains 5 replies, has 4 voices, and was last updated by

 
Participant
4 years, 4 months ago.

  • Author
    Posts
  • #17012

    Participant
    Points: 0
    Rank: Member

    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"
        }
    }
    
  • #17015

    Participant
    Points: 0
    Rank: Member

    Maybe you should take a closer look at powershell jobs.

    Take a look at this documentation:
    http://technet.microsoft.com/en-us/library/hh849698.aspx

  • #17017

    Participant
    Points: 0
    Rank: Member

    I tried but it didn't work

    $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.
    	$scriptblock={
            param($s)
            #Check if they are online
    	    if (($s | Check-Online) -eq 1) {	 
                write-output "$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-output "$s= $Regvalue"
                write-output "$s= $Regvalue2"
                write-output "$s= $Regvalue3"
                write-output "$s= $Regvalue4"
                Add-Content $loglocation "$s,$aValue,$bValue"
            }else{
                Write-Error "$s is offline"
            }    
        }
        start-job -name $s -scriptblock $scriptblock -argumentlist $s
    }
    
    while (get-job -state "Running")
    {
        start-sleep 1   
    } 
    get-job | receive-job
    get-job | remove-job
    
  • #17183

    Member
    Points: 0
    Rank: Member

    I've been marking his posts regarding this "Long Path Tool" on unrelated threads as Spam. Three so far in the last few minutes. Hopefully he'll catch on.

  • #17194

    Participant
    Points: 76
    Rank: Member

    This script http://gallery.technet.microsoft.com/Powershell-to-create-many-1b4f6f37 shows an example of using Start-job, Get-job, Receive-job, Remove-job to run a PS script in several concurrently-running threads.
    Notice that on this example, the number of threads = the number of vLUNs on line 11

  • #17178

    Participant
    Points: 0
    Rank: Member

    Long Path Tool seems to have nothing to do with what I am asking about

The topic ‘Convert to multithreading’ is closed to new replies.