Public/Get-SPSqlPatch.ps1
function Get-SPSqlPatch { <# .SYNOPSIS This function is used to get SQL Server patches info and return it as a PSObject .DESCRIPTION The function accesses a google excel sheet provided by "https://sqlserverbuilds.blogspot.com" which contains a list of all SQL Server patches available for each SQL Version. The function then parses the table and converts it into a PSObject, with parameters such as Cumlative Update and Service Pack download links. .PARAMETER SqlVersion The SQL Version you want to search for. If not specified the function returns patches for default SQL Versions "2008", "2008 R2", "2012", "2014", "2016", "2017", "2019" .EXAMPLE PS C:\> Get-SPSqlPatch Returns all available patches listed on "https://sqlserverbuilds.blogspot.com" for default SQL Versions "2008", "2008 R2", "2012", "2014", "2016", "2017", "2019" .EXAMPLE PS C:\> Get-SPSqlPatch -SqlVersion "2017", "2016" Returns all SQL patches available for SQL Server 2017 and SQL Server 2016 .NOTES Author: Patrick Cull Date: 2020-03-23 #> [Cmdletbinding()] param( [string[]] $SqlVersion = @("2008", "2008 R2", "2012", "2014", "2016", "2017", "2019") ) #Setup proxy credentials in case they're needed. $browser = New-Object System.Net.WebClient $browser.Proxy.Credentials =[System.Net.CredentialCache]::DefaultNetworkCredentials [Net.ServicePointManager]::SecurityProtocol = [Net.SecurityProtocolType]::Tls12 $PatchListURL = "https://docs.google.com/spreadsheets/d/16Ymdz80xlCzb6CwRFVokwo0onkofVYFoSkc7mYe6pgw/gviz/tq?tq=&tqx=out:csv" $DocOutput= Invoke-WebRequest $PatchListURL | ConvertFrom-Csv $RelevantPatches = $DocOutput | Select-Object SQLServer, SP, CU, Build, Description, Link, ReleaseDate | Where-Object {(($_.SP -or $_.CU) -or $_.Description -like '*GDR*') -and $_.Link -and $_.ReleaseDate } if($SqlVersion) { $RelevantPatches = $RelevantPatches | Where-Object SQLServer -in $SqlVersion } #Reverse the array so we can pick up the service packs as it gets scanned and we can assign it to each following CU. [array]::reverse($RelevantPatches) $RelevantPatches | Foreach-Object { $SqlRelease = $_.SQLServer $BuildNum = $_.Build if($_.SP -eq 'TRUE') { $PatchType = "Service Pack" } elseif($_.CU -eq 'TRUE'){ $PatchType = "Cumulative Update" } else { $PatchType = "Hotfix" } try { $ReleaseDate = [datetime]::parseexact($_.ReleaseDate, 'yyyy-MM-dd', $null) } catch { $ReleaseError = $_.ReleaseDate Write-Error "$ReleaseError of $BuildNum not valid date" } $PatchNumPattern = "\((.*?)\)" $PatchNumber = [regex]::match($_.Description, $PatchNumPattern).Groups[1].Value if($SqlRelease -gt 2016) { $ServicePack = $null $CumulativeUpdate = $PatchNumber } elseif($PatchType -eq "Service Pack") { $ServicePack = $PatchNumber $CumulativeUpdate = $null } else { $CumulativeUpdate = $PatchNumber } $DownloadLink = $_.Link $KBNumber = $DownloadLink -split '/' | Where-Object {$_ -match "^[\d\.]+$"} #If the KB number is not in the URL, attempt to access the downloadlink and parse the KB number from the resulting webpage. if(!$KBNumber) { $ProgressPreference = 'SilentlyContinue' try { $KBDownloadResponse = Invoke-WebRequest -Uri $DownloadLink -UseBasicParsing } catch { #Write-Error "Error connecting to build $BuildNum link: $DownloadLink - KB Number was not attainable." #Error checking dead links } $ProgressPreference = 'Continue' $KBLinkContent = $KBDownloadResponse.Content $KBNumberPattern = "KB(.*?)-x64" $KBNumber = [regex]::match($KBLinkContent, $KBNumberPattern).Groups[1].Value if($KBNumber -eq ""){$KBNumber = $null} } [PSCustomObject][Ordered] @{ SqlVersion = $SqlRelease PatchType = $PatchType ServicePack = $ServicePack CumulativeUpdate = $CumulativeUpdate ReleaseDate = $ReleaseDate Build = $_.Build Link = $DownloadLink KBNumber = $KBNumber Description = $_.Description } } } |