Skip to content

Instantly share code, notes, and snippets.

@markgodiy
Created August 21, 2023 13:06
Show Gist options
  • Select an option

  • Save markgodiy/a8e5c830d861ea9ab5eb070450d16dfc to your computer and use it in GitHub Desktop.

Select an option

Save markgodiy/a8e5c830d861ea9ab5eb070450d16dfc to your computer and use it in GitHub Desktop.
Get-SCCMPendingPatches
<#
.DESCRIPTION
Author: Mark Go
PowerShell script designed to check for pending patches available via SCCM (System Center Configuration Manager). It provides the ability to retrieve pending patch information for specified remote computers and can be used to identify patches that need to be installed. The script also includes the option to automatically start the WinRM service on target hosts if necessary.
.EXAMPLE
Get-SCCMPendingPatches SERVER01 -Verbose
Get pending patches for a specific computer
.EXAMPLE
$computers = "PC01","SERVER01","192.168.1.101"
PS C:\>$sccmstatus = @(Get-SCCMPendingPatches -ComputerName $computers)
or
PS C:\>[array]$sccmstatus = Get-SCCMPendingPatches -ComputerName $computers
Get pending patches for a list of computers and store the results in an array
.EXAMPLE
Get-Content "C:\path\to\computers.txt" | Get-SCCMPendingPatches
Get pending patches for a list of computers using a text file
.EXAMPLE
Get-SCCMPendingPatches SERVER01 | % {Get-KbUpdate -Name $_.Name -Latest}
Get more detailed information about the patch by pipelining into Get-KBUpdate cmdlet from the kbupdate module, https://github.com/potatoqualitee/kbupdate.
To install kbupdate module: (Admin required) "Install-Module kbupdate;Import-Module kbupdate"
#>
function Get-SCCMPendingPatches {
[CmdletBinding()]
param (
[Parameter(ValueFromPipeline = $true)][String[]]$ComputerName = $env:COMPUTERNAME
)
function Start-WinRMService {
param (
[string]$Computer
)
try {
Write-Verbose "Checking WinRM service status on $Computer"
$serviceStatus = Get-Service -ComputerName $Computer -Name WinRM -ErrorAction Stop | Select-Object -ExpandProperty Status
if ($serviceStatus -eq "Stopped") {
Write-Verbose "Starting WinRM service on $Computer"
Start-Service -Name WinRM -ComputerName $Computer -ErrorAction Stop
Write-Verbose "WinRM service started successfully on $Computer"
}
else {
Write-Verbose "WinRM service is already running on $Computer"
}
}
catch {
Write-Verbose "Failed to start WinRM service on $Computer - $_"
}
}
foreach ($Computer in $ComputerName) {
if ($Computer -as [System.Net.IPAddress]) {
# Resolving IPv4 to hostname
try {
$resolvedComputer = (Resolve-DnsName -Name $Computer -ErrorAction Stop).NameHost.Split('.')[0]
$resolvedComputer = $resolvedComputer.ToUpper() # Convert computer name to uppercase
Write-Verbose "Resolved $Computer --> Hostname: $resolvedComputer "
} catch {
$resolvedComputer = $Computer
}
} else {
$resolvedComputer = $Computer
}
Write-Verbose "Getting pending patches for computer: $resolvedComputer"
try {
# Test if the host is reachable using Test-Connection
if (Test-Connection -ComputerName $resolvedComputer -Count 1 -ErrorAction Stop) {
$namespace = "root\ccm\clientsdk"
$class = "CCM_SoftwareUpdate"
$patches = Get-CimInstance -ComputerName $resolvedComputer -Namespace $namespace -ClassName $class |
Where-Object { $_.ComplianceState -eq "0" }
if ($patches) {
$patches | ForEach-Object {
$_ | Add-Member -MemberType NoteProperty -Name "ComputerName" -Value $resolvedComputer -PassThru
} | Select-Object ComputerName, @{Name = "Article"; Expression = { "KB$($_.ArticleID)" } }, Name, Description, URL
}
else {
Write-Verbose "No patches required for computer: $resolvedComputer"
}
}
else {
Write-Verbose "Unable to establish connection with remote host: $resolvedComputer"
Start-WinRMService -Computer $resolvedComputer
}
}
catch {
Write-Verbose "Error connecting to remote host: $resolvedComputer - $_"
}
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment