<#
.SYNOPSIS
WSUS_AutomaticApprovals.ps1 - Script that does automatic approvals for Pilot and Standard groups in intervals.

.DESCRIPTION
Script helps in approval cycle - approving updates firstly to defined "pilot" groups, and later after certain time, appying these to "standard" groups, and doing new approval for "pilot".

Pilot groups need to have "pilot" in name, as the same standard need to have "standard".

HOW IT WORKS:
Script checks if relevant .csv file exists.

If CSV does NOT exist (if dry run):
Script does approval process just for pilot group.

if CSV exists:
Script checks what was the last time span for updates approved to a "pilot" group.
For that time span it does approval for "standard" targer groups.
Second approval cycle is being done on "pilot" target groups (start time: last sync time, end time: date the sript is triggered)

.OUTPUTS
Verbose option
CSV file

.PARAMETER range
Parameter needed for specifiyng scope of target groups - in this example "Servers" and "Workstations"

.PARAMETER verbose
Gemerates detailed output on the screen.

.EXAMPLE
.\WSUS_AutomaticApprovals.ps1 -range "Servers" -Verbose
This command will do updates on all target groups with "Servers" in name, write everything to CSV file and show detailed information on the screen.

.EXAMPLE
.\WSUS_AutomaticApprovals.ps1 -Range "Workstations"
This command will do updates on all target groups with "Workstations" in name and write everything to CSV file.

.LINK
https://paweljarosz.wordpress.com/2016/12/20/powershell-script-for-auto-approving-wsus-updates-for-pi

.NOTES
Written By: Pawel Jarosz
Website:    http://paweljarosz.wordpress.com
GitHub:     https://github.com/zaicnupagadi
Technet:    https://gallery.technet.microsoft.com/scriptcenter/site/mydashboard


Change Log
V1.00, 20/12/2016 - Initial version

#>

PowerShell
Edit|Remove
Param( 
  [Parameter(Mandatory=$true, HelpMessage="Available switches are 'Workstations' or 'Servers'")] [string]$range 
 
) 
 
Function ApproveUpdates ($TargetGroup$StartDate$EndDate$Range) { 
$report = @() 
 
$Current_Date_Formated = (get-date -Format ‘MM\/dd\/yyyy’) 
$Next_Approval_Date_Raw = (Get-Date).AddDays(14) 
$Next_Approval_Date_Formated = '{0:MM\/dd\/yyyy}' -$Next_Approval_Date_Raw 
 
$updatescope = New-Object Microsoft.UpdateServices.Administration.UpdateScope 
 
ForEach ($TG in $TargetGroup) { 
 
$updatescope.FromCreationDate = $StartDate 
$updatescope.ToCreationDate = $EndDate 
 
$Number_Of_Updates = ($wsus.GetUpdates($UpdateScope| Measure-Object).count 
 
    $wsus.GetUpdates($UpdateScope| ForEach { 
 
      Write-Verbose ("Approving {0} for {1}" -$_.Title,$TG.Name) 
        if($_.RequiresLicenseAgreementAcceptance) { 
        $_.AcceptLicenseAgreement() 
        Write-Verbose -Message "License accepted for $($_.Title)" -Verbose 
        } 
      $_.Approve('Install',$TG| Out-Null 
      } 
 
    $obj = [PSCustomObject]@{ 
    UpdateRange = $Range 
    TargetGroupName = $TG.Name 
    StartPatchDate = $StartDate 
    EndPatchDate = $EndDate 
    NumberOfUpdates = $Number_Of_Updatess 
    CurrentDate = $Current_Date_Formated 
    NextApprovalDate = $Next_Approval_Date_Formated 
} 
$report +$obj 
} 
$report | export-csv $CSVFile -Delimiter ";" -Append 
} 
 
 
if ($range -eq "Workstations" -or $range -eq "Servers"){ 
 
Write-Verbose "Process of updates approval for $range has been triggered..." 
 
$wsus = Get-WsusServer 
$CSVFileName = $range+"UpdateTimes.csv" 
$CSVPath = 'c:\' 
$CSVFile = "$CSVPath$CSVFileName" 
 
$Current_Date = (get-date -Format ‘MM\/dd\/yyyy’) 
 
    if (!(Test-Path $CSVFile)) { 
 
    Write-Verbose "File $CSVFileName does not exist i given path, starting initial approval..." 
    $InitialApproval = $true 
    $Group = $wsus.GetComputerTargetGroups() | where {$_.Name -match "$range" -and $_.Name -match "Pilot" } 
    Write-Verbose "Starting approval of updates for time range 01/01/2016 -" $Current_Date 
 
    Write-Verbose "Starting approval of Pilot groups for period 01/01/2000 - "$Current_Date 
    ApproveUpdates $Group "01/01/2000" $Current_Date $range 
 
    } else { 
 
    Write-Verbose "File $CSVFileName exists, importing..." 
    $ImportCsv = Import-Csv $CSVFile -Delimiter ";" 
 
    $PilotLastSyncRecords = $ImportCsv | ? {$_.TargetGroupName -match "Pilot"| sort { [datetime]$_.NextApprovalDate } -Descending 
 
    if ($Current_Date -eq $PilotLastSyncRecords[0].NextApprovalDate){ 
 
    $SPD = $PilotLastSyncRecords[0].StartPatchDate 
    $EPD = $PilotLastSyncRecords[0].EndPatchDate 
    $CPD = $PilotLastSyncRecords[0].CurrentDate 
 
    Write-Verbose "Last time of synchronization time was $CPD" 
 
    $GroupPilot = $wsus.GetComputerTargetGroups() | where {$_.Name -match "$range" -and $_.Name -match "Pilot" } 
    $GroupStandard = $wsus.GetComputerTargetGroups() | where {$_.Name -match "$range" -and $_.Name -match "Standard" } 
     
    Write-Verbose "Starting approval of Standard groups for period $SPD  - $EPD" 
    ApproveUpdates $GroupStandard $SPD $EPD $range 
 
    Write-Verbose "Starting approval of Pilot groups for period $EPD - $Current_Date" 
    ApproveUpdates $GroupPilot $EPD $Current_Date $range 
     
    } else { 
    Write-Output "Today is not the day of next approval cycle." 
    } 
     
    } 
 
} else { 
write-Output "Wrong 'range' parameter has been provided, it should be 'Servers' either 'Workstations'." 
}