WSUS approve patches/update with specific criteria via powershell

There is a lot happening in this script so I will try to cover as much as possible. This scripts goes through and approves and decline updates/patches that meet a specific criteria, if it does not meet the criteria it will leave the updates/patches in an unapproved state. The reason I need to come up with this scripts was because the amount of time that it was taking me each month to got through each patch and see if it was applicable to our environment was taking far too long. We do not have any Itanium based servers, we only have 32 bit of windows server 2003, and 64 bit of windows server 2008. This script will let you first run a report of the list of patches that will be approved and declined. After your verify that your list is applicable to your criteria you can then run the approve option. This will approve and decline patches for computers in the “All Computers” group. If you need to get more granular than that I suggest you take a look at the $group variable and be sure that you get the specific computer group that you need.

$caption = "Choose Option";
$message = "What would you like to do with new updates?";
$report = new-Object System.Management.Automation.Host.ChoiceDescription "&Report Patches","Report";
$approve = new-Object System.Management.Automation.Host.ChoiceDescription "&Approve/Decline Patches","Approve";
$choices = [System.Management.Automation.Host.ChoiceDescription[]]($approve,$report);
$answer = $host.ui.PromptForChoice($caption,$message,$choices,0)
#$answer 0=approve 1=report
##FINAL SCRIPT
$wsusserver = "YOUR IP ADDRESS OR SERVERNAME"
##Load required assemblies
[void][reflection.assembly]::LoadWithPartialName("Microsoft.UpdateServices.Administration")
$wsus = [Microsoft.UpdateServices.Administration.AdminProxy]::getUpdateServer($wsusserver,$False,8530)
##Retriving "All Computers" Group information
$group = $wsus.GetComputerTargetGroups() | where {$_.Name -eq 'All Computers'}
##Retriving list of unapproved updates
$updates = $wsus.GetUpdates()  | where {$_.IsApproved -eq $False -and $_.IsDeclined -eq $False}
########################################
#Itanium Updates
########################################
##Retrive a subset of updates where IA64 is in the legacyname
$IAUpdates = $updates | where {($_.LegacyName -like '*IA64*')}
Foreach ($IAUpdate in $IAUpdates) {
    switch ($answer){
        0 {$IAUpdate.Decline(); $msgDeclined = $msgDeclined + $IAUpdate.SecurityBulletins + "`t" + $IAUpdate.MsrcSeverity + "`t" + $IAUpdate.Title + "`n";break}
        1 {$msgDeclined = $msgDeclined + $IAUpdate.SecurityBulletins + "`t" + $IAUpdate.MsrcSeverity + "`t" + $IAUpdate.Title + "`n";break}
    }
    ##Uncomment the next line to check updates that are in an incorrect state
    #If ($IAUpdate.IsDeclined -ne "True") {$msgCheckTheseUpdates = $msgCheckTheseUpdates + $IAUpdate.Title + "`n"}
}
########################################
#Windows Security Updates Critical
########################################
##Revise list of unapproved updates
$updates = $wsus.GetUpdates()  | where {$_.IsApproved -eq $False -and $_.IsDeclined -eq $False}
##Retrive a subset of updates that are security updates and are of the windows family and have a MSRC serverity of Critical
$WSecCriticalUpdates = $updates | where {$_.UpdateClassificationTitle -eq 'Security Updates' -and $_.ProductFamilyTitles -like 'Windows' -and $_.MsrcSeverity -eq 'Critical'}
Foreach ($WSecCriticalUpdate in $WSecCriticalUpdates) {
    If ($WSecCriticalUpdate.LegacyName -like "*x64*" -and ($WSecCriticalUpdate.ProductTitles -like "*2008*") -or ($WSecCriticalUpdate.ProductTitles -like "*2012 R2*")) {
            switch ($answer) {
                0 {$WSecCriticalUpdate.Approve('Install',$group); $msgApproved = $msgApproved + $WSecCriticalUpdate.SecurityBulletins + "`t" + $WSecCriticalUpdate.MsrcSeverity + "`t" + $WSecCriticalUpdate.Title + "`n";break}
                1 {$msgApproved = $msgApproved + $WSecCriticalUpdate.SecurityBulletins + "`t" + $WSecCriticalUpdate.MsrcSeverity + "`t" + $WSecCriticalUpdate.Title + "`n";break}
            }
            ##Uncomment the next line to check updates that are in an incorrect state
            #If ($WSecCriticalUpdate.IsApproved -ne "True"){$msgCheckTheseUpdates = $msgCheckTheseUpdates + $WSecCriticalUpdate.Title + "`n"}
    }elseif ($WSecCriticalUpdate.LegacyName -like "*x86*" -and $WSecCriticalUpdate.ProductTitles -like "*2003*") {
            switch ($answer) {
                0 {$WSecCriticalUpdate.Approve('Install',$group); $msgApproved = $msgApproved + $WSecCriticalUpdate.SecurityBulletins + "`t" + $WSecCriticalUpdate.MsrcSeverity + "`t" + $WSecCriticalUpdate.Title + "`n";break}
                1 {$msgApproved = $msgApproved + $WSecCriticalUpdate.SecurityBulletins + "`t" + $WSecCriticalUpdate.MsrcSeverity + "`t" + $WSecCriticalUpdate.Title + "`n";break}
            }
            ##Uncomment the next line to check updates that are in an incorrect state
            #If ($WSecCriticalUpdate.IsApproved -ne "True"){$msgCheckTheseUpdates = $msgCheckTheseUpdates + $WSecCriticalUpdate.Title + "`n"}
    }else {
        switch ($answer) {
            0 {$WSecCriticalUpdate.Decline(); $msgDeclined + $WSecCriticalUpdate.SecurityBulletins + "`t" + $WSecCriticalUpdate.MsrcSeverity + "`t" + $WSecCriticalUpdate.Title + "`n";break}
            1 {$msgDeclined = $msgDeclined + $WSecCriticalUpdate.SecurityBulletins + "`t" + $WSecCriticalUpdate.MsrcSeverity + "`t" + $WSecCriticalUpdate.Title + "`n";break}
        }
        ##Uncomment the next line to check updates that are in an incorrect state
        #If ($WSecCriticalUpdate.IsDeclined -ne "True"){$msgCheckTheseUpdates = $msgCheckTheseUpdates + $WSecCriticalUpdate.Title + "`n"}
    }
}
########################################
#Windows Security Updates 1 month old
########################################
##Revise list of unapproved updates
$updates = $wsus.GetUpdates()  | where {$_.IsApproved -eq $False -and $_.IsDeclined -eq $False}
##Retrive a subset of updates that are security updates and are of the windows family and DO NOT have a MSRC serverity of Critical
$WSecNoneCriticalUpdates = $updates | where {$_.UpdateClassificationTitle -eq 'Security Updates' -and $_.ProductFamilyTitles -like 'Windows' -and $_.MsrcSeverity -ne 'Critical'}
Foreach ($WSecNoneCriticalUpdate in $WSecNoneCriticalUpdates) {
    If ($WSecNoneCriticalUpdate.LegacyName -like "*x64*" -and ($WSecNoneCriticalUpdate.ProductTitles -like "*2008*") -or ($WSecNoneCriticalUpdate.ProductTitles -like "*2012 R2*")) {
            ##Getting the createdate of each update and storing it in a variable that can be calculated later
            [datetime]$CreationDate = ($WSecNoneCriticalUpdate).CreationDate
            ##If the update is more than 27 day old it will approve
            If ($CreationDate -le (Get-Date).AddDays(-27)) {
                switch ($answer){
                    0 {$WSecNoneCriticalUpdate.Approve('Install',$group);$msgApproved = $msgApproved + $WSecNoneCriticalUpdate.SecurityBulletins + "`t" + $WSecNoneCriticalUpdate.MsrcSeverity + "`t" + $WSecNoneCriticalUpdate.Title + "`n";break}
                    1 {$msgApproved = $msgApproved + $WSecNoneCriticalUpdate.SecurityBulletins + "`t" + $WSecNoneCriticalUpdate.MsrcSeverity + "`t" + $WSecNoneCriticalUpdate.Title + "`n";break}
                }
            }
    }elseif ($WSecNoneCriticalUpdate.LegacyName -like "*x86*" -and $WSecNoneCriticalUpdate.ProductTitles -like "*2003*") {
        ##Getting the createdate of each update and storing it in a variable that can be calculated later
        [datetime]$CreationDate = ($WSecNoneCriticalUpdate).CreationDate
        ##If the update is more than 27 day old it will approve
        If ($CreationDate -le (Get-Date).AddDays(-27)) {
            switch ($answer){
                    0 {$WSecNoneCriticalUpdate.Approve('Install',$group);$msgApproved = $msgApproved + $WSecNoneCriticalUpdate.SecurityBulletins + "`t" + $WSecNoneCriticalUpdate.MsrcSeverity + "`t" + $WSecNoneCriticalUpdate.Title + "`n";break}
                    1 {$msgApproved = $msgApproved + $WSecNoneCriticalUpdate.SecurityBulletins + "`t" + $WSecNoneCriticalUpdate.MsrcSeverity + "`t" + $WSecNoneCriticalUpdate.Title + "`n";break}
            }
        }
    }else {
        switch ($answer){
            0 {$WSecNoneCriticalUpdate.Decline(); $msgDeclined = $msgDeclined + $WSecNoneCriticalUpdate.SecurityBulletins + "`t" + $WSecNoneCriticalUpdate.MsrcSeverity + "`t" + $WSecNoneCriticalUpdate.Title + "`n";break}
            1 {$msgDeclined = $msgDeclined + $WSecNoneCriticalUpdate.SecurityBulletins + "`t" + $WSecNoneCriticalUpdate.MsrcSeverity + "`t" + $WSecNoneCriticalUpdate.Title + "`n";break}
        }
    }
}
########################################
#Windows Recommended Updates 1 month old
########################################
##Revise list of unapproved updates
$updates = $wsus.GetUpdates()  | where {$_.IsApproved -eq $False -and $_.IsDeclined -eq $False}
##Retrive a subset of updates that are updates and are of the windows family
$WRecommendedUpdates = $updates | where {$_.UpdateClassificationTitle -eq 'Updates' -and $_.ProductFamilyTitles -like 'Windows'}
Foreach ($WRecommendedUpdate in $WRecommendedUpdates) {
    If ($WRecommendedUpdate.LegacyName -like "*x64*" -and ($WRecommendedUpdate.ProductTitles -like "*2008*") -or ($WRecommendedUpdate.ProductTitles -like "*2012 R2*")) {
        ##Getting the createdate of each update and storing it in a variable that can be calculated later
        [datetime]$CreationDate = ($WRecommendedUpdate).CreationDate
        ##If the update is more than 27 day old it will approve
        If ($CreationDate -le (Get-Date).AddDays(-27)) {
            switch ($answer) {
                0 {$WRecommendedUpdate.Approve('Install',$group); $msgApproved = $msgApproved + $WRecommendedUpdate.SecurityBulletins + "`t      " + $WRecommendedUpdate.MsrcSeverity + "`t" +  $WRecommendedUpdate.Title + "`n";break}
                1 {$msgApproved = $msgApproved + $WRecommendedUpdate.SecurityBulletins + "`t      " + $WRecommendedUpdate.MsrcSeverity + "`t" +  $WRecommendedUpdate.Title + "`n";break}
            }
        }
    }elseif ($WRecommendedUpdate.LegacyName -like "*x86*" -and $WRecommendedUpdate.ProductTitles -like "*2003*") {
        ##Getting the createdate of each update and storing it in a variable that can be calculated later
        [datetime]$CreationDate = ($WRecommendedUpdate).CreationDate
        ##If the update is more than 27 day old it will approve
        If ($CreationDate -le (Get-Date).AddDays(-27)) {
            switch ($answer) {
                0 {$WRecommendedUpdate.Approve('Install',$group); $msgApproved = $msgApproved + $WRecommendedUpdate.SecurityBulletins + "`t      " + $WRecommendedUpdate.MsrcSeverity + "`t" +  $WRecommendedUpdate.Title + "`n";break}
                1 {$msgApproved = $msgApproved + $WRecommendedUpdate.SecurityBulletins + "`t      " + $WRecommendedUpdate.MsrcSeverity + "`t" +  $WRecommendedUpdate.Title + "`n";break}
            }
        }
    }else {
        switch ($answer) {
            0 {$WRecommendedUpdate.Decline();  $msgDeclined = $msgDeclined + $WRecommendedUpdate.SecurityBulletins + "`t      " + $WRecommendedUpdate.MsrcSeverity + "`t" +  $WRecommendedUpdate.Title + "`n";break}
            1 {$msgDeclined = $msgDeclined + $WRecommendedUpdate.SecurityBulletins + "`t      " + $WRecommendedUpdate.MsrcSeverity + "`t" +  $WRecommendedUpdate.Title + "`n";break}
        }
    }
}
########################################
#Windows Office Updates 1 month old
########################################
##Revise list of unapproved updates
$updates = $wsus.GetUpdates()  | where {$_.IsApproved -eq $False -and $_.IsDeclined -eq $False}
##Retrive a subset of updates that are updates and are of the windows family
$WOfficeUpdates = $updates | where {($_.UpdateClassificationTitle -eq 'Updates' -or $_.UpdateClassificationTitle -eq 'Security Updates') -and $_.ProductTitles -like '*Office 2*' -and $_.Title -notlike '*Share*'}
Foreach ($WOfficeUpdate in $WOfficeUpdates) {
    [datetime]$CreationDate = ($WOfficeUpdate).CreationDate
    ##If the update is more than 27 day old it will approve
    If ($CreationDate -le (Get-Date).AddDays(-27)) {
        switch ($answer) {
            0 {$WOfficeUpdate.Approve('Install',$group); $msgApproved = $msgApproved + $WOfficeUpdate.SecurityBulletins + "`t" + $WOfficeUpdate.MsrcSeverity + "`t" +  $WOfficeUpdate.Title + "`n"; break}
            1 {$msgApproved = $msgApproved + $WOfficeUpdate.SecurityBulletins + "`t" + $WOfficeUpdate.MsrcSeverity + "`t" +  $WOfficeUpdate.Title + "`n"; break}
        }
    }
}
##Sending EMAIL
$month = get-date -Format MMMM
switch($answer){
    0 {send-mailmessage -to patchingreports@example.com -subject "Updates Approve/Declined for $month" -body "Approved Updates`n $msgApproved`nDeclined Updates`n $msgDeclined"  -smtpserver "mailserver.example.com" -from WSUSServer@example.com;break}
    1 {send-mailmessage -to patchingreports@example.com -subject "Updates Reports for $month" -body "Approved Updates`n $msgApproved`nDeclined Updates`n $msgDeclined"  -smtpserver "mailserver.example.com" -from WSUSServer@example.com;break}
}
exit

Feel free to modify this script as needed for you environment. Leave a comment if you have any questions. Have fun and happy scripting.
As always with powershell be sure your Set-ExecutionPolicy is set to remotesigned if you want the local script to run.