8.1 KiB
Aufgabenplanung (Task Scheduler)
Das Script kann über die Windows Aufgabenplanung automatisch ausgeführt werden, z.B. täglich zu einer bestimmten Uhrzeit.
Voraussetzungen
- Das Script muss als Administrator (bzw. SYSTEM) ausgeführt werden
- Eine
config.inimuss im Script-Verzeichnis vorhanden sein - PowerShell 5.1 muss verfügbar sein (auf allen unterstützten OS standardmäßig vorhanden)
Aufgabe per PowerShell erstellen (empfohlen)
Folgende Befehle in einer administrativen PowerShell ausführen:
Täglich um 04:00 Uhr
$action = New-ScheduledTaskAction `
-Execute "powershell.exe" `
-Argument "-ExecutionPolicy Bypass -NoProfile -File `"C:\scripts\windows-updater\windows-updater.ps1`""
$trigger = New-ScheduledTaskTrigger -Daily -At "04:00"
$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" `
-Action $action `
-Trigger $trigger `
-Principal $principal `
-Settings $settings `
-Description "Automatische Windows Updates mit Benachrichtigung"
Wöchentlich (z.B. Sonntags um 03:00 Uhr)
$trigger = New-ScheduledTaskTrigger -Weekly -DaysOfWeek Sunday -At "03:00"
Den Rest wie oben, nur den Trigger austauschen.
Monatlich (z.B. erster Montag im Monat um 04:00 Uhr)
$trigger = New-ScheduledTaskTrigger -Weekly -DaysOfWeek Monday -WeeksInterval 1 -At "04:00"
# New-ScheduledTaskTrigger bietet kein -Monthly mit Wochentag-Option,
# daher wird der CIM-Trigger verwendet (entspricht GUI → "Monatlich"):
$trigger = New-CimInstance -CimClass (
Get-CimClass -Namespace "Root/Microsoft/Windows/TaskScheduler" `
-ClassName "MSFT_TaskMonthlyDOWTrigger"
) -ClientOnly -Property @{
DaysOfWeek = [int16]2 # Montag (So=1, Mo=2, Di=4, Mi=8, Do=16, Fr=32, Sa=64)
WeeksOfMonth = [int16]1 # Erste Woche
Months = [int16]4095 # Alle 12 Monate (Bit-Summe: 1+2+4+...+2048)
Enabled = $true
}
$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
$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):
# 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
# Uhrzeit ändern
$trigger = New-ScheduledTaskTrigger -Daily -At "02:00"
Set-ScheduledTask -TaskName "Windows Updater" -Trigger $trigger
# Aufgabe deaktivieren
Disable-ScheduledTask -TaskName "Windows Updater"
# Aufgabe aktivieren
Enable-ScheduledTask -TaskName "Windows Updater"
# Aufgabe löschen
Unregister-ScheduledTask -TaskName "Windows Updater" -Confirm:$false
Aufgabe manuell starten (zum Testen)
Start-ScheduledTask -TaskName "Windows Updater"
Aufgabe per GUI erstellen
taskschd.mscöffnen (oder "Aufgabenplanung" im Startmenü suchen)- Rechtsklick auf "Aufgabenplanungsbibliothek" → "Aufgabe erstellen..."
- Reiter Allgemein:
- Name:
Windows Updater - "Mit höchsten Privilegien ausführen" aktivieren
- "Unabhängig von der Benutzeranmeldung ausführen" wählen
- Benutzer auf
SYSTEMändern
- Name:
- Reiter Trigger:
- Neuer Trigger → Täglich → Startzeit z.B. 04:00
- Reiter Aktionen:
- Neue Aktion → "Programm starten"
- Programm:
powershell.exe - Argumente:
-ExecutionPolicy Bypass -NoProfile -File "C:\scripts\windows-updater\windows-updater.ps1"
- Reiter Einstellungen:
- "Aufgabe so schnell wie möglich nach einem verpassten Start ausführen" aktivieren
- "Aufgabe beenden, falls sie länger ausgeführt wird als:" 2 Stunden
Wichtige Hinweise
SYSTEM-Kontext
Das Script läuft als SYSTEM-Benutzer. Beachte dabei:
- Netzlaufwerke sind nicht verfügbar (SYSTEM hat keine zugeordneten Laufwerke)
- Umgebungsvariablen wie
%USERPROFILE%zeigen aufC:\Windows\system32\config\systemprofile - winget muss ggf. über den vollen Pfad aufgerufen werden (das Script behandelt dies automatisch)
- Log-Dateien müssen in einem Verzeichnis liegen, auf das SYSTEM Schreibrechte hat (z.B.
C:\logs\)
Execution Policy
Das Script wird mit -ExecutionPolicy Bypass aufgerufen, damit es ohne vorherige Änderung der systemweiten Execution Policy läuft. Dies ist sicher, da nur dieses spezifische Script betroffen ist.
Timeout
Die Standard-Ausführungszeitbegrenzung ist auf 2 Stunden gesetzt. Bei Servern mit vielen Updates kann dies ggf. erhöht werden:
$settings = New-ScheduledTaskSettingsSet `
-ExecutionTimeLimit (New-TimeSpan -Hours 4)
Set-ScheduledTask -TaskName "Windows Updater" -Settings $settings
Log prüfen
Nach der ersten automatischen Ausführung die Logs prüfen:
# Heutiges Log anzeigen
$today = Get-Date -Format "yyyy-MM-dd"
Get-Content "C:\logs\windows-updater\windows-updater_$today.log"
# Letzten Lauf in der Aufgabenplanung prüfen
Get-ScheduledTaskInfo -TaskName "Windows Updater" | Select-Object LastRunTime, LastTaskResult
Exit-Codes in der Aufgabenplanung
| Task Result | Bedeutung |
|---|---|
| 0 | Erfolg |
| 1 | Fehler (Details im Log) |
| 2 | Neustart erforderlich (Auto-Reboot deaktiviert) |
| 0x1 | Allgemeiner Fehler |
| 0x41301 | Aufgabe läuft gerade |
Empfohlene Zeitplanung
| Szenario | Empfehlung |
|---|---|
| Arbeitsstation | Täglich, 12:00 (Mittagspause) mit DryRun, Manuelles Update später |
| 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 |