Um DefenderUpdatesOnly ergänzt
This commit is contained in:
32
README.md
32
README.md
@@ -27,6 +27,8 @@
|
||||
## Features
|
||||
|
||||
- **Windows Updates** automatisch installieren via PSWindowsUpdate-Modul
|
||||
- **Defender-Only Modus** nur Defender-Definitionsupdates installieren (per Parameter oder Config) — ideal für häufige Ausführung alle paar Stunden
|
||||
- **Kommandozeilen-Parameter** `-DefenderOnly`, `-DryRun`, `-ConfigFile` für flexible Steuerung ohne Config-Änderung
|
||||
- **Winget-Updates** optional (`winget upgrade --all`), automatische Erkennung der Verfügbarkeit
|
||||
- **Benachrichtigungen** via ntfy, E-Mail und/oder Microsoft Teams (inkl. HTML-Report und Adaptive Cards)
|
||||
- **Benachrichtigungs-Ereignisse** granular steuerbar (je Ereignis einzeln ein-/ausschaltbar)
|
||||
@@ -73,11 +75,41 @@ Danach `config.ini` mit einem Texteditor öffnen und die gewünschten Werte anpa
|
||||
### 3. Script ausführen (als Administrator)
|
||||
|
||||
```powershell
|
||||
# Alle Updates installieren (Standard)
|
||||
powershell.exe -ExecutionPolicy Bypass -File "C:\scripts\windows-updater\windows-updater.ps1"
|
||||
|
||||
# Nur Defender-Definitionsupdates
|
||||
powershell.exe -ExecutionPolicy Bypass -File "C:\scripts\windows-updater\windows-updater.ps1" -DefenderOnly
|
||||
|
||||
# Dry-Run (nur prüfen, nicht installieren)
|
||||
powershell.exe -ExecutionPolicy Bypass -File "C:\scripts\windows-updater\windows-updater.ps1" -DryRun
|
||||
|
||||
# Alternative Config-Datei verwenden
|
||||
powershell.exe -ExecutionPolicy Bypass -File "C:\scripts\windows-updater\windows-updater.ps1" -ConfigFile "D:\configs\server-config.ini"
|
||||
```
|
||||
|
||||

