Installing MSU files to update several 100 machines via csv file

Hello Everyone,

I hope all is well and keeping safe. I was in the midst of typing out a powershell script to install several “MSU” files via a specific location and pushing out a csv file list of servernames to have the patches installed on them. I looked at your great video of installing ‘MSU’ files but that was on 1 machine having multiple patches being installed remotely. I hope this email lays out question on how to perform the csv import of the list to have the patches installed on multiple remote machines. Thank you in advance for your input.

1 Like

First, can you enter a PS session on all of your target computers? Second, are your MSU files on a shared drive that all your target PCs can access?

You need to share the code you have so far and we can work on it.

Thanks Paul for your reply. I’ve pretty much copied your PS tutorial sample you have here. However, I’m not sure where I need to put the $machine variable in order to install the patches from either a local drive or a network share. I can do that part but I’m confused as to where I need to put the $machine variable if I want to install it on each target machine from a text file using the get-contect cmdlet. Here is the script:

# Run the script as administrator
# Possibly change this variable depending 
# on where your updates are stored on a network share
$UpdatePath = "\\network sharename\folder"

#List of target machines
$machines = Get-Content -Path \\network sharename\folder\clientlist.txt

# Get list of installed hotfix
Get-HotFix > "$UpdatePath\old_hotfix_list.txt"

# Get a list of all *.msu file updates in the folder
$Updates = Get-ChildItem -Path $UpdatePath | Where-Object {$_.Name -like "*.msu"}

ForEach ($Update in $Updates) {
    
    # Get the full path of the update file
    $Updatefilepath = $Update.FullName

    #logging
    Write-Host "Installing update $Update"
    
    #Install the update
    Start-Process -Wait wusa -ArgumentList "/update $Updatefilepath","/quiet","/norestart"
}

# Create new hotfix list
Get-HotFix > "$UpdatePath\new_hotfix_list.txt"
1 Like

Here you are getting a list of computers:

$machines = Get-Content -Path \\network sharename\folder\clientlist.txt

See if this returns an array by running $machines.GetType(). If it’s an array then we can run a foreach loop on that variable and insert your update code there:

ForEach($Machine in $machines) {
    Get-HotFix ...
    # Insert your update code for each machine here
}

Hi Paul,

Thank you kindly for your toturial. So, I need to insert the “install the update” code here?

ForEach ($machine in $machines) {
#Install the update
Start-Process -Wait wusa -ArgumentList “$machine /update $Updatefilepath”,"/quiet","/norestart"
}

Am I correct on here?

Here is my final result:

# Run the script as administrator
# Possibly change this variable depending 
# on where your updates are stored
$UpdatePath = "D:\Updates"

#List of target machines
$machines = Get-Content -Path D:\Updates\clientlist.txt

# Get list of installed hotfix
Get-HotFix > "$UpdatePath\old_hotfix_list.txt"

# Get a list of all *.msu file updates in the folder
$Updates = Get-ChildItem -Path $UpdatePath | Where-Object {$_.Name -like "*.msu"}

ForEach ($machine in $machines) {
    
    # Get the full path of the update file
    $Updatefilepath = $machine.FullName

    #logging
    Write-Host "Installing update $machine"
    
    #Install the update
    Start-Process -Wait wusa -ArgumentList "/machine $Updatefilepath","/quiet","/norestart"
}

# Create new hotfix list
Get-HotFix > "$UpdatePath\new_hotfix_list.txt"

That looks good - don’t you want the Get-HotFix command to run for each computer, though? That probably should run inside the foreach loop. It will need to be modified so it runs against the target machine name not the local computer also.

Yes, that’s a good idea. Do you mean the #get the list of installed hotfix for each machine, correct?

1 Like

Yeah it looks like this might work. I didnt test it so it might need some tweaking

ForEach ($machine in $machines) {
#... At the beginning of the for loop
    Get-HotFix -ComputerName $machine.FullName > "$($machine.FullName)_old_hotfix_list.txt"
#... At the end of the for loop
    Get-HotFix -ComputerName $machine.FullName > "$($machine.FullName)_new_hotfix_list.txt"
}

Awesome…that makes sense. Thank you very much Paul.

1 Like

Sure thing!