Last active
March 25, 2022 06:23
-
-
Save misury/d253ed116765804fb6945a7c5853f7c5 to your computer and use it in GitHub Desktop.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
# Get the ID and security principal of the current user account | |
$myWindowsID=[System.Security.Principal.WindowsIdentity]::GetCurrent() | |
$myWindowsPrincipal=new-object System.Security.Principal.WindowsPrincipal($myWindowsID) | |
# Get the security principal for the Administrator role | |
$adminRole=[System.Security.Principal.WindowsBuiltInRole]::Administrator | |
# Check to see if we are currently running "as Administrator" | |
if ($myWindowsPrincipal.IsInRole($adminRole)) | |
{ | |
# We are running "as Administrator" - so change the title and background color to indicate this | |
$Host.UI.RawUI.WindowTitle = $myInvocation.MyCommand.Definition + "(Elevated)" | |
$Host.UI.RawUI.BackgroundColor = "DarkBlue" | |
clear-host | |
} | |
else | |
{ | |
# We are not running "as Administrator" - so relaunch as administrator | |
# Create a new process object that starts PowerShell | |
$newProcess = new-object System.Diagnostics.ProcessStartInfo "PowerShell"; | |
# Specify the current script path and name as a parameter | |
$newProcess.Arguments = $myInvocation.MyCommand.Definition; | |
# Indicate that the process should be elevated | |
$newProcess.Verb = "runas"; | |
# Start the new process | |
[System.Diagnostics.Process]::Start($newProcess); | |
# Exit from the current, unelevated, process | |
exit | |
} | |
# Run your code that needs to be elevated here | |
function Install-WindowsUpdate { | |
<# | |
.SYNOPSIS | |
Downloads and installs updates via Windows Update | |
.DESCRIPTION | |
This uses the windows update service to search, download and install updates. By default, only critical updates are included and a reboot will be induced if required. | |
.PARAMETER GetUpdatesFromMS | |
If this switch is set, the default windows update server, if any, is bypassed and windows update requests go to the public Microsoft Windows update service. | |
.PARAMETER AcceptEula | |
If any update requires a Eula acceptance, setting this switch will accept the Eula and allow the update to be installed. | |
.PARAMETER SuppressReboots | |
Setting this switch will suppress a reboot in the event that any update requires one. | |
.PARAMETER Criteria | |
The criteria used for searching updates. The default criteria is "IsHidden=0 and IsInstalled=0 and Type='Software'" which is effectively just critical updates. | |
.LINK | |
https://boxstarter.org | |
#> | |
param( | |
[switch]$getUpdatesFromMS, | |
[switch]$acceptEula, | |
[switch]$SuppressReboots, | |
[string]$criteria="IsHidden=0 and IsInstalled=0 and Type='Software' and BrowseOnly=0" | |
) | |
if(Get-IsRemote){ | |
Invoke-FromTask @" | |
Import-Module $($boxstarter.BaseDir)\boxstarter.WinConfig\Boxstarter.Winconfig.psd1 | |
Install-WindowsUpdate -GetUpdatesFromMS:`$$GetUpdatesFromMS -AcceptEula:`$$AcceptEula -SuppressReboots -Criteria "$Criteria" | |
"@ -IdleTimeout 0 -TotalTimeout 0 | |
if(Test-PendingReboot){ | |
Invoke-Reboot | |
} | |
return | |
} | |
try{ | |
$searchSession=Start-TimedSection "Checking for updates..." | |
$updateSession =new-object -comobject "Microsoft.Update.Session" | |
$Downloader =$updateSession.CreateUpdateDownloader() | |
$Installer =$updateSession.CreateUpdateInstaller() | |
$Searcher =$updatesession.CreateUpdateSearcher() | |
if($getUpdatesFromMS) { | |
$Searcher.ServerSelection = 2 #2 is the Const for the Windows Update server | |
} | |
$wus=Get-WmiObject -Class Win32_Service -Filter "Name='wuauserv'" | |
$origStatus=$wus.State | |
$origStartupType=$wus.StartMode | |
Write-BoxstarterMessage "Update service is in the $origStatus state and its startup type is $origStartupType" -verbose | |
if($origStartupType -eq "Auto"){ | |
$origStartupType = "Automatic" | |
} | |
if($origStatus -eq "Stopped"){ | |
if($origStartupType -eq "Disabled"){ | |
Set-Service wuauserv -StartupType Automatic | |
} | |
Out-BoxstarterLog "Starting windows update service" -verbose | |
Start-Service -Name wuauserv | |
} | |
else { | |
# Restart in case updates are running in the background | |
Out-BoxstarterLog "Restarting windows update service" -verbose | |
Remove-BoxstarterError { Restart-Service -Name wuauserv -Force -WarningAction SilentlyContinue } | |
} | |
$Result = $Searcher.Search($criteria) | |
Stop-TimedSection $searchSession | |
$totalUpdates = $Result.updates.count | |
If ($totalUpdates -ne 0) | |
{ | |
Out-BoxstarterLog "$($Result.updates.count) Updates found" | |
$currentCount = 0 | |
foreach($update in $result.updates) { | |
++$currentCount | |
if(!($update.EulaAccepted)){ | |
if($acceptEula) { | |
$update.AcceptEula() | |
} | |
else { | |
Out-BoxstarterLog " * $($update.title) has a user agreement that must be accepted. Call Install-WindowsUpdate with the -AcceptEula parameter to accept all user agreements. This update will be ignored." | |
continue | |
} | |
} | |
$Result= $null | |
if ($update.isDownloaded -eq "true" -and ($update.InstallationBehavior.CanRequestUserInput -eq $false )) { | |
Out-BoxstarterLog " * $($update.title) already downloaded" | |
$result = install-Update $update $currentCount $totalUpdates | |
} | |
elseif($update.InstallationBehavior.CanRequestUserInput -eq $true) { | |
Out-BoxstarterLog " * $($update.title) Requires user input and will not be downloaded" | |
} | |
else { | |
Download-Update $update | |
$result = Install-Update $update $currentCount $totalUpdates | |
} | |
} | |
if($result -ne $null -and $result.rebootRequired) { | |
if($SuppressReboots) { | |
Out-BoxstarterLog "A Restart is Required." | |
} else { | |
$Rebooting=$true | |
Out-BoxstarterLog "Restart Required. Restarting now..." | |
Stop-TimedSection $installSession | |
if(test-path function:\Invoke-Reboot) { | |
return Invoke-Reboot | |
} else { | |
Restart-Computer -force | |
} | |
} | |
} | |
} | |
else{Out-BoxstarterLog "There is no update applicable to this machine"} | |
} | |
catch { | |
Out-BoxstarterLog "There were problems installing updates: $($_.ToString())" | |
throw | |
} | |
finally { | |
if($origAUVal){ | |
Set-ItemProperty -Path HKLM:\Software\Policies\Microsoft\Windows\WindowsUpdate\AU -Name UseWuServer -Value $origAUVal -ErrorAction SilentlyContinue | |
} | |
if($origStatus -eq "Stopped") | |
{ | |
Out-BoxstarterLog "Stopping win update service and setting its startup type to $origStartupType" -verbose | |
Set-Service wuauserv -StartupType $origStartupType | |
Remove-BoxstarterError { stop-service wuauserv -WarningAction SilentlyContinue } | |
} | |
} | |
} | |
function Download-Update($update) { | |
$downloadSession = Start-TimedSection "Download of $($update.Title)" | |
$updates = new-Object -com "Microsoft.Update.UpdateColl" | |
$updates.Add($update) | out-null | |
$Downloader.Updates = $updates | |
$retry = $true | |
[int]$retries = "10" | |
[int]$currentRetry = "0" | |
[int]$retrySeconds = 30 | |
do { | |
try { | |
$Downloader.Download() | Out-Null | |
$retry = $false | |
} | |
catch { | |
# Check for WU_E_SELFUPDATE_IN_PROGRESS | |
if($_.Exception.HResult -eq -2145124325) { | |
if ($currentRetry -gt $retries) { | |
# We can't wait forever... | |
Write-BoxstarterMessage "Windows Update Agent took too long to update itself." | |
throw | |
} | |
Write-BoxstarterMessage "Windows Update Agent is self-updating... Waiting." | |
$global:error.RemoveAt(0) | |
Start-Sleep -Seconds $retrySeconds | |
$currentRetry = $currentRetry + 1 | |
} | |
# Some other execption happened... | |
else { | |
throw | |
} | |
} | |
} while ($retry -eq $true) | |
Stop-TimedSection $downloadSession | |
} | |
function Install-Update($update, $currentCount, $totalUpdates) { | |
$installSession=Start-TimedSection "Install $currentCount of $totalUpdates updates: $($update.Title)" | |
$updates= new-Object -com "Microsoft.Update.UpdateColl" | |
$updates.Add($update) | out-null | |
$Installer.updates = $Updates | |
try { $result = $Installer.Install() } catch { | |
if(!($SuppressReboots) -and (test-path function:\Invoke-Reboot)){ | |
if(Test-PendingReboot){ | |
$global:error.RemoveAt(0) | |
Invoke-Reboot | |
} | |
} | |
# Check for WU_E_INSTALL_NOT_ALLOWED | |
if($_.Exception.HResult -eq -2145124330) { | |
Out-BoxstarterLog "There is either an update in progress or there is a pending reboot blocking the install." | |
$global:error.RemoveAt(0) | |
} | |
else { throw } | |
} | |
Stop-TimedSection $installSession | |
return $result | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment