Um DefenderUpdatesOnly ergänzt

This commit is contained in:
Patrick Asmus
2026-07-07 10:14:27 +02:00
parent eacc7cdbe1
commit c236b08311
5 changed files with 239 additions and 33 deletions

View File

@@ -9,12 +9,18 @@ Author: Patrick Asmus
Web: https://www.cleveradmin.de
Repository: https://git.techniverse.net/scriptos/windows-updater.git
License: MIT
Version: 2.7.2
Date: 06.07.2026
Modifications: Guard TLS 1.3 with enum check and try/catch fallback to TLS 1.2
Version: 2.8.0
Date: 07.07.2026
Modifications: Add -DefenderOnly, -DryRun, -ConfigFile parameters and UpdateType config option
#####################################################
#>
param(
[switch]$DefenderOnly,
[switch]$DryRun,
[string]$ConfigFile
)
# ===================================================
#region Administrator Check
# ===================================================
@@ -53,6 +59,9 @@ $script:UseXlsx = $false
$script:UpdateResults = [System.Collections.ArrayList]::new()
$script:WingetResults = [System.Collections.ArrayList]::new()
$script:ScriptStartTime = Get-Date
$script:DefenderOnlyMode = $DefenderOnly.IsPresent
$script:DryRunParam = $DryRun.IsPresent
$script:ConfigFilePath = $ConfigFile
#endregion
@@ -765,6 +774,11 @@ function Get-AvailableUpdates {
$params["MicrosoftUpdate"] = $true
}
if ($script:DefenderOnlyMode) {
$params["Category"] = @("Definition Updates")
Write-Log "Filtering for Defender definition updates only"
}
if (-not [string]::IsNullOrWhiteSpace($excludeKBs)) {
$kbList = $excludeKBs -split ',' | ForEach-Object { $_.Trim() } | Where-Object { -not [string]::IsNullOrWhiteSpace($_) }
if ($kbList.Count -gt 0) {
@@ -773,7 +787,7 @@ function Get-AvailableUpdates {
}
}
if ($excludeDrivers) {
if ($excludeDrivers -and -not $script:DefenderOnlyMode) {
$params["NotCategory"] = "Drivers"
Write-Log "Excluding driver updates"
}
@@ -804,6 +818,10 @@ function Install-PendingUpdates {
$params["MicrosoftUpdate"] = $true
}
if ($script:DefenderOnlyMode) {
$params["Category"] = @("Definition Updates")
}
if (-not [string]::IsNullOrWhiteSpace($excludeKBs)) {
$kbList = $excludeKBs -split ',' | ForEach-Object { $_.Trim() } | Where-Object { -not [string]::IsNullOrWhiteSpace($_) }
if ($kbList.Count -gt 0) {
@@ -811,7 +829,7 @@ function Install-PendingUpdates {
}
}
if ($excludeDrivers) {
if ($excludeDrivers -and -not $script:DefenderOnlyMode) {
$params["NotCategory"] = "Drivers"
}
@@ -1158,16 +1176,30 @@ function Invoke-ServiceWatchdog {
function Start-WindowsUpdater {
# --- Load Config ---
$configPath = Join-Path -Path $PSScriptRoot -ChildPath "config.ini"
if (-not [string]::IsNullOrWhiteSpace($script:ConfigFilePath)) {
$configPath = $script:ConfigFilePath
}
else {
$configPath = Join-Path -Path $PSScriptRoot -ChildPath "config.ini"
}
$script:Config = Read-IniFile -Path $configPath
# --- Resolve DefenderOnly mode (parameter overrides config) ---
if (-not $script:DefenderOnlyMode) {
$configUpdateType = Get-ConfigValue -Config $script:Config -Section "General" -Key "UpdateType" -Default "All"
if ($configUpdateType -eq "DefenderOnly") {
$script:DefenderOnlyMode = $true
}
}
# --- Initialize Logging ---
$logPath = Get-ConfigValue -Config $script:Config -Section "General" -Key "LogPath" -Default "C:\logs\windows-updater"
$logRetention = Get-ConfigValue -Config $script:Config -Section "General" -Key "LogRetentionDays" -Default 365 -Type int
Initialize-Logging -LogPath $logPath -RetentionDays $logRetention
$modeLabel = if ($script:DefenderOnlyMode) { "Defender Only" } else { "Full Update" }
Write-Log "=========================================="
Write-Log "Windows Updater started"
Write-Log "Windows Updater started (Mode: $modeLabel)"
Write-Log "=========================================="
# --- OS Detection ---
@@ -1208,6 +1240,7 @@ function Start-WindowsUpdater {
# --- Scan for Updates ---
$dryRun = Get-ConfigValue -Config $script:Config -Section "General" -Key "DryRun" -Default $false -Type bool
if ($script:DryRunParam) { $dryRun = $true }
$availableUpdates = Get-AvailableUpdates
if ($null -eq $availableUpdates) {
@@ -1220,13 +1253,15 @@ function Start-WindowsUpdater {
exit 1
}
$updateLabel = if ($script:DefenderOnlyMode) { "Defender" } else { "Windows" }
if (@($availableUpdates).Count -eq 0) {
Write-Log "No updates available"
Send-Notification -Subject "No Updates - $env:COMPUTERNAME" `
-Body "No Windows updates are currently available for $env:COMPUTERNAME." `
Send-Notification -Subject "No $updateLabel Updates - $env:COMPUTERNAME" `
-Body "No $updateLabel updates are currently available for $env:COMPUTERNAME." `
-EventName "NoUpdates"
if (-not $dryRun) {
Invoke-WingetUpgrade
if (-not $script:DefenderOnlyMode) { Invoke-WingetUpgrade }
Export-UpdateHistory
}
Invoke-UpdateHook -Phase Post | Out-Null
@@ -1250,7 +1285,7 @@ function Start-WindowsUpdater {
if ($dryRun) {
Write-Log "DRY-RUN mode active - no updates will be installed"
$reportLines = @("Available Updates for $env:COMPUTERNAME ($updateCount):`n")
$reportLines = @("Available $updateLabel Updates for $env:COMPUTERNAME ($updateCount):`n")
foreach ($u in $availableUpdates) {
$sizeStr = if ($u.Size) { "{0:N2} MB" -f ($u.Size / 1MB) } else { "N/A" }
$kbStr = if ($u.KB) { $u.KB } else { "N/A" }
@@ -1258,7 +1293,7 @@ function Start-WindowsUpdater {
}
$reportBody = $reportLines -join "`n"
Send-Notification -Subject "Dry-Run Report - $env:COMPUTERNAME" -Body $reportBody -EventName "DryRun"
Send-Notification -Subject "$updateLabel Dry-Run Report - $env:COMPUTERNAME" -Body $reportBody -EventName "DryRun"
Invoke-UpdateHook -Phase Post | Out-Null
Write-Log "Windows Updater finished (dry-run)"
@@ -1268,8 +1303,10 @@ function Start-WindowsUpdater {
# --- Install Updates ---
Install-PendingUpdates
# --- Winget ---
Invoke-WingetUpgrade
# --- Winget (skip in DefenderOnly mode) ---
if (-not $script:DefenderOnlyMode) {
Invoke-WingetUpgrade
}
# --- Export History ---
Export-UpdateHistory
@@ -1279,7 +1316,7 @@ function Start-WindowsUpdater {
$failCount = ($script:UpdateResults | Where-Object { $_.Result -notmatch "^Installed|^Succeeded|^Success" } | Measure-Object).Count
$summaryBody = @(
"Windows Update Summary for $env:COMPUTERNAME"
"$updateLabel Update Summary for $env:COMPUTERNAME"
"OS: $($script:OSInfo.Caption)"
"Date: $(Get-Date -Format 'dd.MM.yyyy HH:mm:ss')"
""
@@ -1295,7 +1332,7 @@ function Start-WindowsUpdater {
$summaryText = $summaryBody -join "`n"
$hasFailures = $failCount -gt 0 -or $script:HasErrors
$priority = if ($hasFailures) { "high" } else { "default" }
$subjectPrefix = if ($hasFailures) { "Updates (with errors)" } else { "Updates OK" }
$subjectPrefix = if ($hasFailures) { "$updateLabel Updates (with errors)" } else { "$updateLabel Updates OK" }
Send-Notification -Subject "$subjectPrefix - $env:COMPUTERNAME" `
-Body $summaryText -Priority $priority `
@@ -1304,22 +1341,24 @@ function Start-WindowsUpdater {
# --- Post-Update Hook ---
Invoke-UpdateHook -Phase Post | Out-Null
# --- Reboot Handling ---
$script:RebootPending = Test-PendingReboot
if ($script:RebootPending) {
Write-Log "System reboot is pending"
$rebootHandled = Invoke-ScheduledReboot
if (-not $rebootHandled) {
Write-Log "Auto-reboot is disabled, manual reboot required" -Level WARN
Send-Notification -Subject "Reboot Required - $env:COMPUTERNAME" `
-Body "Windows updates have been installed on $env:COMPUTERNAME but a reboot is required. Auto-reboot is disabled." `
-Priority "high" -EventName "RebootRequired"
# --- Reboot Handling (skip in DefenderOnly mode) ---
if (-not $script:DefenderOnlyMode) {
$script:RebootPending = Test-PendingReboot
if ($script:RebootPending) {
Write-Log "System reboot is pending"
$rebootHandled = Invoke-ScheduledReboot
if (-not $rebootHandled) {
Write-Log "Auto-reboot is disabled, manual reboot required" -Level WARN
Send-Notification -Subject "Reboot Required - $env:COMPUTERNAME" `
-Body "Windows updates have been installed on $env:COMPUTERNAME but a reboot is required. Auto-reboot is disabled." `
-Priority "high" -EventName "RebootRequired"
}
}
else {
Write-Log "No reboot required"
# --- Service Watchdog (only when no reboot is pending) ---
Invoke-ServiceWatchdog
}
}
else {
Write-Log "No reboot required"
# --- Service Watchdog (only when no reboot is pending) ---
Invoke-ServiceWatchdog
}
# --- Finish ---
@@ -1328,7 +1367,7 @@ function Start-WindowsUpdater {
Write-Log "=========================================="
if ($script:HasErrors) { exit 1 }
if ($script:RebootPending -and -not (Get-ConfigValue -Config $script:Config -Section "Reboot" -Key "Enabled" -Default $false -Type bool)) { exit 2 }
if (-not $script:DefenderOnlyMode -and $script:RebootPending -and -not (Get-ConfigValue -Config $script:Config -Section "Reboot" -Key "Enabled" -Default $false -Type bool)) { exit 2 }
exit 0
}