|
||||
|
||||
## Parameter
|
||||
|
||||
| Parameter | Typ | Beschreibung |
|
||||
|---|---|---|
|
||||
| `-DefenderOnly` | Switch | Nur Windows Defender Definitionsupdates installieren. Überspringt Winget, Reboot und Service Watchdog |
|
||||
| `-DryRun` | Switch | Nur prüfen welche Updates verfügbar sind, ohne zu installieren. Überschreibt die Config-Einstellung |
|
||||
| `-ConfigFile` | String | Pfad zu einer alternativen Konfigurationsdatei (Standard: `config.ini` im Script-Verzeichnis) |
|
||||
|
||||
Parameter überschreiben die entsprechenden Config-Werte. So kann dasselbe Script mit verschiedenen Parametern für verschiedene Aufgaben verwendet werden.
|
||||
|
||||
### Typisches Setup: Defender häufig, volle Updates monatlich
|
||||
|
||||
```
|
||||
# Alle 4 Stunden: Defender-Updates (per Aufgabenplanung)
|
||||
powershell.exe -ExecutionPolicy Bypass -File "C:\scripts\windows-updater\windows-updater.ps1" -DefenderOnly
|
||||
|
||||
# Einmal im Monat: Alle Updates (per Aufgabenplanung)
|
||||
powershell.exe -ExecutionPolicy Bypass -File "C:\scripts\windows-updater\windows-updater.ps1"
|
||||
```
|
||||
|
||||
### 4. Optional: Aufgabenplanung einrichten
|
||||
|
||||
Für automatische Ausführung per Windows Aufgabenplanung siehe [Aufgabenplanung einrichten](docs/task-scheduler.md).
|
||||
|
||||
@@ -11,6 +11,9 @@ LogPath = C:\logs\windows-updater
|
||||
LogRetentionDays = 365
|
||||
# Dry-run mode: scan and report only, do not install (true/false)
|
||||
DryRun = false
|
||||
# Update type: All (all updates), DefenderOnly (only Defender definition updates)
|
||||
# Can be overridden with -DefenderOnly parameter
|
||||
UpdateType = All
|
||||
|
||||
[WindowsUpdate]
|
||||
# Use Microsoft Update (includes Office, .NET, drivers) instead of Windows Update only
|
||||
|
||||
@@ -10,7 +10,8 @@ Alle Einstellungen werden in der Datei `config.ini` vorgenommen, die sich im sel
|
||||
|---|---|---|---|
|
||||
| `LogPath` | String | `C:\logs\windows-updater` | Verzeichnis für Log-Dateien (eine Datei pro Tag) |
|
||||
| `LogRetentionDays` | Integer | `365` | Anzahl Tage, nach denen alte Log-Dateien gelöscht werden |
|
||||
| `DryRun` | Boolean | `false` | Nur prüfen welche Updates verfügbar sind, ohne zu installieren |
|
||||
| `DryRun` | Boolean | `false` | Nur prüfen welche Updates verfügbar sind, ohne zu installieren. Kann per `-DryRun` Parameter überschrieben werden |
|
||||
| `UpdateType` | String | `All` | Art der Updates: `All` (alle Updates), `DefenderOnly` (nur Defender-Definitionsupdates). Kann per `-DefenderOnly` Parameter überschrieben werden |
|
||||
|
||||
### [WindowsUpdate]
|
||||
|
||||
@@ -109,6 +110,27 @@ Steuert, welche Ereignisse eine Benachrichtigung auslösen. Alle Ereignisse sind
|
||||
| `Enabled` | Boolean | `false` | Update-History-Tracking aktivieren |
|
||||
| `HistoryPath` | String | `C:\logs\windows-updater\update-history` | Basispfad für die History-Datei (Dateiendung wird automatisch gewählt: `.xlsx` wenn ImportExcel verfügbar, sonst `.csv`) |
|
||||
|
||||
## Kommandozeilen-Parameter
|
||||
|
||||
Das Script unterstützt Parameter, die Config-Werte überschreiben. So kann dasselbe Script mit einer Config-Datei für verschiedene Einsatzzwecke verwendet werden.
|
||||
|
||||
| Parameter | Überschreibt | Beschreibung |
|
||||
|---|---|---|
|
||||
| `-DefenderOnly` | `UpdateType` | Nur Windows Defender Definitionsupdates installieren |
|
||||
| `-DryRun` | `DryRun` | Nur prüfen, nicht installieren |
|
||||
| `-ConfigFile <Pfad>` | *(Config-Pfad)* | Alternative Konfigurationsdatei verwenden |
|
||||
|
||||
### DefenderOnly-Modus im Detail
|
||||
|
||||
Im DefenderOnly-Modus werden ausschließlich Updates der Kategorie "Definition Updates" (Windows Defender Signaturen) installiert. Folgende Funktionen werden dabei übersprungen:
|
||||
|
||||
- **Winget-Updates** — nicht relevant für Defender-Signaturen
|
||||
- **Reboot-Handling** — Definitionsupdates erfordern keinen Neustart
|
||||
- **Service Watchdog** — kein Neustart von Diensten nötig
|
||||
- **Treiber-Ausschluss** (`ExcludeDrivers`) — nicht relevant, da nur Definitionsupdates geladen werden
|
||||
|
||||
Pre-/Post-Update Hooks, Logging, History und Benachrichtigungen funktionieren normal.
|
||||
|
||||
## Boolean-Werte
|
||||
|
||||
Folgende Werte werden als `true` erkannt (Groß-/Kleinschreibung egal):
|
||||
@@ -129,6 +151,44 @@ DryRun = false
|
||||
UseMicrosoftUpdate = true
|
||||
```
|
||||
|
||||
### Nur Defender-Updates (per Config)
|
||||
|
||||
```ini
|
||||
[General]
|
||||
LogPath = C:\logs\windows-updater
|
||||
DryRun = false
|
||||
UpdateType = DefenderOnly
|
||||
|
||||
[WindowsUpdate]
|
||||
UseMicrosoftUpdate = true
|
||||
```
|
||||
|
||||
### Dual-Setup: Defender häufig + volle Updates monatlich
|
||||
|
||||
Eine Config-Datei genügt. Die Unterscheidung erfolgt per Parameter:
|
||||
|
||||
```ini
|
||||
[General]
|
||||
LogPath = C:\logs\windows-updater
|
||||
DryRun = false
|
||||
# UpdateType = All (Standard, volle Updates)
|
||||
|
||||
[WindowsUpdate]
|
||||
UseMicrosoftUpdate = true
|
||||
ExcludeDrivers = true
|
||||
RetryCount = 3
|
||||
```
|
||||
|
||||
Aufgabenplanung:
|
||||
|
||||
```powershell
|
||||
# Alle 4 Stunden: nur Defender-Updates
|
||||
powershell.exe -ExecutionPolicy Bypass -File "C:\scripts\windows-updater\windows-updater.ps1" -DefenderOnly
|
||||
|
||||
# Einmal im Monat (z.B. erster Sonntag, 03:00): alle Updates
|
||||
powershell.exe -ExecutionPolicy Bypass -File "C:\scripts\windows-updater\windows-updater.ps1"
|
||||
```
|
||||
|
||||
### Mit E-Mail Benachrichtigung
|
||||
|
||||
```ini
|
||||
|
||||
@@ -70,6 +70,77 @@ $trigger.StartBoundary = (Get-Date "04:00").ToString("yyyy-MM-dd'T'HH:mm:ss")
|
||||
|
||||
Den Rest wie beim täglichen Beispiel, nur den Trigger austauschen.
|
||||
|
||||
### Defender-Updates alle 4 Stunden
|
||||
|
||||
```powershell
|
||||
$action = New-ScheduledTaskAction `
|
||||
-Execute "powershell.exe" `
|
||||
-Argument "-ExecutionPolicy Bypass -NoProfile -File `"C:\scripts\windows-updater\windows-updater.ps1`" -DefenderOnly"
|
||||
|
||||
$trigger = New-ScheduledTaskTrigger -Once -At "00:00" -RepetitionInterval (New-TimeSpan -Hours 4)
|
||||
|
||||
$principal = New-ScheduledTaskPrincipal `
|
||||
-UserId "SYSTEM" `
|
||||
-RunLevel Highest `
|
||||
-LogonType ServiceAccount
|
||||
|
||||
$settings = New-ScheduledTaskSettingsSet `
|
||||
-AllowStartIfOnBatteries `
|
||||
-DontStopIfGoingOnBatteries `
|
||||
-StartWhenAvailable `
|
||||
-ExecutionTimeLimit (New-TimeSpan -Minutes 30)
|
||||
|
||||
Register-ScheduledTask `
|
||||
-TaskName "Windows Updater - Defender" `
|
||||
-Action $action `
|
||||
-Trigger $trigger `
|
||||
-Principal $principal `
|
||||
-Settings $settings `
|
||||
-Description "Defender-Definitionsupdates alle 4 Stunden"
|
||||
```
|
||||
|
||||
### Dual-Setup: Defender häufig + volle Updates monatlich
|
||||
|
||||
Zwei Aufgaben anlegen — eine für Defender (häufig), eine für alle Updates (selten):
|
||||
|
||||
```powershell
|
||||
# Aufgabe 1: Defender alle 4 Stunden (wie oben)
|
||||
# Aufgabe 2: Volle Updates monatlich am ersten Sonntag um 03:00
|
||||
$action = New-ScheduledTaskAction `
|
||||
-Execute "powershell.exe" `
|
||||
-Argument "-ExecutionPolicy Bypass -NoProfile -File `"C:\scripts\windows-updater\windows-updater.ps1`""
|
||||
|
||||
$trigger = New-CimInstance -CimClass (
|
||||
Get-CimClass -Namespace "Root/Microsoft/Windows/TaskScheduler" `
|
||||
-ClassName "MSFT_TaskMonthlyDOWTrigger"
|
||||
) -ClientOnly -Property @{
|
||||
DaysOfWeek = [int16]1 # Sonntag
|
||||
WeeksOfMonth = [int16]1 # Erste Woche
|
||||
Months = [int16]4095 # Alle 12 Monate
|
||||
Enabled = $true
|
||||
}
|
||||
$trigger.StartBoundary = (Get-Date "03:00").ToString("yyyy-MM-dd'T'HH:mm:ss")
|
||||
|
||||
$principal = New-ScheduledTaskPrincipal `
|
||||
-UserId "SYSTEM" `
|
||||
-RunLevel Highest `
|
||||
-LogonType ServiceAccount
|
||||
|
||||
$settings = New-ScheduledTaskSettingsSet `
|
||||
-AllowStartIfOnBatteries `
|
||||
-DontStopIfGoingOnBatteries `
|
||||
-StartWhenAvailable `
|
||||
-ExecutionTimeLimit (New-TimeSpan -Hours 2)
|
||||
|
||||
Register-ScheduledTask `
|
||||
-TaskName "Windows Updater - Monthly" `
|
||||
-Action $action `
|
||||
-Trigger $trigger `
|
||||
-Principal $principal `
|
||||
-Settings $settings `
|
||||
-Description "Vollständige Windows Updates monatlich"
|
||||
```
|
||||
|
||||
### Bestehende Aufgabe ändern
|
||||
|
||||
```powershell
|
||||
@@ -168,3 +239,4 @@ Get-ScheduledTaskInfo -TaskName "Windows Updater" | Select-Object LastRunTime, L
|
||||
| Server (nicht-kritisch) | Täglich, 03:00-05:00 mit Auto-Reboot |
|
||||
| Server (kritisch/Produktion) | Wöchentlich Sonntag, 03:00 mit DryRun. Manuell nach Prüfung |
|
||||
| Testumgebung | Täglich, 02:00 mit Auto-Reboot |
|
||||
| Defender-Signaturen | Alle 4 Stunden mit `-DefenderOnly`, zusätzlich zu einem der obigen Szenarien |
|
||||
|
||||
@@ -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
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user