Last active
November 6, 2017 19:07
-
-
Save bklockwood/da0ca606e6c0f2bfc34f to your computer and use it in GitHub Desktop.
Simplified PSWU
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#requires -version 2.0 | |
function Get-UpdateList { | |
<# | |
.Synopsis | |
Gets list of updates from Windows Update. | |
.PARAMETER Criteria | |
The search criteria, see http://goo.gl/7nZSPs | |
Left at default, it will return all updates that have not yet | |
been installed, whether software or driver. Including Hidden | |
updates. | |
.NOTES | |
Returns an ISearchResult object (http://goo.gl/pvnUSM) named $ISearchResult | |
ISearchresult type - System.__ComObject#{d40cff62-e08c-4498-941a-01e25f0fd33c} | |
$ISearchResult.Updates contains an IUpdateCollection - http://goo.gl/8C2dbb | |
WU error codes: http://goo.gl/cSWDY8 | |
.EXAMPLE | |
Get-UpdateList | ft -AutoSize | |
ResultCode RootCategories Updates Warnings | |
---------- -------------- ------- -------- | |
2 System.__ComObject System.__ComObject System.__ComObject | |
.EXAMPLE | |
(Get-UpdateList).Updates.Count | |
40 | |
Shows that there are 40 updates available. | |
.EXAMPLE | |
(Get-UpdateList).Updates | select maxdownloadsize, title | ft -AutoSize | |
MaxDownloadSize Title | |
--------------- ----- | |
10123467 Update for Windows Server 2012 R2 (KB2884846) | |
948931 Security Update for Windows Server 2012 R2 (KB2876331) | |
517819 Security Update for Windows Server 2012 R2 (KB2892074) | |
376647 Update for Windows Server 2012 R2 (KB2917993) | |
#> | |
[CmdletBinding()] | |
Param | |
([Parameter(Mandatory=$false, ValueFromPipeline=$false, Position=0)] $Criteria = "IsInstalled=0") | |
try { | |
$Searcher = New-Object -ComObject Microsoft.Update.Searcher | |
$ISearchResult = $Searcher.Search($Criteria) | |
$ISearchResult | |
} catch { | |
Write-Error "ERROR in Get-UpdateList" | |
return $_ | |
} | |
} | |
Function Show-UpdateList { | |
<# | |
.Synopsis | |
Print a nice table of Updates not installed with some attribute info. | |
.Description | |
Columns: | |
THDRE | |
|||||- "E" if EULA accepted, "-" if not | |
||||-- "R" if reboot required, "-" if not (frequently wrong!) | |
|||--- "D" if the update has been downloaded, "-" if not | |
||---- "H" if the update is hiden, "-" if not | |
|----- "S" if software, "D" if driver | |
.TODO | |
They don't sort properly; | |
#> | |
[Cmdletbinding()] | |
Param([Parameter(Mandatory=$true,Position=0,ValueFromPipeline=$true)]$ISearchResult) | |
if ($ISearchResult.pstypenames -notcontains 'System.__ComObject#{d40cff62-e08c-4498-941a-01e25f0fd33c}') { | |
Write-Error "$ISearchResult is not an ISearchResult object (http://goo.gl/pvnUSM)" | |
break | |
} | |
Write-Output "$($ISearchResult.Updates.Count) updates available:" | |
$ISearchResult.Updates | | |
Select @{n='KB';e={$_.KbArticleIds}}, | |
#Update type 1 is software, type 2 is driver. http://goo.gl/VvV7tt | |
@{n='T';e={if ($_.Type -eq 1) {"S"} ElseIf ($_.Type -eq 2) {"D"}}}, | |
@{n='H';e={if ($_.isHidden) {"H"} Else {"-"}}}, | |
@{n='D';e={if ($_.isDownloaded) {"D"} Else {"-"}}}, | |
@{n='R';e={if ($_.Rebootrequired) {"R"} Else {"-"}}}, | |
@{n='E';e={if ($_.EulaAccepted) {"E"} Else {"-"}}}, | |
@{n='MB';e={'{0:N0}' -f ($_.MaxDownloadSize/1MB)}}, | |
@{n='Severity';e={$_.MsrcSeverity}}, | |
@{n='Published';e={$_.LastDeploymentChangeTime.ToShortDateString()}}, | |
#@{n='UID';e={$_.Identity.UpdateID}}, | |
#truncate title to 40 chars | |
@{n='Title';e={ if ($($_.Title.Length) -lt 40) {$_.Title} else {$($_.Title.Substring(0,37)) + "..."}}} | | |
Sort -Property $_.LastDeploymentChangeTime | ft -AutoSize |out-string | |
} | |
function Install-Update { | |
<# | |
.SYNOPSIS | |
Downloads and installs updates | |
.NOTES | |
Uses IUpdateDownloader http://goo.gl/hPK49j | |
and IUpdateInstaller http://goo.gl/jeDijU | |
WU error codes: http://goo.gl/cSWDY8 | |
#> | |
[CmdletBinding()] | |
Param ( | |
[parameter(Mandatory=$true, ValueFromPipeline=$true)]$ISearchResult, | |
[parameter(Mandatory=$false, ValueFromPipeline=$true)][switch]$OneByOne | |
) | |
if ($ISearchResult.pstypenames -notcontains 'System.__ComObject#{d40cff62-e08c-4498-941a-01e25f0fd33c}') { | |
Write-Error "$ISearchResult is not an ISearchResult object (http://goo.gl/pvnUSM)" | |
break | |
} | |
$DesiredUpdates = New-Object -ComObject Microsoft.Update.UpdateColl | |
$counter = 0 | |
foreach ($u in $ISearchResult.Updates) { | |
$u.AcceptEula() | |
if (!$($u.IsHidden) -and !$($u.Rebootrequired)) { | |
$counter++ | |
$DesiredUpdates.Add($u) |out-null | |
} | |
#Used for debugging. One update at a time. | |
if ($OneByOne) { | |
if ($counter -gt 1) {break} | |
} | |
} | |
If ($DesiredUpdates.Count -lt 1) { | |
Write-Verbose "No updates to install!" | |
} else { | |
Write-Verbose "Downloading and installing $($DesiredUpdates.Count) updates" | |
$Downloader = New-Object -ComObject Microsoft.Update.Downloader | |
$Downloader.Updates = $DesiredUpdates | |
$DownloadResult = $Downloader.Download() | |
#Resultcode 2-success, 3-success with errors. | |
#Using -contains instead of -in for PS v2 compat | |
if (2,3 -notcontains $DownloadResult.ResultCode) { | |
Write-Error "Downloader error HResult $($DownloadResult.HResult), resultcode $($DownloadResult.ResultCode)" | |
} else { | |
if ($DownloadResult.ResultCode -eq 3) {Write-Verbose "Downloaded with errors; beginning install."} | |
if ($DownloadResult.ResultCode -eq 2) {Write-Verbose "Downloaded successfully; beginning install."} | |
$Installer = New-Object -ComObject Microsoft.Update.Installer | |
$Installer.Updates = $DesiredUpdates | |
$InstallResult = $Installer.Install() | |
switch ($InstallResult.ResultCode) { | |
2 {Write-Verbose "Installed updates successfully."} | |
3 {Write-Verbose "Installed updates swith errors."} | |
default {Write-Error "Installer error $($InstallResult.HResult),resultcode $($InstallResult.ResultCode)"} | |
} | |
} | |
} | |
} | |
Get-UpdateList -Criteria "IsInstalled=0 AND RebootRequired=0 AND BrowseOnly=0 AND Type='Software'" | Install-Update |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
this version of PSWU only downloads and installs those updates which claim they won't need a reboot.
see https://goo.gl/7nZSPs for better understanding of the criteria on last line