-
This commit is contained in:
parent
21ac65f282
commit
66188144d2
1 changed files with 116 additions and 94 deletions
202
cleanup.ps1
202
cleanup.ps1
|
|
@ -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"
|
||||
}
|
||||
$UpdateSession = New-Object -ComObject "Microsoft.Update.Session"
|
||||
$UpdateSearcher = $UpdateSession.CreateUpdateSearcher()
|
||||
$UpdateDownloader = $UpdateSession.CreateUpdateDownloader()
|
||||
$UpdateInstaller = $UpdateSession.CreateUpdateInstaller()
|
||||
|
||||
# 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"
|
||||
}
|
||||
Write-Log "Searching for available Windows updates..." -Level "INFO"
|
||||
|
||||
# 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"
|
||||
}
|
||||
}
|
||||
# Search for updates
|
||||
$SearchResult = $UpdateSearcher.Search("IsInstalled=0 and Type='Software'")
|
||||
$AvailableUpdates = $SearchResult.Updates
|
||||
|
||||
# Check for and install Windows updates
|
||||
if ($ScriptResult.windows_updates.pswindowsupdate_installed) {
|
||||
try {
|
||||
Write-Log "Checking for and installing Windows updates..." -Level "INFO"
|
||||
$ScriptResult.windows_updates.updates_available = $AvailableUpdates.Count
|
||||
Write-Log "Found $($AvailableUpdates.Count) Windows update(s)." -Level "INFO"
|
||||
|
||||
# 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
|
||||
if ($AvailableUpdates.Count -gt 0) {
|
||||
# Prepare download collection
|
||||
$UpdatesToDownload = New-Object -ComObject "Microsoft.Update.UpdateColl"
|
||||
|
||||
# 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"
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue