Skip to content

Instantly share code, notes, and snippets.

@xopez
Last active August 31, 2025 07:09
Show Gist options
  • Select an option

  • Save xopez/66b7c8b6d4520845a498e302591d73b4 to your computer and use it in GitHub Desktop.

Select an option

Save xopez/66b7c8b6d4520845a498e302591d73b4 to your computer and use it in GitHub Desktop.
Updater for Chocolatey
# PowerShell Script fuer Chocolatey Auto-Update
param(
[Parameter(Position = 0)]
[string]$Action
)
$ScriptPath = $MyInvocation.MyCommand.Path
$TaskName = "ChocolateyAutoUpdate"
# Funktion zur Ueberpruefung der Internetverbindung
function Test-InternetConnection {
# Teste nur Chocolatey-relevante Domains
$testUrls = @(
"https://community.chocolatey.org",
"https://chocolatey.org"
)
foreach ($url in $testUrls) {
try {
$response = Invoke-WebRequest -Uri $url -UseBasicParsing -TimeoutSec 10 -Method Head -ErrorAction Stop
if ($response.StatusCode -eq 200) {
return $true
}
}
catch {
continue
}
}
return $false
}
# Funktion zum Erstellen des geplanten Tasks
function Install-ScheduledTask {
Write-Host "Erstelle geplanten Task fuer automatische Updates..."
try {
# Entferne existierenden Task falls vorhanden
Unregister-ScheduledTask -TaskName $TaskName -Confirm:$false -ErrorAction SilentlyContinue
# Erstelle Aktion
$Action = New-ScheduledTaskAction -Execute "PowerShell.exe" -Argument "-ExecutionPolicy Bypass -File `"$ScriptPath`" -Action UpdateOnly"
# Erstelle Trigger: Bei Systemstart und alle 12 Stunden
$TriggerStartup = New-ScheduledTaskTrigger -AtStartup
$TriggerInterval = New-ScheduledTaskTrigger -Once -At (Get-Date) -RepetitionInterval (New-TimeSpan -Hours 12) -RepetitionDuration (New-TimeSpan -Days 365)
# Erstelle Einstellungen
$Settings = New-ScheduledTaskSettingsSet -AllowStartIfOnBatteries -DontStopIfGoingOnBatteries -StartWhenAvailable -DontStopOnIdleEnd
# Erstelle Principal mit SYSTEM-Rechten fuer Ausfuehrung ohne Benutzeranmeldung
$Principal = New-ScheduledTaskPrincipal -UserId "SYSTEM" -LogonType ServiceAccount -RunLevel Highest
# Registriere Task
Register-ScheduledTask -TaskName $TaskName -Action $Action -Trigger @($TriggerStartup, $TriggerInterval) -Settings $Settings -Principal $Principal -Description "Automatisches Chocolatey Update bei Systemstart und alle 12 Stunden"
Write-Host "Geplanter Task erstellt und aktiviert:"
Write-Host " - Laeuft bei jedem System-Start"
Write-Host " - Laeuft alle 12 Stunden"
}
catch {
Write-Error "Fehler beim Erstellen des geplanten Tasks: $($_.Exception.Message)"
exit 1
}
}
# Funktion zum Entfernen des geplanten Tasks
function Remove-ScheduledTask {
try {
$task = Get-ScheduledTask -TaskName $TaskName -ErrorAction SilentlyContinue
if ($task) {
Write-Host "Entferne geplanten Task..."
Unregister-ScheduledTask -TaskName $TaskName -Confirm:$false
Write-Host "Geplanter Task entfernt."
}
else {
Write-Host "Kein geplanter Task gefunden."
}
}
catch {
Write-Error "Fehler beim Entfernen des geplanten Tasks: $($_.Exception.Message)"
}
}
# Funktion fuer das Chocolatey Update
function Start-ChocolateyUpdate {
# Pruefe ob Script als SYSTEM laeuft (ueber SID - sprachenunabhaengig)
$currentUser = [System.Security.Principal.WindowsIdentity]::GetCurrent()
$isSystem = $currentUser.User.Value -eq "S-1-5-18" # SYSTEM Account SID
# Debug-Ausgabe
$userName = $currentUser.Name
if ($isSystem) {
# Fuer SYSTEM: Verwende festen Log-Ordner in C:\Windows\Temp
$sessionTempPath = "C:\Windows\Temp\ChocolateyAutoUpdate"
}
else {
# Fuer User: Erstelle session-spezifischen Temp-Ordner
$sessionId = [System.Diagnostics.Process]::GetCurrentProcess().SessionId
$sessionTempPath = Join-Path $env:TEMP "ChocolateyAutoUpdate_UserSession_$($sessionId)"
}
$LogFile = Join-Path $sessionTempPath "update.log"
$ErrorFile = Join-Path $sessionTempPath "error.log"
# Erstelle temporaeren Ordner falls nicht vorhanden
if (-not (Test-Path $sessionTempPath)) {
New-Item -ItemType Directory -Path $sessionTempPath -Force | Out-Null
}
# Debug-Ausgabe fuer User-Kontext
$debugMsg = "Script laeuft als: $userName (SID: $($currentUser.User.Value), isSystem: $isSystem)"
Write-Host $debugMsg
Add-Content -Path $LogFile -Value $debugMsg -Encoding UTF8
# SYSTEM: Nur die letzten 30 Logdateien behalten
if ($isSystem) {
$logFiles = Get-ChildItem -Path $sessionTempPath -Filter '*.log' -File | Sort-Object LastWriteTime -Descending
if ($logFiles.Count -gt 30) {
$logFiles | Select-Object -Skip 30 | Remove-Item -Force -ErrorAction SilentlyContinue
}
} else {
# Registry-Cleanup nur fuer User-Kontext
# Erstelle Batch-Datei fuer Logout-Cleanup
$cleanupBatch = Join-Path $sessionTempPath "cleanup.bat"
@"
@echo off
timeout /t 2 /nobreak >nul
rd /s /q "$sessionTempPath" 2>nul
"@ | Out-File -FilePath $cleanupBatch -Encoding ASCII
# Registriere Cleanup fuer Windows-Logout ueber Registry (RunOnce)
try {
$runOncePath = "HKCU:\Software\Microsoft\Windows\CurrentVersion\RunOnce"
Set-ItemProperty -Path $runOncePath -Name "ChocolateyAutoUpdate_Cleanup" -Value "`"$cleanupBatch`"" -Force
}
catch {
# Fallback: Verwende PowerShell Registry fuer Cleanup
try {
New-ItemProperty -Path $runOncePath -Name "ChocolateyAutoUpdate_Cleanup" -Value "cmd.exe /c rd /s /q `"$sessionTempPath`"" -Force
}
catch { }
}
}
# Erstelle Log-Eintrag mit Timestamp
$timestamp = Get-Date -Format "yyyy-MM-dd HH:mm:ss"
try {
$message = "$timestamp Ueberpruefe Internetverbindung..."
Write-Host $message
Add-Content -Path $LogFile -Value $message -Encoding UTF8
# Warte maximal 5 Minuten auf Internetverbindung
$timeout = 300
$elapsed = 0
while (-not (Test-InternetConnection) -and ($elapsed -lt $timeout)) {
$message = "$timestamp Keine Internetverbindung verfuegbar. Warte 30 Sekunden... ($elapsed/$timeout)"
Write-Host $message
Add-Content -Path $LogFile -Value $message -Encoding UTF8
Start-Sleep -Seconds 30
$elapsed += 30
$timestamp = Get-Date -Format "yyyy-MM-dd HH:mm:ss"
}
if ($elapsed -ge $timeout) {
$errorMsg = "$timestamp Timeout: Keine Internetverbindung nach 5 Minuten. Abbruch."
Write-Error $errorMsg
$errorMsg | Add-Content -Path $ErrorFile
exit 1
}
$message = "$timestamp Internetverbindung verfuegbar. Starte Chocolatey Auto-Update..."
Write-Host $message
Add-Content -Path $LogFile -Value $message -Encoding UTF8
# Pruefe ob Chocolatey installiert ist
if (-not (Get-Command choco -ErrorAction SilentlyContinue)) {
$errorMsg = "$timestamp Fehler: Chocolatey ist nicht installiert oder nicht im PATH verfuegbar."
Write-Error $errorMsg
$errorMsg | Add-Content -Path $ErrorFile
exit 1
}
$message = "$timestamp Fuehre choco upgrade all aus..."
Write-Host $message
Add-Content -Path $LogFile -Value $message -Encoding UTF8
# Pruefe erst welche Pakete Updates benoetigen
$message = "$timestamp Pruefe auf veraltete Pakete..."
Write-Host $message
Add-Content -Path $LogFile -Value $message -Encoding UTF8
$outdated = choco outdated -r --ignore-unfound 2>>$ErrorFile
if ($outdated) {
$message = "$timestamp Gefundene veraltete Pakete:"
Write-Host $message
Add-Content -Path $LogFile -Value $message -Encoding UTF8
Write-Host $outdated
Add-Content -Path $LogFile -Value $outdated -Encoding UTF8
$message = "$timestamp Starte Update nur fuer veraltete Pakete..."
Write-Host $message
Add-Content -Path $LogFile -Value $message -Encoding UTF8
$upgradeOutput = choco upgrade all -y --ignore-unfound 2>> $ErrorFile
Write-Host $upgradeOutput
Add-Content -Path $LogFile -Value $upgradeOutput -Encoding UTF8
}
else {
$message = "$timestamp Keine veralteten Pakete gefunden. Kein Update erforderlich."
Write-Host $message
Add-Content -Path $LogFile -Value $message -Encoding UTF8
}
if ($LASTEXITCODE -eq 0) {
$message = "$timestamp Chocolatey Auto-Update abgeschlossen."
Write-Host $message
Add-Content -Path $LogFile -Value $message -Encoding UTF8
}
else {
$errorMsg = "$timestamp Chocolatey Update mit Fehlern beendet (Exit Code: $LASTEXITCODE)"
Write-Warning $errorMsg
$errorMsg | Add-Content -Path $ErrorFile
}
}
catch {
$errorMsg = "$timestamp Fehler beim Chocolatey Update: $($_.Exception.Message)"
Write-Error $errorMsg
$errorMsg | Add-Content -Path $ErrorFile
exit 1
}
# Log-Ordner Info anzeigen
if ($isSystem) {
Write-Host "SYSTEM-Context: Logs verfuegbar unter: $sessionTempPath"
Write-Host "SYSTEM-Logs werden nicht automatisch bereinigt."
}
else {
Write-Host "User Session-Temp Ordner verfuegbar unter: $sessionTempPath"
Write-Host "Ordner wird beim Windows-Logout automatisch bereinigt."
}
}
# Hauptlogik
switch ($Action.ToLower()) {
"install-task" {
Install-ScheduledTask
}
"remove-task" {
Remove-ScheduledTask
}
"updateonly" {
Start-ChocolateyUpdate
}
"help" {
Write-Host "Verwendung: .\chocolatey-autoupdate.ps1 [OPTION]"
Write-Host ""
Write-Host "Optionen:"
Write-Host " install-task Installiert automatischen Task (bei Reboot + alle 12h)"
Write-Host " remove-task Entfernt automatischen Task"
Write-Host " updateonly Fuehrt nur das Update aus (fuer internen Gebrauch)"
Write-Host " help Zeigt diese Hilfe an"
Write-Host ""
Write-Host "Ohne Argument: Fuehrt einmalig ein Update aus"
}
default {
Start-ChocolateyUpdate
}
}
@xopez
Copy link
Author

xopez commented Aug 30, 2025

Set-ExecutionPolicy -ExecutionPolicy RemoteSigned -Scope LocalMachine 

install-task: Installiert automatischen Task (bei Reboot + alle 12h)
remove-task: Entfernt automatischen Task
updateonly: Führt nur das Update aus (für internen Gebrauch)
help: Zeigt diese Hilfe an

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment