Get Windows Update client configuration

One of the first things I do when provsioning a new server is:

  • configure the network card, assign an IP address
  • define a proxy
  • configure Windows Update settings
  • Download and install all security udpates

Every IT-pro has his own list. The Microsoft PowerShell MVP Jeffery Hicks says for example on this page: Windows Server 2012: First Five Fixes

I assume you will do the following tasks by default when setting up a new Windows Server 2012 system:
* Configure computer name
* Configure networking
* Install features and roles
* Run Windows Update
I’m not going to cover those as I think they are pretty self-evident in the Server Manager GUI, but I do have 5 additional “fixes” that I’ve been using.

He’s right for a GUI environment but it isn’t very straight forward for the Core Edition or when you’ve to automate it.

I’ve already presented how to get and set a proxy server using powershell on this page: https://p0w3rsh3ll.wordpress.com/2012/10/07/getsetclear-proxy/

Recently the Microsoft MVP Jan Egil Ring presented on the Hey Scripting guy’s blog how to Use PowerShell to Configure the NIC on Windows Server 2012

For listing and configuring Windows updates settings, currently I only know the excellent work done by Boe Prox for corporate environments. Here are some links to the great resources Boe shared and still maintains:

But this isn’t exactly what I was looking for, espcially for Non–Active Directory environments. I also wanted a console output where I don’t need to know that AUoptions represents the behavior of Automatic udpates notifications and that a value of 4 means that it should “install updates automatically”.

I didn’t want a script for Managing Windows Update with PowerShell that doesn’t take into account group policy (GPO) settings.

Even the module written by Michal Gajda and presented by Ed Wilson in the following Hey scripting guy’s blog post didn’t propose a solution to read the Windows update settings.

So I’ve been using the following resources to write my own function.

I also wanted the function to work on a freshly installed computer where Windows Updates settings haven’t been configured yet.

