# 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.ini` muss 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 ```powershell $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) ```powershell $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) ```powershell $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 ```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 # 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) ```powershell Start-ScheduledTask -TaskName "Windows Updater" ``` ## Aufgabe per GUI erstellen 1. `taskschd.msc` öffnen (oder "Aufgabenplanung" im Startmenü suchen) 2. Rechtsklick auf "Aufgabenplanungsbibliothek" → "Aufgabe erstellen..." 3. 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 4. Reiter **Trigger**: - Neuer Trigger → Täglich → Startzeit z.B. 04:00 5. Reiter **Aktionen**: - Neue Aktion → "Programm starten" - Programm: `powershell.exe` - Argumente: `-ExecutionPolicy Bypass -NoProfile -File "C:\scripts\windows-updater\windows-updater.ps1"` 6. 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 auf `C:\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: ```powershell $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: ```powershell # 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 |