In a previous post, I wrote about how to run all updates on a list of servers. Since then, I've refined my process to do it through the SCCM console. The benefit is that
- I can run the script on computers on different domains,
- on computers that are in Workgroups,
- and computers that can't be reached because of firewall rules.
Create the Script
In SCCM, navigate to Software Library > Scripts and create a new PowerShell script using this code, and approve it. You will need to change the log path below in yellow.<#
AUTHOR : Eswar Koneti
DATE : 14-Nov-2016
COMMENT : This script check and install the software updates available in
software center on clients remotely with nice logging info
VERSION : 1.0
#>
# Determine script location
$system = "$env:computername"
$log = "\\CONTOSOSERVER01\Updates Log\InstallUpdates-$system.log"
$date = Get-Date -Format "dd-MM-yyyy hh:mm:ss"
# Get list of clients from notepad
"--------------------- Script executed on $date (DD-MM-YYYY hh:mm:ss) ---------------------" + "`r`n" | Out-File $log -append
# Get list of all instances of CCM_SoftwareUpdate from root\CCM\ClientSDK for missing updates https://msdn.microsoft.com/en-us/library/jj155450.aspx?f=255&MSPPError=-2147217396
$TargetedUpdates= Get-WmiObject -Namespace root\CCM\ClientSDK -Class CCM_SoftwareUpdate -Filter ComplianceState=0
$approvedUpdates= ($TargetedUpdates |Measure-Object).count
$pendingpatches=($TargetedUpdates |Where-Object {$TargetedUpdates.EvaluationState -ne 8} |Measure-Object).count
$rebootpending=($TargetedUpdates |Where-Object {$TargetedUpdates.EvaluationState -eq 8} |Measure-Object).count
if ($pendingpatches -gt 0)
{
try {
$MissingUpdatesReformatted = @($TargetedUpdates | ForEach-Object {if($_.ComplianceState -eq 0){[WMI]$_.__PATH}})
# The following is the invoke of the CCM_SoftwareUpdatesManager.InstallUpdates with our found updates
$InstallReturn = Invoke-WmiMethod -Class CCM_SoftwareUpdatesManager -Name InstallUpdates -ArgumentList (,$MissingUpdatesReformatted) -Namespace root\ccm\clientsdk
"$system,Targeted Patches :$approvedUpdates,Pending patches:$pendingpatches,Reboot Pending patches :$rebootpending,initiated $pendingpatches patches for install" | Out-File $log -append
}
catch {"$System,pending patches - $pendingpatches but unable to install them ,please check Further" | Out-File $log -append }
}
else {"$system,Targeted Patches :$approvedUpdates,Pending patches:$pendingpatches,Reboot Pending patches :$rebootpending,Compliant" | Out-File $log -append }
AUTHOR : Eswar Koneti
DATE : 14-Nov-2016
COMMENT : This script check and install the software updates available in
software center on clients remotely with nice logging info
VERSION : 1.0
#>
# Determine script location
$system = "$env:computername"
$log = "\\CONTOSOSERVER01\Updates Log\InstallUpdates-$system.log"
$date = Get-Date -Format "dd-MM-yyyy hh:mm:ss"
# Get list of clients from notepad
"--------------------- Script executed on $date (DD-MM-YYYY hh:mm:ss) ---------------------" + "`r`n" | Out-File $log -append
# Get list of all instances of CCM_SoftwareUpdate from root\CCM\ClientSDK for missing updates https://msdn.microsoft.com/en-us/library/jj155450.aspx?f=255&MSPPError=-2147217396
$TargetedUpdates= Get-WmiObject -Namespace root\CCM\ClientSDK -Class CCM_SoftwareUpdate -Filter ComplianceState=0
$approvedUpdates= ($TargetedUpdates |Measure-Object).count
$pendingpatches=($TargetedUpdates |Where-Object {$TargetedUpdates.EvaluationState -ne 8} |Measure-Object).count
$rebootpending=($TargetedUpdates |Where-Object {$TargetedUpdates.EvaluationState -eq 8} |Measure-Object).count
if ($pendingpatches -gt 0)
{
try {
$MissingUpdatesReformatted = @($TargetedUpdates | ForEach-Object {if($_.ComplianceState -eq 0){[WMI]$_.__PATH}})
# The following is the invoke of the CCM_SoftwareUpdatesManager.InstallUpdates with our found updates
$InstallReturn = Invoke-WmiMethod -Class CCM_SoftwareUpdatesManager -Name InstallUpdates -ArgumentList (,$MissingUpdatesReformatted) -Namespace root\ccm\clientsdk
"$system,Targeted Patches :$approvedUpdates,Pending patches:$pendingpatches,Reboot Pending patches :$rebootpending,initiated $pendingpatches patches for install" | Out-File $log -append
}
catch {"$System,pending patches - $pendingpatches but unable to install them ,please check Further" | Out-File $log -append }
}
else {"$system,Targeted Patches :$approvedUpdates,Pending patches:$pendingpatches,Reboot Pending patches :$rebootpending,Compliant" | Out-File $log -append }
Create a Server Device Collection
Every time I run this, I need to check to see that the group of servers I'm updating hasn't changed. Some may have been added to the environment, deleted, or switched to a different update group. I go to our server spreadsheet and copy/paste them into the text file I'm going to use. One server per line.
Next, I open the SCCM console, go to my server update group, and remove all machines from the group.
Then, I open up a SCCM PowerShell prompt from the blue dropdown arrow menu in the top left of the console.
Then I run this script (You will need to replace the names of the text file and device collection name in yellow below):
Get-Content "ES:\Group 1 Patching.txt" | foreach { Add-CMDeviceCollectionDirectMembershipRule -CollectionName "Servers - Group 1 Patching" -ResourceID (Get-CMDevice -Name $_).ResourceID }
This populates the device collection. once the servers are in there, make sure that the list is complete. You don't want to miss any servers, or run updates on a server that you aren't supposed to.
Once it looks good, right click on the device collection and run the script that installs all updates on the group.
Note: you can do this for any device collection of machines, or individual device. Creating a device collection of servers is related to monthly server patching. You could also do this with Win10/Win7 or any other windows based machines that are in SCCM.
0 comments:
Post a Comment
Note: Only a member of this blog may post a comment.