Function Get-WUSettings {            
[cmdletbinding()]            
Param(            
[switch]$viaRegistry=$false            
)            
Begin {            
    # Get the Operating system            
    $OSVersion = [environment]::OSVersion.Version            
            
    # Initialize object            
    $WshShell = New-Object -ComObject Wscript.Shell            
            
    $polkey = 'HKLM\SOFTWARE\Policies\Microsoft\Windows\WindowsUpdate\AU'            
    $stdkey = 'HKLM\SOFTWARE\Microsoft\Windows\CurrentVersion\WindowsUpdate\Auto Update'            
}            
Process {            
    if ($viaRegistry) {            
        try {            
            $AUEnabled = $WshShell.RegRead("$polkey\NoAutoUpdate")            
        } catch {            
            # if this value is absent, it means it's turned on            
            $AUEnabled = 0            
        }            
        Switch ($AUEnabled) {            
            1 {$AUEnabled = $false}            
            0 {$AUEnabled = $true }            
        }            
        try {            
            $AUOptions = $WshShell.RegRead("$polkey\AUOptions")            
        } catch {            
            try {            
                $AUOptions = $WshShell.RegRead("$stdkey\AUOptions")            
            } catch {            
                $AUOptions = 0            
            }            
        }            
        Switch ($AUOptions) {            
            0 {$AUNotificationLevel = 'Not Configured'}            
            1 {$AUNotificationLevel = 'Never check for updates'}            
            2 {$AUNotificationLevel = 'Notify Before Download'}            
            3 {$AUNotificationLevel = 'Notify Before Installation'}            
            4 {$AUNotificationLevel = 'Install updates automatically'}            
        }            
        try {            
            $IncludeRecommendedUpdates = $WshShell.RegRead("$polkey\IncludeRecommendedUpdates")            
        } catch {            
            # if the value is absent we get it from            
            $IncludeRecommendedUpdates = $WshShell.RegRead("$stdkey\IncludeRecommendedUpdates")            
        }            
        Switch ($IncludeRecommendedUpdates) {            
            0 {$GetRecommendedUpdates = $false}            
            1 {$GetRecommendedUpdates = $true}            
        }            
       try {            
            $UseWUServerVal = $WshShell.RegRead("$polkey\UseWUServer")            
        } catch {            
            # if the value doesn't exist, it means that we don't use a WSUS server            
            $UseWUServerVal = 0            
        }            
        Switch ($UseWUServerVal) {            
            1 {$UseWUServer = $true}            
            0 {$UseWUServer = $false }            
        }            
        # Create a default object with a subset of properties            
        $obj = New-Object -TypeName psobject -Property @{            
            'Is Automatic Update Enabled' = $AUEnabled            
            'Use a WSUS Server' = $UseWUServer            
            'Automatic Updates Notification' = $AUNotificationLevel;            
            'Receive recommended udpates' = $GetRecommendedUpdates;            
        }            
        if ($OSVersion -lt [version]'6.2') {            
            try {            
                $ScheduledInstallDay  = $WshShell.RegRead("$polkey\ScheduledInstallDay")            
                $ScheduledInstallTime = $WshShell.RegRead("$polkey\ScheduledInstallTime")            
            } catch {            
                try {            
                    $ScheduledInstallDay  = $WshShell.RegRead("$stdkey\ScheduledInstallDay")            
                    $ScheduledInstallTime = $WshShell.RegRead("$stdkey\ScheduledInstallTime")            
                } catch {            
                    # Absent = Every Day @3 AM but I prefer to leave it blank in the returned object            
                }            
            }            
            Switch ($ScheduledInstallDay) {            
                0 {$InstallDay = 'Every Day'}            
                1 {$InstallDay = 'Every Sunday'}            
                2 {$InstallDay = 'Every Monday'}            
                3 {$InstallDay = 'Every Tuesday'}            
                4 {$InstallDay = 'Every Wednesday'}            
                5 {$InstallDay = 'Every Thursday'}            
                6 {$InstallDay = 'Every Friday'}            
                7 {$InstallDay = 'Every Saturday'}            
            }            
            if ($ScheduledInstallTime) {            
                $InstallTime = New-TimeSpan -Hours $ScheduledInstallTime            
            }            
            $obj | Add-Member -MemberType NoteProperty -Name 'Install Frequency' -Value $InstallDay            
            $obj | Add-Member -MemberType NoteProperty -Name 'Install Time' -Value $InstallTime            
        } else {            
            # These properties don't exist anymore on Windows 8            
        }            
        # Add extra properties            
        if ($UseWUServer) {            
            try {            
                $WUServer = $WshShell.RegRead('HKLM\SOFTWARE\Policies\Microsoft\Windows\WindowsUpdate\WUServer')            
                $WUStatusServer =  $WshShell.RegRead('HKLM\SOFTWARE\Policies\Microsoft\Windows\WindowsUpdate\WUStatusServer')            
            } catch {            
                # we silently fail            
            }            
            $obj | Add-Member -MemberType NoteProperty -Name 'WSUS Server' -Value $WUServer            
            $obj | Add-Member -MemberType NoteProperty -Name 'WSUS Status URL' -Value $WUStatusServer            
        }            
        try {            
            $OptinGUID = $WshShell.RegRead('HKLM\SOFTWARE\Microsoft\Windows\CurrentVersion\WindowsUpdate\Services\DefaultService')            
        } catch {            
            # Fail silently            
        }            
        if ($OptinGUID -eq '7971f918-a847-4430-9279-4a52d1efe18d') {            
            $obj | Add-Member -MemberType NoteProperty -Name "Opted-in Microsoft Update" -Value $true            
        } else {            
            $obj | Add-Member -MemberType NoteProperty -Name "Opted-in Microsoft Update" -Value $false            
        }            
        # Return our object            
        $obj            
            
    } else {            
        # We use Com Object            
        $COMWUSettings = (New-Object -ComObject Microsoft.Update.AutoUpdate).Settings            
        # Settings might be controlled by GPO            
        if ($COMWUSettings.ReadOnly) {            
            # Use the registry            
            Get-WUSettings -viaRegistry:$true            
            break            
        } else {            
            $UseWUServer = $false            
        }            
        Switch ($COMWUSettings.NotificationLevel) {            
            0 {$AUNotificationLevel = 'Not Configured'}            
            1 {$AUNotificationLevel = 'Never check for updates'}            
            2 {$AUNotificationLevel = 'Notify Before Download'}            
            3 {$AUNotificationLevel = 'Notify Before Installation'}            
            4 {$AUNotificationLevel = 'Install updates automatically'}            
        }            
        $isAUenabled = (New-Object -ComObject Microsoft.Update.AutoUpdate).serviceEnabled            
        $obj = New-Object -TypeName psobject -Property @{            
            'Is Automatic Update Enabled' = $isAUenabled            
            'Automatic Updates Notification' = $AUNotificationLevel;            
            'Use a WSUS Server' = $UseWUServer            
            'Receive recommended udpates' = $COMWUSettings.IncludeRecommendedUpdates;            
        }            
        if ($OSVersion -lt [version]'6.2') {            
            Switch ($COMWUSettings.ScheduledInstallationDay) {            
                0 {$InstallDay = 'Every Day'}            
                1 {$InstallDay = 'Every Sunday'}            
                2 {$InstallDay = 'Every Monday'}            
                3 {$InstallDay = 'Every Tuesday'}            
                4 {$InstallDay = 'Every Wednesday'}            
                5 {$InstallDay = 'Every Thursday'}            
                6 {$InstallDay = 'Every Friday'}            
                7 {$InstallDay = 'Every Saturday'}            
            }            
            if ($COMWUSettings.ScheduledInstallationTime) {            
                $InstallTime = New-TimeSpan -Hours $COMWUSettings.ScheduledInstallationTime            
            }            
            $obj | Add-Member -MemberType NoteProperty -Name 'Install Frequency' -Value $InstallDay            
            $obj | Add-Member -MemberType NoteProperty -Name 'Install Time' -Value $InstallTime            
            
        } else {            
            # not available on W8            
        }            
        (New-Object -ComObject Microsoft.Update.ServiceManager).services | ForEach-Object {            
            if ($_.IsDefaultAUService) {            
                $OptinGUID = $_.ServiceID             
            }            
        }            
        if ($OptinGUID -eq '7971f918-a847-4430-9279-4a52d1efe18d') {            
            $obj | Add-Member -MemberType NoteProperty -Name "Opted-in Microsoft Update" -Value $true            
        } else {            
            $obj | Add-Member -MemberType NoteProperty -Name "Opted-in Microsoft Update" -Value $false            
        }            
        # return            
        $obj            
    }            
}            
End {}            
}

Here’s what I get on the Windows 7 computer I use at home:
Get-WUsettings output on W7 @home
Here’s what I get on the Windows 8 computer I use at home:
Get-WUSettings output on W8 @home

Advertisements

7 thoughts on “Get Windows Update client configuration

  1. Hi There – Is tehre anyway to get this to accept pipelined input? This fills a big need we have perfectly – except for that one small part…I need this run against groups of servers… Thanks in advance!

    • Yes, there is but for what parameter? For a ComputerName parameter to target a remote computer?
      Actually, there’s a more simple way to achieve this w/o modifying the code.
      Copy/paste the code into a .ps1 file, get rid of the function statement by removing the first and last line of the code.

      $c = Get-Credential
      Get-Content myremotetargets.txt | % {
      Invoke-Command -ComputerName $_ -File mycode.ps1 -Credential $c
      }
      
  2. Hi,
    you can help me with the following…?

    When run the function or the script among server groups the output not show something values.

    Remote Servers Groups by: Invoke-Command -ComputerName $Servers -FilePath .\Get-WUSettings.ps1

    Receive recommended udpates :
    Is Automatic Update Enabled :
    Automatic Updates Notification :
    Use a WSUS Server : False
    Opted-in Microsoft Update : False
    PSComputerName : SRVDC01
    RunspaceId : 1dffc724-fa5b-4451-be4d-755d68ca136a

    Receive recommended udpates :
    Is Automatic Update Enabled :
    Automatic Updates Notification :
    Use a WSUS Server : False
    Opted-in Microsoft Update : False
    PSComputerName : SRVFILE01
    RunspaceId : bced6e95-a1a2-43a3-84fe-17e838a93df6

    Locally on server SRVDC01: Get-WUSettings

    Receive recommended udpates : True
    Is Automatic Update Enabled : True
    Automatic Updates Notification : Notify Before Installation
    Use a WSUS Server : False
    Opted-in Microsoft Update : False

    Thanks!!

    • Hi,

      Yes, I can help 🙂

      I was able to reproduce the behavior you mentioned.

      Running the comObject through remoting doesn’t work very well.

      To override this shortcoming, you can create a file Get-WUSettings.ps1, copy/paste the above function and add the following line after the function:

      # Force reading the settings via the registry
      Get-WUSettings -viaregistry:$true
      

      And then you use the file the way you did with the invoke-command cmdlet.

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s