Convert to multithreading

This topic contains 5 replies, has 4 voices, and was last updated by Profile photo of Sam Boutros Sam Boutros 2 years, 4 months ago.

  • Author
    Posts
  • #17012
    Profile photo of Its PaPPy
    Its PaPPy
    Participant

    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
    Profile photo of Alexander Johansson
    Alexander Johansson
    Participant

    Maybe you should take a closer look at powershell jobs.

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

  • #17017
    Profile photo of Its PaPPy
    Its PaPPy
    Participant

    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
    Profile photo of Dave Wyatt
    Dave Wyatt
    Moderator

    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
    Profile photo of Sam Boutros
    Sam Boutros
    Participant

    This script [url]http://gallery.technet.microsoft.com/Powershell-to-create-many-1b4f6f37 [/url] 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
    Profile photo of Its PaPPy
    Its PaPPy
    Participant

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

You must be logged in to reply to this topic.