Files
scripts/MDT-WinUpdate.ps1
2025-10-18 17:11:58 -05:00

160 lines
6.1 KiB
PowerShell

# Run Windows Update
# iRaven
# 2025-07-30
<#
.SYNOPSIS
Updates windows with PSWindowsUpdate
.PARAMETER MDT
Set this if being used with MDT so logs get put in the right place
.PARAMETER Reboot
Allow system reboots
#>
## Initial Tasks
param(
[switch] $MDT,
[switch] $Reboot
)
$ErrorActionPreference = "Continue"
$PSModulePathCU = $env:PSModulePath.split(';')[0] # CurrentUser PSModule path
$PSModulePathAU = $env:PSModulePath.split(';')[1] # All Users PSModule path
if ($MDT){
$MDTPath = $Global:TSEnv.Value("DeployRoot")
}
$WUServer = (Get-ItemProperty HKLM:\Software\Policies\Microsoft\Windows\WindowsUpdate).WUServer
## Functions
Function SetWUServer {
if (!(test-path HKLM:\Software\Policies\Microsoft\Windows\WindowsUpdate)){
New-Item -Path "HKLM:\Software\Policies\Microsoft\Windows\WindowsUpdate"
}
New-ItemProperty -Path "HKLM:\Software\Policies\Microsoft\Windows\WindowsUpdate" -Name WUServer -Value "http://fluttershy.technolog.net:8530"
New-ItemProperty -Path "HKLM:\Software\Policies\Microsoft\Windows\WindowsUpdate" -Name WUStatusServer -Value "http://fluttershy.technolog.net:8530"
if (!(test-path HKLM:\Software\Policies\Microsoft\Windows\WindowsUpdate\AU)){
New-Item -Path "HKLM:\Software\Policies\Microsoft\Windows\WindowsUpdate\AU"
}
New-ItemProperty -Path "HKLM:\Software\Policies\Microsoft\Windows\WindowsUpdate" -Name UseWUServer -Value 0
}
Function ImportPSWindowsUpdate {
Write-Host -ForegroundColor Yellow "Importing PS Windows Update module..."
# Write-LogEntry -Value "Importing PS Windows Update Module..." -Severity 1 -Component "ImportPSWindowsUpdate" -FileName $ScriptLog
try {
if (!(Test-Path -Path $PSModulePathAU\PSWindowsUpdate -PathType Container)){
# Get from PSGallery/NuGet
Write-Host -ForegroundColor Yellow "Installing PSWindowsUpdate from PSGallery"
if (!(Get-PackageProvider -ListAvailable -Name 'NuGet' -ErrorAction Ignore)) {
Write-Host -ForegroundColor Yellow 'Installing NuGet package provider...'
Install-PackageProvider -Name 'NuGet' -Force
Install-Module -Name PSWindowsUpdate -Scope AllUsers -Force
} else {
Install-Module -Name PSWindowsUpdate -Scope AllUsers -Force
}
}
Import-Module PSWindowsUpdate -Force
Write-Host -ForegroundColor Green "PSWindowsUpdate module imported!"
Write-LogEntry -Value "PSWindowsUpdate module imported!" -Severity 1 -Component "ImportPSWindowsUpdate" -FileName $ScriptLog
return $true
} catch {
Write-LogEntry -Value "Failed to import PSWindowsUpdate!" -Severity 3 -Component "ImportPSWindowsUpdate" -FileName $ScriptLog
Write-Host -ForegroundColor Red "Failed to import PSWindowsUpdate!"
return $false
}
}
Function RunWinUpdate { # Run Windows Updates
if(ImportPSWindowsUpdate){
try {
Write-LogEntry -Value "Installing all available Windows Updates..." -Severity 1 -Component "RunWinUpdate" -FileName $ScriptLog
Write-Host -ForegroundColor Yellow "Installing all available Windows Updates..."
if (($null -eq $WUServer) -and !($Reboot)){
Install-WindowsUpdate -MicrosoftUpdate -AcceptAll -IgnoreReboot
#Requires -RunAsAdministrator
} elseif (($null -eq $WUServer) -and $Reboot){
Install-WindowsUpdate -MicrosoftUpdate -AcceptAll -AutoReboot
#Requires -RunAsAdministrator
} elseif ($WUServer -and $Reboot) {
Install-WindowsUpdate -AcceptAll -AutoReboot
#Requires -RunAsAdministrator
} else {
Install-WindowsUpdate -AcceptAll -IgnoreReboot
#Requires -RunAsAdministrator
}
return $true
} catch {
Write-Host -ForegroundColor Red "Failed installing all available Windows updates!"
Write-LogEntry -Value "Failed installing all available Windows updates!" -Severity 3 -Component "RunWinUpdate" -FileName $ScriptLog
}
} else {
Write-LogEntry -Value "Failed to update Windows due to failed import of PSWindowsUpdate PS module." -Severity 3 -Component "RunWinUpdate" -FileName $ScriptLog
return $false
}
}
Function Write-LogEntry
{
#Write data to a CMTrace compatible log file. (Credit to SCConfigMgr - https://www.scconfigmgr.com/)
param(
[parameter(Mandatory = $true, HelpMessage = "Value added to the log file.")]
[ValidateNotNullOrEmpty()]
[string]$Value,
[parameter(Mandatory = $true, HelpMessage = "Severity for the log entry. 1 for Informational, 2 for Warning and 3 for Error.")]
[ValidateNotNullOrEmpty()]
[ValidateSet("1", "2", "3")]
[string]$Severity,
[parameter(Mandatory = $true, HelpMessage = "Component of the log file.")]
[ValidateNotNullOrEmpty()]
[string]$Component,
[parameter(Mandatory = $false, HelpMessage = "Name of the log file that the entry will written to.")]
[ValidateNotNullOrEmpty()]
[string]$FileName
)
#Determine log file location
$LogFilePath = $FileName
#Construct time stamp for log entry
if(-not(Test-Path -Path 'variable:global:TimezoneBias'))
{
[string]$global:TimezoneBias = [System.TimeZoneInfo]::Local.GetUtcOffset((Get-Date)).TotalMinutes
if($TimezoneBias -match "^-")
{
$TimezoneBias = $TimezoneBias.Replace('-', '+')
}
else
{
$TimezoneBias = '-' + $TimezoneBias
}
}
$Time = -join @((Get-Date -Format "HH:mm:ss.fff"), $TimezoneBias)
#Construct date for log entry
$Date = (Get-Date -Format "MM-dd-yyyy")
#Construct context for log entry
$Context = $([System.Security.Principal.WindowsIdentity]::GetCurrent().Name)
#Construct final log entry
$LogText = "<![LOG[$($Value)]LOG]!><time=""$($Time)"" date=""$($Date)"" component=""$($Component)"" context=""$($Context)"" type=""$($Severity)"" thread=""$($PID)"" file="""">"
#Add value to log file
try
{
Out-File -InputObject $LogText -Append -NoClobber -Encoding Default -FilePath $LogFilePath -ErrorAction Stop
}
catch [System.Exception]
{
Write-Warning -Message "Unable to append log entry to $FileName file. Error message at line $($_.InvocationInfo.ScriptLineNumber): $($_.Exception.Message)"
}
}
# Main Program
if ($MDT){
if ($null -eq $WUServer) {
SetWUServer
}
$ScriptLog = "$MDTPath\_Logs\$env:ComputerName-WindowsUpdate.log"
} else {
$ScriptLog = "$env:SystemDrive\irnh\PSWindowsUpdate.log"
}
RunWinUpdate