<# .SYNOPSIS Opts a Windows device in to Microsoft Update (or back out of it). .DESCRIPTION Uses the Microsoft.Update.ServiceManager COM object, the same API behind the "Receive updates for other Microsoft products" toggle in Settings. Once the Microsoft Update service is registered, Windows Update offers fixes for Office, SQL Server, Visual C++ runtimes and other Microsoft products, not just Windows. Returns an object describing the service afterwards and sets exit code 0 on success or 1 on failure, so it drops straight into a ConfigMgr program. .PARAMETER ServiceId The update service to register. Defaults to Microsoft Update. .PARAMETER Remove Unregister the service instead of registering it. .PARAMETER SkipAutomaticUpdates Register the service, but don't make it part of scheduled Automatic Updates scans. .EXAMPLE .\Register-MicrosoftUpdateService.ps1 -WhatIf .EXAMPLE .\Register-MicrosoftUpdateService.ps1 -Remove #> [CmdletBinding(SupportsShouldProcess)] param( [ValidatePattern('^[0-9a-fA-F]{8}-([0-9a-fA-F]{4}-){3}[0-9a-fA-F]{12}$')] [string]$ServiceId = '7971f918-a847-4430-9279-4a52d1ef18d2', [switch]$Remove, [switch]$SkipAutomaticUpdates ) # AddService2 flags: allow pending registration (1), allow online registration (2), register with AU (4). $flags = 1 -bor 2 if (-not $SkipAutomaticUpdates) { $flags = $flags -bor 4 } $stateNames = @{ 1 = 'NotRegistered'; 2 = 'RegistrationPending'; 3 = 'Registered' } function Get-ServiceState { param($Manager, [string]$Id) $svc = @($Manager.Services) | Where-Object { $_.ServiceID -eq $Id } | Select-Object -First 1 [pscustomobject]@{ ComputerName = $env:COMPUTERNAME ServiceId = $Id Name = if ($svc) { $svc.Name } else { $null } Registered = [bool]$svc RegisteredWithAU = if ($svc) { [bool]$svc.IsRegisteredWithAU } else { $false } IsDefaultAUService = if ($svc) { [bool]$svc.IsDefaultAUService } else { $false } Result = $null } } try { $manager = New-Object -ComObject Microsoft.Update.ServiceManager $manager.ClientApplicationID = 'Register-MicrosoftUpdateService' } catch { Write-Error "Couldn't create the Windows Update ServiceManager COM object: $($_.Exception.Message)" exit 1 } $before = Get-ServiceState -Manager $manager -Id $ServiceId Write-Verbose ("Before: Registered={0}, RegisteredWithAU={1}" -f $before.Registered, $before.RegisteredWithAU) $exitCode = 0 $result = 'NoChange' try { if ($Remove) { if (-not $before.Registered) { Write-Verbose 'Service is not registered. Nothing to remove.' } elseif ($PSCmdlet.ShouldProcess($env:COMPUTERNAME, "Remove update service $ServiceId")) { $manager.RemoveService($ServiceId) $result = 'Removed' } else { $result = 'WhatIf' } } else { $alreadyDone = $before.Registered -and ($SkipAutomaticUpdates -or $before.RegisteredWithAU) if ($alreadyDone) { Write-Verbose 'Service is already registered the way you asked. Nothing to do.' } elseif ($PSCmdlet.ShouldProcess($env:COMPUTERNAME, "Register update service $ServiceId (flags $flags)")) { # Third argument is the authorization cab path. Microsoft Update doesn't need one. $registration = $manager.AddService2($ServiceId, $flags, '') $result = $stateNames[[int]$registration.RegistrationState] if (-not $result) { $result = "State$($registration.RegistrationState)" } } else { $result = 'WhatIf' } } } catch { Write-Error "Update service change failed: $($_.Exception.Message)" $result = 'Failed' $exitCode = 1 } $after = Get-ServiceState -Manager $manager -Id $ServiceId $after.Result = $result $after # A normal finish returns exit code 0. Only a failure needs to say otherwise. if ($exitCode) { exit $exitCode }