WindowsUpdateSetting.psm1
#requires -version 5.1 #region main code Function Set-WindowsUpdateDeferral { [cmdletbinding(SupportsShouldProcess)] [OutputType("None", "WindowsUpdateDeferral")] Param ( [Parameter(HelpMessage = "Enter the number of days (0-365) to defer feature updates")] [ValidateRange(0, 365)] [int]$Feature, [Parameter(HelpMessage = "Enter the number of days (0-365) to defer quality updates")] [ValidateRange(0, 365)] [int]$Quality, [switch]$Passthru ) Write-Verbose "[$((Get-Date).TimeofDay)] Starting $($myinvocation.mycommand)" $base1 = "HKLM:\SOFTWARE\Microsoft\WindowsUpdate\ux\Settings" if ($PSCmdlet.ShouldProcess("$env:COMPUTERNAME")) { if ($Feature) { Set-ItemProperty -Path $base1 -Name DeferFeatureUpdatesPeriodInDays -Value $Feature } if ($Quality) { Set-ItemProperty -Path $base1 -Name DeferQualityUpdatesPeriodInDays -Value $Quality } if ($Passthru) { Get-WindowsUpdateDeferral } } #should process Write-Verbose "[$((Get-Date).TimeofDay)] Ending $($myinvocation.mycommand)" } Function Get-WindowsUpdateDeferral { [cmdletbinding()] [OutputType("WindowsUpdateDeferral")] Param () Write-Verbose "[$((Get-Date).TimeofDay)] Starting $($myinvocation.mycommand)" $base1 = "HKLM:\SOFTWARE\Microsoft\WindowsUpdate\ux\Settings" $feature = Get-ItemPropertyValue -Path $base1 -Name DeferFeatureUpdatesPeriodInDays $Quality = Get-ItemPropertyValue -Path $base1 -Name DeferQualityUpdatesPeriodInDays $obj = [PSCustomObject]@{ Computername = $env:COMPUTERNAME FeatureUpdateDeferral = $Feature QualityUpdateDeferral = $Quality } $obj.psobject.typenames.insert(0, 'WindowsUpdateDeferral') $obj Write-Verbose "[$((Get-Date).TimeofDay)] Ending $($myinvocation.mycommand)" } Function Set-WindowsActiveHours { [cmdletbinding(SupportsShouldProcess)] [OutputType("None", "WindowsActiveHours")] Param( [Parameter(Mandatory, HelpMessage = "Enter a starting time like 7:00AM")] [datetime]$StartTime, [Parameter(Mandatory, HelpMessage = "Enter a ending time like 7:00PM")] [datetime]$EndTime, [switch]$Passthru ) Write-Verbose "[$((Get-Date).TimeofDay)] Starting $($myinvocation.mycommand)" $base1 = "HKLM:\SOFTWARE\Microsoft\WindowsUpdate\ux\Settings" #times must be 18 hours or less apart $ts = New-Timespan -start $startTime -end $EndTime if ($ts.hours -gt 18 -OR $ts.hours -lt 0) { Write-Warning "The end time must be 18 hours or less from the start time." #abort and bail return } if ($PSCmdlet.ShouldProcess("Windows Active Hours", "Update hours: $($starttime.hour):00 to $($endtime.hour):00")) { Write-Verbose "Setting start time to $($startTime.hour):00" Set-ItemProperty -Path $base1 -Name ActiveHoursStart -Value $starttime.hour -type DWord Write-Verbose "Setting end time to $($endTime.hour):00" Set-ItemProperty -Path $base1 -Name ActiveHoursEnd -Value $EndTime.hour -type DWord if ($passthru) { Get-WindowsActiveHours } } #should process Write-Verbose "[$((Get-Date).TimeofDay)] Ending $($myinvocation.mycommand)" } #close Set-WindowsActiveHours Function Get-WindowsActiveHours { [cmdletbinding()] [OutputType('WindowsActiveHours')] Param() Write-Verbose "[$((Get-Date).TimeofDay)] Starting $($myinvocation.mycommand)" $base1 = "HKLM:\SOFTWARE\Microsoft\WindowsUpdate\ux\Settings" $start = Get-ItemPropertyValue -Path $base1 -Name ActiveHoursStart $end = Get-ItemPropertyValue -Path $base1 -Name ActiveHoursEnd $obj = [PSCustomObject]@{ Computername = $env:COMPUTERNAME ActiveHoursStart = $start ActiveHoursEnd = $end } $obj.psobject.typenames.insert(0, 'WindowsActiveHours') $obj Write-Verbose "[$((Get-Date).TimeofDay)] Ending $($myinvocation.mycommand)" } #close Get-WindowsActiveHours Function Suspend-WindowsUpdate { [CmdletBinding(SupportsShouldProcess)] [OutputType("None", "WindowsUpdateSetting")] [Alias("swu")] Param( [Parameter(HelpMessage = "Enter a datetime to resume updates. This must be less than 35 days.")] [ValidateScript( { if ($_ -gt (Get-Date)) { $True } else { Throw "You must enter a date in the future." $false } })] [ValidateScript( { $test = New-Timespan -Start (Get-Date) -end $_ if ($test.totalDays -gt 35) { Throw "You must enter a date less than 35 days from now" $False } else { $True } })] [datetime]$Resume = (Get-Date).AddDays(35), [switch]$Passthru ) Write-Verbose "[$((Get-Date).TimeofDay)] Starting $($MyInvocation.Mycommand)" $epoch = Get-Date 1/1/1600 $utc = (Get-Date).ToUniversalTime() $Start = "{0:u}" -f $utc $end = "{0:u}" -f $resume.ToUniversalTime() $ticks = ($utc - $epoch).Ticks $val = $ticks - $ticks % [timespan]::TicksPerSecond Write-Verbose "[$((Get-Date).TimeofDay)] Pausing Windows Updates until $end" if ($pscmdlet.ShouldProcess($env:computername, "Suspend Windows Update until $Resume")) { $base1 = "HKLM:\SOFTWARE\Microsoft\WindowsUpdate\ux\Settings" Set-ItemProperty -Path $base1 -Name PauseFeatureUpdatesStartTime -Value $start -Type String Set-ItemProperty -Path $base1 -Name PauseQualityUpdatesStartTime -Value $start -Type String Set-ItemProperty -Path $base1 -Name PauseUpdatesExpiryTime -Value $end -Type String Set-ItemProperty -Path $base1 -Name PauseFeatureUpdatesEndTime -Value $end -Type String Set-ItemProperty -Path $base1 -Name PauseQualityUpdatesEndTime -Value $end -Type String $base2 = "HKLM:\SOFTWARE\Microsoft\WindowsUpdate\UpdatePolicy\Settings" Set-ItemProperty -path $base2 -name PausedFeatureStatus -value 1 -type DWord #dword 1 = on 0 = off Set-ItemProperty -path $base2 -name PausedQualityStatus -value 1 -type DWord #dword 1 = on 0 = off Set-ItemProperty -path $Base2 -name PausedFeatureDate -value $val -Type QWord Set-ItemProperty -path $Base2 -name PausedQualityDate -value $val -Type QWord if ($passthru) { Get-WindowsUpdateSetting } } Write-Verbose "[$((Get-Date).TimeofDay)] Ending $($MyInvocation.Mycommand)" } #close function Function Resume-WindowsUpdate { [CmdletBinding(SupportsShouldProcess)] [OutputType("None", "WindowsUpdateSetting")] [Alias("rwu")] Param([switch]$Passthru) Write-Verbose "[$((Get-Date).TimeofDay)] Starting $($MyInvocation.Mycommand)" Write-Verbose "[$((Get-Date).TimeofDay)] Testing if Windows Update is paused" if (Test-IsWindowsUpdatePaused) { If ($pscmdlet.ShouldProcess($env:COMPUTERNAME)) { Write-Verbose "[$((Get-Date).TimeofDay)] Restoring Windows Update Settings" $base1 = "HKLM:\SOFTWARE\Microsoft\WindowsUpdate\ux\Settings" $settings = 'PauseFeatureUpdatesStartTime', 'PauseQualityUpdatesStartTime', 'PauseUpdatesExpiryTime', 'PauseFeatureUpdatesEndTime', 'PauseQualityUpdatesEndTime' Write-Verbose "[$((Get-Date).TimeofDay)] Removing registry values from $base1" foreach ($setting in $settings) { Write-Verbose "[$((Get-Date).TimeofDay)] ..$setting" Remove-ItemProperty -Path $base1 -Name $setting } $base2 = "HKLM:\SOFTWARE\Microsoft\WindowsUpdate\UpdatePolicy\Settings" $settings = 'PausedFeatureStatus', 'PausedQualityStatus' Write-Verbose "[$((Get-Date).TimeofDay)] Updating registry values from $base2" foreach ($setting in $settings) { Write-Verbose "[$((Get-Date).TimeofDay)] ..$setting" Set-ItemProperty -path $base2 -name $setting -value 0 -type DWord #dword 1 = on 0 = off } $settings = 'PausedFeatureDate', 'PausedQualityDate' Write-Verbose "[$((Get-Date).TimeofDay)] Removing registry values from $base2" foreach ($setting in $settings) { Write-Verbose "[$((Get-Date).TimeofDay)] ..$setting" Remove-ItemProperty -Path $base2 -Name $setting } if ($passthru) { Get-WindowsUpdateSetting } } #should process } #if paused else { Write-Host "Windows Updates are already enabled" -ForegroundColor green } Write-Verbose "[$((Get-Date).TimeofDay)] Ending $($MyInvocation.Mycommand)" } #close function Function Test-IsWindowsUpdatePaused { [cmdletbinding()] [OutputType([boolean])] Param() Write-Verbose "[$((Get-Date).TimeofDay)] Starting $($MyInvocation.Mycommand)" $base1 = "HKLM:\SOFTWARE\Microsoft\WindowsUpdate\ux\Settings" Try { [void](Get-ItemProperty -Path $base1 -Name PauseFeatureUpdatesStartTime -ErrorAction stop) $True } Catch { $False } Write-Verbose "[$((Get-Date).TimeofDay)] Ending $($MyInvocation.Mycommand)" } Function Get-WindowsUpdateSetting { [CmdletBinding()] [OutputType('WindowsUpdateSetting')] [Alias("gwu")] Param() Write-Verbose "[$((Get-Date).TimeofDay)] Starting $($MyInvocation.Mycommand)" $base1 = "HKLM:\SOFTWARE\Microsoft\WindowsUpdate\ux\Settings" $paused = Test-IsWindowsUpdatePaused if ($paused) { Write-Verbose "[$((Get-Date).TimeofDay)] Querying $base1 for values" $start = ((Get-ItemPropertyValue -Path $base1 -Name PauseFeatureUpdatesStartTime) -As [datetime]).ToUniversalTime() $resume = ((Get-ItemPropertyValue -Path $base1 -Name PauseFeatureUpdatesEndTime) -As [datetime]).ToUniversalTime() $remain = $resume - (Get-Date) } else { $start = $null $resume = $null $remain = $null } $obj = [pscustomobject]@{ Computername = $env:computername UpdatesPaused = $paused PauseStartUTC = $start PauseEndUTC = $resume Remaining = $remain } $obj.psobject.typenames.insert(0, 'WindowsUpdateSetting') $obj Write-Verbose "[$((Get-Date).TimeofDay)] Ending $($MyInvocation.Mycommand)" } #endregion |