Search code examples
powershellpowershell-3.0

Run Parallel jobs power shell


Hello PowerShell gurus

I made this script to get the latest KB patch installed on a remote PC. And its now working. AL though its crude and something I just put together (while learning PS). It gets the job done… Painfully slow but works. It takes over 2:40 hrs to run and check 128 PCs. I saw in other posts that creating parallels jobs for this might help. I have no idea on how to create parallel jobs please help me.

my script

Start-Transcript -Path "$(Get-location)\RESULTLOG-$(Get-date -Format "yyyyMMddTHHmmss").log"

Function Get-FileName{
    [System.Reflection.Assembly]::LoadWithPartialName(“System.windows.forms”) | Out-Null
    $OpenFileDialog = New-Object System.Windows.Forms.OpenFileDialog
    $OpenFileDialog.initialDirectory = Get-Location
    $OpenFileDialog.filter = “All files (*.*)| *.*”
    $OpenFileDialog.ShowDialog() | Out-Null
    $OpenFileDialog.filename
}

$Importfile = Get-FileName
$Clients = Get-Content $Importfile

Foreach($Client in $Clients){

    #CHECK IF  PC IS ENABLED IN AD <<<<feature improvement 
    # if(get-adcomputer -Filter 'Name -like $p' -Properties Enabled)


    if (Test-Connection -ComputerName $Client -Count 2 -Quiet) {
        try { 
            Get-HotFix -ComputerName $Client -Description 'Security Update' | Select-Object -Last 1
        }
        catch { 
            "$Client;An error occurred." 
        }  
    }
    else{
        "$Client;not on line "
    }
}
Stop-Transcript

I'm also trying to work on checking if PC is enabled in Active Directory before running the rest of the code, but I have that commented out for the mean time what I got works.

Can the performance in this be improved?? I know that network speed might have something to do but for the amount of data from each PC should not take this long


Solution

  • Take a look at the "-Parallel" switch of ForEach-Object: https://devblogs.microsoft.com/powershell/powershell-foreach-object-parallel-feature/

    You may need to change your code a bit in order to make it to work with the ForEach-Object call instead of the foreach block:

    ...
    $Clients | ForEach-Object {
        if (Test-Connection -ComputerName $_ -Count 2 -Quiet) {
            try { 
                Get-HotFix -ComputerName $_ -Description 'Security Update' | 
                    Select-Object -Last 1
            }
            catch { 
                "$_;An error occurred." 
            }  
         }
         else {
            "$_;not on line "
         }
    } -Parallel
    ...
    

    EDIT: As mentioned by @doug-maurer in the comments as well as in the link I provided, this will only work on PowerShell v7-Preview-3 onwards.