This commit is contained in:
Joeri 2026-02-07 11:19:57 +01:00
parent 21ac65f282
commit 66188144d2

View file

@ -18,7 +18,7 @@ $LogDirectory = "C:\Quest"
$LogDate = Get-Date -Format "yyyy-MM-dd"
$RandomSuffix = Get-Random -Minimum 1000 -Maximum 9999
$LogFile = Join-Path $LogDirectory "cleanup-${LogDate}-${RandomSuffix}.log"
$WebhookUrl = "https://n8n.questcomputers.be/webhook/99077b7d-140f-477e-9241-2b9581ddaf34"
$WebhookUrl = "https://n8n.questcomputers.be/webhook-test/99077b7d-140f-477e-9241-2b9581ddaf34"
$ScriptStartTime = Get-Date
# Configuration - Timeout for winget (in seconds)
@ -32,7 +32,7 @@ if (-not (Test-Path $LogDirectory)) {
# Initialize structured data object
$ScriptResult = [ordered]@{
"script_name" = "System Cleanup Script"
"version" = "1.1"
"version" = "1.2"
"execution_info" = @{
"started_at" = $ScriptStartTime.ToString("yyyy-MM-dd HH:mm:ss")
"computer_name" = $env:COMPUTERNAME
@ -338,7 +338,6 @@ if ($ScriptResult.app_updates.winget_available) {
# Create temporary files for output
$WingetOutputFile = Join-Path $LogDirectory "winget_output.txt"
$WingetErrorFile = Join-Path $LogDirectory "winget_error.txt"
# Start winget process with timeout
$wingetProcess = Start-Process -FilePath "winget" -ArgumentList "upgrade --all --silent --accept-package-agreements --accept-source-agreements" -NoNewWindow -Wait -PassThru -ErrorAction Stop
@ -349,9 +348,13 @@ if ($ScriptResult.app_updates.winget_available) {
Write-Log "Winget exit code: $WingetExitCode" -Level "INFO"
Write-Log "Winget duration: $($WingetDuration.ToString('F2')) seconds" -Level "INFO"
# Read output if available
if (Test-Path $WingetOutputFile) {
$wingetOutput = Get-Content $WingetOutputFile -Raw
# Parse winget output from log file if available
$wingetOutput = Get-Content $LogFile | Select-String -Pattern "winget|Winget|Upgrading|Upgraded" -Context 2 | Out-String
$wingetOutput | Out-File -FilePath $LogFile -Append -Encoding UTF8
# Alternative: Try to capture output directly
try {
$wingetOutput = winget upgrade --all --silent 2>&1 | Out-String
$wingetOutput | Out-File -FilePath $LogFile -Append -Encoding UTF8
# Parse winget output to extract updated apps
@ -374,16 +377,14 @@ if ($ScriptResult.app_updates.winget_available) {
$ScriptResult.app_updates.apps_updated = $AppsUpdated
$ScriptResult.app_updates.apps_checked = $AppsUpdated.Count
# Clean up temporary files
Remove-Item $WingetOutputFile -ErrorAction SilentlyContinue
Remove-Item $WingetErrorFile -ErrorAction SilentlyContinue
} catch {
Write-Log "Could not capture winget output: $($_.Exception.Message)" -Level "WARNING"
}
if ($AppsUpdated.Count -gt 0) {
Write-Log "Application updates completed. Updated $($AppsUpdated.Count) application(s): $($AppsUpdated -join ', ')" -Level "INFO"
} else {
Write-Log "Application updates completed. All applications are up to date." -Level "INFO"
Write-Log "Application updates completed. All applications are up to date or winget output could not be parsed." -Level "INFO"
}
} catch {
# Check if it's a timeout
@ -405,112 +406,133 @@ Write-Log "Application updates section completed." -Level "INFO"
"" | Out-File -FilePath $LogFile -Append -Encoding UTF8
# --------------------------------------------------------------------------------
# Updating Windows
# Updating Windows (using Windows Update API directly)
# --------------------------------------------------------------------------------
Write-Log "================================================================================" -Level "INFO"
Write-Log "SECTION: Windows Updates" -Level "INFO"
Write-Log "================================================================================" -Level "INFO"
# Install NuGet provider
Write-Log "Installing NuGet package provider..." -Level "INFO"
# Load Windows Update COM object
Write-Log "Initializing Windows Update service..." -Level "INFO"
try {
Install-PackageProvider -Name NuGet -MinimumVersion 2.8.5.201 -Force -ErrorAction Stop | Out-Null
$ScriptResult.windows_updates.nuget_installed = $true
Write-Log "NuGet package provider installed successfully." -Level "INFO"
} catch {
Write-Log "Failed to install NuGet: $($_.Exception.Message)" -Level "ERROR"
}
# Install PSWindowsUpdate module
Write-Log "Installing PSWindowsUpdate module..." -Level "INFO"
try {
Install-Module PSWindowsUpdate -Force -AllowClobber -ErrorAction Stop | Out-Null
$ScriptResult.windows_updates.pswindowsupdate_installed = $true
Write-Log "PSWindowsUpdate module installed successfully." -Level "INFO"
} catch {
Write-Log "Failed to install PSWindowsUpdate: $($_.Exception.Message)" -Level "ERROR"
}
# Import PSWindowsUpdate module
if ($ScriptResult.windows_updates.pswindowsupdate_installed) {
try {
Write-Log "Importing PSWindowsUpdate module..." -Level "INFO"
Import-Module PSWindowsUpdate -ErrorAction Stop
Write-Log "PSWindowsUpdate module imported successfully." -Level "INFO"
} catch {
Write-Log "Failed to import PSWindowsUpdate: $($_.Exception.Message)" -Level "ERROR"
}
}
# Check for and install Windows updates
if ($ScriptResult.windows_updates.pswindowsupdate_installed) {
try {
Write-Log "Checking for and installing Windows updates..." -Level "INFO"
$UpdateSession = New-Object -ComObject "Microsoft.Update.Session"
$UpdateSearcher = $UpdateSession.CreateUpdateSearcher()
$UpdateDownloader = $UpdateSession.CreateUpdateDownloader()
$UpdateInstaller = $UpdateSession.CreateUpdateInstaller()
Write-Log "Searching for available Windows updates..." -Level "INFO"
# Search for updates
$SearchResult = $UpdateSearcher.Search("IsInstalled=0 and Type='Software'")
$AvailableUpdates = $SearchResult.Updates
$ScriptResult.windows_updates.updates_available = $AvailableUpdates.Count
Write-Log "Found $($AvailableUpdates.Count) Windows update(s)." -Level "INFO"
if ($AvailableUpdates.Count -gt 0) {
# Prepare download collection
$UpdatesToDownload = New-Object -ComObject "Microsoft.Update.UpdateColl"
# Run Windows update check and install in one command
$UpdateOutput = Get-WindowsUpdate -AcceptAll -Install -IgnoreUser -IgnoreReboot -ErrorAction Stop 2>&1 | Out-String
$UpdateOutput | Out-File -FilePath $LogFile -Append -Encoding UTF8
# Parse the output to extract KB numbers and titles
$UpdateLines = $UpdateOutput -split "`n"
$UpdatesFound = $false
$UpdatesInstalled = @()
foreach ($line in $UpdateLines) {
# Look for KB pattern in the output
if ($line -match "KB\d+" -or $line -match "Update for|Security Update|Cumulative Update") {
$UpdatesFound = $true
# Extract KB number
$kbMatch = [regex]::Match($line, 'KB\d+')
$kb = if ($kbMatch.Success) { $kbMatch.Value } else { "Unknown" }
# Extract title (remove KB number and extra spaces)
$title = $line -replace 'KB\d+\s*' -replace '\s+' -replace '^\s*|\s*$' -trim
if ($title -and $title.Length -gt 3) {
$UpdateInfo = @{
"kb" = $kb
"title" = $title
"description" = ""
"size_mb" = 0
"is_downloaded" = $true
"reboot_required" = $false
}
$UpdatesInstalled += $UpdateInfo
}
foreach ($Update in $AvailableUpdates) {
$UpdateInfo = @{
"kb" = if ($Update.KBArticleIDs.Count -gt 0) { "KB$($Update.KBArticleIDs[0])" } else { "Unknown" }
"title" = $Update.Title
"description" = $Update.Description
"size_mb" = [math]::Round($Update.MaxDownloadSize / 1MB, 2)
"is_downloaded" = $false
"reboot_required" = ($Update.InstallationBehavior.RebootBehavior -ne "NeverRequiresReboot")
}
$ScriptResult.windows_updates.updates_installed += $UpdateInfo
# Add to download collection
$UpdatesToDownload.Add($Update) | Out-Null
}
$ScriptResult.windows_updates.updates_installed = $UpdatesInstalled
$ScriptResult.windows_updates.updates_available = $UpdatesInstalled.Count
# Download updates
Write-Log "Downloading $($AvailableUpdates.Count) update(s)..." -Level "INFO"
$UpdateDownloader.Updates = $UpdatesToDownload
$DownloadResult = $UpdateDownloader.Download()
# Check if reboot is required from output
if ($UpdateOutput -match "reboot|Reboot|restart|restart your computer") {
$ScriptResult.windows_updates.reboot_required = $true
# Check download result
$DownloadResultCode = switch ($DownloadResult.ResultCode) {
0 { "NotStarted" }
1 { "InProgress" }
2 { "Succeeded" }
3 { "SucceededWithErrors" }
4 { "Failed" }
5 { "Aborted" }
default { "Unknown" }
}
Write-Log "Download result: $DownloadResultCode" -Level "INFO"
if ($DownloadResult.ResultCode -in @(2, 3)) {
# Prepare installation collection
$UpdatesToInstall = New-Object -ComObject "Microsoft.Update.UpdateColl"
foreach ($Update in $AvailableUpdates) {
if ($Update.IsDownloaded) {
$UpdatesToInstall.Add($Update) | Out-Null
}
}
# Install updates
Write-Log "Installing $($UpdatesToInstall.Count) update(s)..." -Level "INFO"
$UpdateInstaller.Updates = $UpdatesToInstall
$InstallResult = $UpdateInstaller.Install()
# Check installation result
$InstallResultCode = switch ($InstallResult.ResultCode) {
0 { "NotStarted" }
1 { "InProgress" }
2 { "Succeeded" }
3 { "SucceededWithErrors" }
4 { "Failed" }
5 { "Aborted" }
default { "Unknown" }
}
Write-Log "Installation result: $InstallResultCode" -Level "INFO"
# Check if reboot is required
if ($InstallResult.RebootRequired) {
$ScriptResult.windows_updates.reboot_required = $true
}
# Update status for downloaded updates
for ($i = 0; $i -lt $ScriptResult.windows_updates.updates_installed.Count; $i++) {
$ScriptResult.windows_updates.updates_installed[$i].is_downloaded = $true
}
}
Write-Log "Windows updates installation completed." -Level "INFO"
if ($UpdatesInstalled.Count -gt 0) {
Write-Log "Installed $($UpdatesInstalled.Count) update(s):" -Level "INFO"
foreach ($update in $UpdatesInstalled) {
if ($ScriptResult.windows_updates.updates_installed.Count -gt 0) {
Write-Log "Installed $($ScriptResult.windows_updates.updates_installed.Count) update(s):" -Level "INFO"
foreach ($update in $ScriptResult.windows_updates.updates_installed) {
Write-Log " - $($update.kb): $($update.title)" -Level "INFO"
}
} else {
Write-Log "No Windows updates were needed or found." -Level "INFO"
}
if ($ScriptResult.windows_updates.reboot_required) {
Write-Log "A system reboot is required to complete the updates." -Level "WARNING"
}
} catch {
$ErrorMsg = "Failed to install Windows updates: $($_.Exception.Message)"
$ScriptResult.windows_updates.errors += $ErrorMsg
Write-Log $ErrorMsg -Level "ERROR"
} else {
Write-Log "No Windows updates were needed." -Level "INFO"
}
} else {
Write-Log "PSWindowsUpdate not installed. Skipping Windows updates." -Level "INFO"
# Clean up COM objects
[System.Runtime.Interopservices.Marshal]::ReleaseComObject($UpdateInstaller) | Out-Null
[System.Runtime.Interopservices.Marshal]::ReleaseComObject($UpdateDownloader) | Out-Null
[System.Runtime.Interopservices.Marshal]::ReleaseComObject($UpdateSearcher) | Out-Null
[System.Runtime.Interopservices.Marshal]::ReleaseComObject($UpdateSession) | Out-Null
[System.GC]::Collect()
[System.GC]::WaitForPendingFinalizers()
} catch {
$ErrorMsg = "Failed to install Windows updates: $($_.Exception.Message)"
$ScriptResult.windows_updates.errors += $ErrorMsg
Write-Log $ErrorMsg -Level "ERROR"
}
Write-Log "Windows updates section completed." -Level "INFO"