From b0bc165a3933438dc7df9a40bb998517ddb16a61 Mon Sep 17 00:00:00 2001 From: Jason Ross Date: Thu, 18 Jun 2026 08:17:17 -0500 Subject: [PATCH] system automation scripts --- .gitignore | 1 + Register-ChocoUpgradeTask.ps1 | 53 ++++++++++++++++++++++ Register-WingetMsStoreTask.ps1 | 53 ++++++++++++++++++++++ Update-Discord.ps1 | 81 ++++++++++++++++++++++++++++++++++ Upgrade-Choco.ps1 | 37 ++++++++++++++++ Upgrade-WingetMsStore.ps1 | 36 +++++++++++++++ 6 files changed, 261 insertions(+) create mode 100644 .gitignore create mode 100644 Register-ChocoUpgradeTask.ps1 create mode 100644 Register-WingetMsStoreTask.ps1 create mode 100644 Update-Discord.ps1 create mode 100644 Upgrade-Choco.ps1 create mode 100644 Upgrade-WingetMsStore.ps1 diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..397b4a7 --- /dev/null +++ b/.gitignore @@ -0,0 +1 @@ +*.log diff --git a/Register-ChocoUpgradeTask.ps1 b/Register-ChocoUpgradeTask.ps1 new file mode 100644 index 0000000..673c4a6 --- /dev/null +++ b/Register-ChocoUpgradeTask.ps1 @@ -0,0 +1,53 @@ +# Register-ChocoUpgradeTask.ps1 +# Registers a scheduled task to run Upgrade-Choco.ps1 daily at 2:00 AM. + +$TaskName = "Chocolatey Daily Upgrade" +$TaskDescription = "Runs choco upgrade all -y daily at 2:00 AM with Administrator privileges." +$ScriptPath = Join-Path $PSScriptRoot "Upgrade-Choco.ps1" + +# Ensure the script exists +if (-not (Test-Path $ScriptPath)) { + Write-Error "Error: Upgrade-Choco.ps1 not found at $ScriptPath" + exit 1 +} + +Write-Output "Configuring scheduled task: $TaskName" +Write-Output "Target script: $ScriptPath" + +# Define Action +$Action = New-ScheduledTaskAction -Execute "powershell.exe" -Argument "-NoProfile -WindowStyle Hidden -ExecutionPolicy Bypass -File `"$ScriptPath`"" + +# Define Trigger (Daily at 2:00 AM) +# Note: Using 2:00 AM for the trigger start boundary +$Trigger = New-ScheduledTaskTrigger -Daily -At "2:00 AM" + +# Define Settings: +# - Allow start on batteries: Yes +# - Don't stop if going on batteries: Yes +# - Start when available: Yes (runs as soon as possible if a scheduled start is missed) +# - Execution time limit: 2 hours (in case it hangs) +$Settings = New-ScheduledTaskSettingsSet -AllowStartIfOnBatteries -DontStopIfGoingOnBatteries -StartWhenAvailable -ExecutionTimeLimit (New-TimeSpan -Hours 2) + +# Define Principal: +# Run as NT AUTHORITY\SYSTEM to ensure it runs elevated and doesn't require a logged-in user session. +$Principal = New-ScheduledTaskPrincipal -UserId "NT AUTHORITY\SYSTEM" -LogonType ServiceAccount -RunLevel Highest + +# Register Scheduled Task (Overwrites if it already exists) +try { + # If task exists, unregister it first to avoid conflicts + if (Get-ScheduledTask -TaskName $TaskName -ErrorAction SilentlyContinue) { + Write-Output "Existing task found. Re-registering..." + Unregister-ScheduledTask -TaskName $TaskName -Confirm:$false + } + + $Task = Register-ScheduledTask -TaskName $TaskName -Description $TaskDescription -Action $Action -Trigger $Trigger -Settings $Settings -Principal $Principal + Write-Output "Successfully registered scheduled task '$TaskName'." + Write-Output "Task details:" + Write-Output " State: $($Task.State)" + Write-Output " Trigger: Daily at 2:00 AM" + Write-Output " Principal: $($Task.Principal.UserId) ($($Task.Principal.RunLevel))" +} +catch { + Write-Error "Failed to register scheduled task: $_" + exit 1 +} diff --git a/Register-WingetMsStoreTask.ps1 b/Register-WingetMsStoreTask.ps1 new file mode 100644 index 0000000..d4b08af --- /dev/null +++ b/Register-WingetMsStoreTask.ps1 @@ -0,0 +1,53 @@ +# Register-WingetMsStoreTask.ps1 +# Registers a scheduled task to run Upgrade-WingetMsStore.ps1 daily at 2:00 AM. + +$TaskName = "WinGet MS Store Upgrade" +$TaskDescription = "Runs winget upgrade for MS Store packages daily at 2:00 AM." +$ScriptPath = Join-Path $PSScriptRoot "Upgrade-WingetMsStore.ps1" + +# Ensure the script exists +if (-not (Test-Path $ScriptPath)) { + Write-Error "Error: Upgrade-WingetMsStore.ps1 not found at $ScriptPath" + exit 1 +} + +Write-Output "Configuring scheduled task: $TaskName" +Write-Output "Target script: $ScriptPath" + +# Define Action +$Action = New-ScheduledTaskAction -Execute "powershell.exe" -Argument "-NoProfile -WindowStyle Hidden -ExecutionPolicy Bypass -File `"$ScriptPath`"" + +# Define Trigger (Daily at 2:00 AM) +$Trigger = New-ScheduledTaskTrigger -Daily -At "2:00 AM" + +# Define Settings: +# - Allow start on batteries: Yes +# - Don't stop if going on batteries: Yes +# - Start when available: Yes (runs as soon as possible if a scheduled start is missed) +# - Execution time limit: 2 hours +$Settings = New-ScheduledTaskSettingsSet -AllowStartIfOnBatteries -DontStopIfGoingOnBatteries -StartWhenAvailable -ExecutionTimeLimit (New-TimeSpan -Hours 2) + +# Define Principal: +# Run as the active user (jasonross) with Highest privileges since winget is user-context tied. +# LogonType is set to Interactive to ensure the user profile and environment variables are loaded. +$Principal = New-ScheduledTaskPrincipal -UserId "jasonross" -LogonType Interactive -RunLevel Highest + +# Register Scheduled Task (Overwrites if it already exists) +try { + # If task exists, unregister it first to avoid conflicts + if (Get-ScheduledTask -TaskName $TaskName -ErrorAction SilentlyContinue) { + Write-Output "Existing task found. Re-registering..." + Unregister-ScheduledTask -TaskName $TaskName -Confirm:$false + } + + $Task = Register-ScheduledTask -TaskName $TaskName -Description $TaskDescription -Action $Action -Trigger $Trigger -Settings $Settings -Principal $Principal + Write-Output "Successfully registered scheduled task '$TaskName'." + Write-Output "Task details:" + Write-Output " State: $($Task.State)" + Write-Output " Trigger: Daily at 2:00 AM" + Write-Output " Principal: $($Task.Principal.UserId) ($($Task.Principal.RunLevel))" +} +catch { + Write-Error "Failed to register scheduled task: $_" + exit 1 +} diff --git a/Update-Discord.ps1 b/Update-Discord.ps1 new file mode 100644 index 0000000..98e5484 --- /dev/null +++ b/Update-Discord.ps1 @@ -0,0 +1,81 @@ +# Update-Discord.ps1 +# Closes Discord if open, checks for updates, launches Discord to apply them, then closes Discord once done. + +$DiscordDir = "$env:LocalAppData\Discord" +$LogFile = Join-Path $PSScriptRoot "Update-Discord.log" + +function Log-Message { + param([string]$Message) + $Timestamp = Get-Date -Format "yyyy-MM-dd HH:mm:ss" + $LogLine = "[$Timestamp] $Message" + Write-Output $LogLine + Add-Content -Path $LogFile -Value $LogLine -ErrorAction SilentlyContinue +} + +Log-Message "Starting Discord daily update task..." + +# Ensure we are in the correct working directory +if (Test-Path $DiscordDir) { + Set-Location -Path $DiscordDir + Log-Message "Working directory set to: $DiscordDir" +} else { + Log-Message "Error: Discord directory not found at $DiscordDir. Exiting." + Exit 1 +} + +# 1. Close Discord if open +$DiscordProcesses = Get-Process -Name "Discord" -ErrorAction SilentlyContinue +if ($DiscordProcesses) { + Log-Message "Closing active Discord processes..." + $DiscordProcesses | Stop-Process -Force + Start-Sleep -Seconds 5 +} else { + Log-Message "Discord is not running." +} + +# 2. Run Update.exe --update +if (Test-Path "Update.exe") { + Log-Message "Running Update.exe --update..." + $UpdateProcess = Start-Process -FilePath "Update.exe" -ArgumentList "--update=https://discord.com/api/updates/stable?platform=win" -Wait -PassThru -NoNewWindow + Log-Message "Update.exe --update completed with exit code: $($UpdateProcess.ExitCode)" +} else { + Log-Message "Error: Update.exe not found. Exiting." + Exit 1 +} + +# 3. Run Update.exe --processStart Discord.exe +Log-Message "Running Update.exe --processStart Discord.exe..." +$LaunchProcess = Start-Process -FilePath "Update.exe" -ArgumentList "--processStart Discord.exe" -PassThru -NoNewWindow +Log-Message "Discord launch triggered." + +# 4. Wait for Discord process to start +Log-Message "Waiting for Discord process to start..." +$Started = $false +for ($i = 1; $i -le 30; $i++) { + if (Get-Process -Name "Discord" -ErrorAction SilentlyContinue) { + $Started = $true + Log-Message "Discord process detected after $i seconds." + break + } + Start-Sleep -Seconds 1 +} + +if ($Started) { + # Give Discord time to complete its checking and update process (installing updates, updating files, database migration) + Log-Message "Waiting 60 seconds for Discord update process to complete..." + Start-Sleep -Seconds 60 + + # 5. Immediately close Discord once the update process is complete + Log-Message "Closing Discord..." + $CloseProcesses = Get-Process -Name "Discord" -ErrorAction SilentlyContinue + if ($CloseProcesses) { + $CloseProcesses | Stop-Process -Force + Log-Message "Discord successfully closed." + } else { + Log-Message "Discord was already closed." + } +} else { + Log-Message "Error: Discord process did not start within 30 seconds." +} + +Log-Message "Discord update task completed." diff --git a/Upgrade-Choco.ps1 b/Upgrade-Choco.ps1 new file mode 100644 index 0000000..660f113 --- /dev/null +++ b/Upgrade-Choco.ps1 @@ -0,0 +1,37 @@ +# Upgrade-Choco.ps1 +# Runs Chocolatey upgrade for all installed packages and logs the output. + +$LogFile = Join-Path $PSScriptRoot "Upgrade-Choco.log" + +function Log-Message { + param([string]$Message) + $Timestamp = Get-Date -Format "yyyy-MM-dd HH:mm:ss" + $LogLine = "[$Timestamp] $Message" + Write-Output $LogLine + Add-Content -Path $LogFile -Value $LogLine -ErrorAction SilentlyContinue +} + +Log-Message "==================================================" +Log-Message "Starting Chocolatey upgrade task..." +Log-Message "==================================================" + +# Check if chocolatey is available +if (Get-Command choco -ErrorAction SilentlyContinue) { + Log-Message "Chocolatey found. Executing: choco upgrade all -y" + + try { + # Run choco upgrade and append output to log file + # We redirect stdout and stderr to the log file + & choco upgrade all -y 2>&1 | Add-Content -Path $LogFile -ErrorAction SilentlyContinue + Log-Message "Chocolatey upgrade execution completed. Exit code: $LastExitCode" + } + catch { + Log-Message "An error occurred while running choco: $_" + } +} else { + Log-Message "Error: choco command not found." +} + +Log-Message "==================================================" +Log-Message "Chocolatey upgrade task finished." +Log-Message "==================================================" diff --git a/Upgrade-WingetMsStore.ps1 b/Upgrade-WingetMsStore.ps1 new file mode 100644 index 0000000..16c56e3 --- /dev/null +++ b/Upgrade-WingetMsStore.ps1 @@ -0,0 +1,36 @@ +# Upgrade-WingetMsStore.ps1 +# Runs winget upgrade for all MS Store packages daily and logs the output. + +$LogFile = Join-Path $PSScriptRoot "Upgrade-WingetMsStore.log" + +function Log-Message { + param([string]$Message) + $Timestamp = Get-Date -Format "yyyy-MM-dd HH:mm:ss" + $LogLine = "[$Timestamp] $Message" + Write-Output $LogLine + Add-Content -Path $LogFile -Value $LogLine -ErrorAction SilentlyContinue +} + +Log-Message "==================================================" +Log-Message "Starting WinGet MS Store upgrade task..." +Log-Message "==================================================" + +# Check if winget is available in the environment path +if (Get-Command winget -ErrorAction SilentlyContinue) { + Log-Message "WinGet found. Executing upgrade command..." + + try { + # Execute winget upgrade and append all output streams (stdout, stderr) to the log file + & winget upgrade --all --source msstore --accept-package-agreements --accept-source-agreements 2>&1 | Add-Content -Path $LogFile -ErrorAction SilentlyContinue + Log-Message "WinGet upgrade completed. Exit code: $LastExitCode" + } + catch { + Log-Message "An error occurred while executing winget: $_" + } +} else { + Log-Message "Error: winget command not found in the current environment path." +} + +Log-Message "==================================================" +Log-Message "WinGet MS Store upgrade task finished." +Log-Message "=================================================="