Skip to main content

Automate Your Lab - Part 6 - WSUS

·458 words·
Automate Your Lab - This article is part of a series.
Part 6: This Article

I have a very slow internet connection at home and need a WSUS server in my lab to save bandwidth and time. To automate WSUS you need PowerShell and an executable.

As in all my scripts in this series you can customize the installation with variables. In order to install WSUS we need only two, one which specifies the partition and one for the folder where WSUS files should be stored. If the folder does not exist the script will create it for you. I recommend not to use the partition C: as WSUS needs a lot of space for saving all Windows update files.

Install-LabWSUS.ps1:

<#
     .SYNOPSIS
     This script will install Windows Server Update Services (WSUS) in your lab

     .NOTES
     You need a Windows Server 2012 R2 for this script to work.
     This script is part of a series to automate your lab on www.dominikbritz.com
#>

#Requires -Version 3
#Requires -RunAsAdministrator

###
### Variables
###
$WSUSPartition = 'E:'
$WSUSFolder = 'WSUS'
$Products = @("Windows Server 2012 R2")

###
### Script
###
Try
{
    If (-not (Test-Path $(Join-Path $WSUSPartition $WSUSFolder)))
    {
        New-Item -Path $WSUSPartition -Name $WSUSFolder -ItemType Directory
    }
    Write-Output "Start WSUS installation"
    Install-WindowsFeature -Name UpdateServices -IncludeManagementTools
    Start-Process $(Join-Path $env:ProgramFiles 'Update Services\Tools\wsusutil.exe') -Argumentlist "postinstall CONTENT_DIR=$(Join-Path $WSUSPartition $WSUSFolder)" -Wait

    Write-Output "Start WSUS configuration"
    $WSUS = Get-WSUSServer
    $WSUSConfig = $WSUS.GetConfiguration()
    Set-WsusServerSynchronization -SyncFromMU
    $WSUSConfig.AllUpdateLanguagesEnabled = $false
    $WSUSConfig.SetEnabledUpdateLanguages("en")
    $WSUSConfig.Save()
    $Subscription = $WSUS.GetSubscription()
    $Subscription.StartSynchronizationForCategoryOnly()

    While ($Subscription.GetSynchronizationStatus() -ne 'NotProcessing') {
        Write-Host "." -NoNewline
        Start-Sleep -Seconds 5
    }

    Get-WsusServer | Get-WsusProduct | Where-Object -FilterScript {$_.product.title -match "Office"} | Set-WsusProduct -Disable
    Get-WsusServer | Get-WsusProduct | Where-Object -FilterScript {$_.product.title -match "Windows"} | Set-WsusProduct -Disable

    Foreach ($Product in $Products)
    {
        Get-WsusServer | Get-WsusProduct | Where-Object -FilterScript {$_.product.title -match $Product} | Set-WsusProduct
    }

    Get-WsusClassification | Where-Object {
        $_.Classification.Title -in (
        'Critical Updates',
        'Definition Updates',
        'Feature Packs',
        'Security Updates',
        'Service Packs',
        'Update Rollups',
        'Updates',
        'Upgrades')
    } | Set-WsusClassification

    $Subscription.SynchronizeAutomatically=$true

    Write-Output "Set synchronization scheduled for midnight each night"
    $Subscription.SynchronizeAutomaticallyTimeOfDay= (New-TimeSpan -Hours 0)
    $Subscription.NumberOfSynchronizationsPerDay=1
    $Subscription.Save()

    Write-Output "Kick Off Synchronization"
    $Subscription.StartSynchronization()
    Write-Output "Sleep a minute"
    Start-Sleep -Seconds 60

    Write-Output "Monitor Progress of Synchronisation"
    While ($Subscription.GetSynchronizationProgress().ProcessedItems -ne $Subscription.GetSynchronizationProgress().TotalItems) {
	    Write-Host "." -NoNewline
        Start-Sleep -Seconds 5
    }

    Write-Output "Load .NET assembly"
    [void][reflection.assembly]::LoadWithPartialName("Microsoft.UpdateServices.Administration")
    $count = 0

    Write-Output "Connect to WSUS Server"
    $updateServer = [Microsoft.UpdateServices.Administration.AdminProxy]::getUpdateServer($env:COMPUTERNAME,$false,8530)

    Write-Output "Decline superseded updates"

    $updatescope = New-Object Microsoft.UpdateServices.Administration.UpdateScope
    $Updates=$updateServer.GetUpdates($updatescope)

    foreach ($Update in $Updates )
    {
        if ($Update.IsSuperseded -eq 'True')
        {
            $Update.Decline()
            $count=$count + 1
        }
    }
    Write-Output "Total Declined Updates : $count"

    Write-Output "Configure and run default approvalrule"
    [void][reflection.assembly]::LoadWithPartialName("Microsoft.UpdateServices.Administration")
    $rule = $WSUS.GetInstallApprovalRules() | Where-Object {
        $_.Name -eq "Default Automatic Approval Rule"}
    $class = $WSUS.GetUpdateClassifications() | Where-Object {$_.Title -In (
        'Critical Updates',
        'Definition Updates',
        'Feature Packs',
        'Security Updates',
        'Service Packs',
        'Update Rollups',
        'Updates',
        'Upgrades')}
    $class_coll = New-Object Microsoft.UpdateServices.Administration.UpdateClassificationCollection
    $class_coll.AddRange($class)
    $rule.SetUpdateClassifications($class_coll)
    $rule.Enabled = $True
    $rule.Save()
    $rule.ApplyRule()

    Write-Output "Finished"
}
Catch
{
    Throw $_
}
Automate Your Lab - This article is part of a series.
Part 6: This Article

Related