From 58dc903f150d0acf28a80e05efb5e5401ebbe81a Mon Sep 17 00:00:00 2001 From: Mark Cornmesser Date: Fri, 5 Dec 2025 15:34:22 -0800 Subject: [PATCH 001/105] self deploy chack/ gw check improvements --- .../manifests/profiles/scheduled_tasks.pp | 3 +- .../files/gw_exe_check.ps1 | 113 ++--- .../files/maintainsystem-hw.ps1 | 423 +++++++----------- .../files/self_redeploy_check.ps1 | 281 ++++++++++++ .../manifests/gw_exe_check.pp | 35 +- .../manifests/self_redeploy_check.pp | 27 ++ 6 files changed, 553 insertions(+), 329 deletions(-) create mode 100644 modules/win_scheduled_tasks/files/self_redeploy_check.ps1 create mode 100644 modules/win_scheduled_tasks/manifests/self_redeploy_check.pp diff --git a/modules/roles_profiles/manifests/profiles/scheduled_tasks.pp b/modules/roles_profiles/manifests/profiles/scheduled_tasks.pp index 7fcb53c8e..78440346d 100644 --- a/modules/roles_profiles/manifests/profiles/scheduled_tasks.pp +++ b/modules/roles_profiles/manifests/profiles/scheduled_tasks.pp @@ -11,8 +11,7 @@ $startup_script = 'azure-maintainsystem.ps1' } 'datacenter': { - #$startup_script = 'maintainsystem-hw.ps1' - $startup_script = 'maintainsystem-reftester.ps1' + $startup_script = 'maintainsystem-hw.ps1' } default: { $startup_script = 'maintainsystem.ps1' diff --git a/modules/win_scheduled_tasks/files/gw_exe_check.ps1 b/modules/win_scheduled_tasks/files/gw_exe_check.ps1 index 6f3b97cb4..9816e0a8a 100644 --- a/modules/win_scheduled_tasks/files/gw_exe_check.ps1 +++ b/modules/win_scheduled_tasks/files/gw_exe_check.ps1 @@ -29,9 +29,7 @@ function Set-PXE { process { $temp_dir = "$env:SystemDrive\temp\" New-Item -ItemType Directory -Force -Path $temp_dir -ErrorAction SilentlyContinue - bcdedit /enum firmware > "$temp_dir\firmware.txt" - $fwbootmgr = Select-String -Path "$temp_dir\firmware.txt" -Pattern "{fwbootmgr}" if (!$fwbootmgr) { Write-Log -message ('{0} :: Device is configured for Legacy Boot. Exiting!' -f $($MyInvocation.MyCommand.Name)) -severity 'DEBUG' @@ -41,7 +39,6 @@ function Set-PXE { $FullLine = ((Get-Content "$temp_dir\firmware.txt" | Select-String "IPV4|EFI Network" -Context 1 -ErrorAction Stop).Context.PreContext)[0] $GUID = '{' + $FullLine.Split('{')[1] bcdedit /set "{fwbootmgr}" bootsequence "$GUID" - Write-Log -message ('{0} :: Device will PXE boot. Restarting' -f $($MyInvocation.MyCommand.Name)) -severity 'DEBUG' Restart-Computer -Force Exit @@ -56,62 +53,72 @@ function Set-PXE { } } -# Main monitoring script - -# Initial sleep for 10 minutes -Write-Log -message "Sleeping 10 minutes before starting GW monitoring..." -severity 'DEBUG' -Start-Sleep -Seconds (10 * 60) - -$regPath = "HKLM:\SOFTWARE\Mozilla\Ronin" -$regName = "GW_failed" - -while ($true) { - Write-Log -message "Checking for 'generic-worker' process..." -severity 'DEBUG' - - $process = Get-Process -Name "generic-worker" -ErrorAction SilentlyContinue +function Register-FailureAndMaybePXE { + param ( + [string] $regName + ) - if (-not $process) { - Write-Log -message "Generic Worker process not found." -severity 'WARN' + $regPath = "HKLM:\SOFTWARE\Mozilla\Ronin\GW_check_failures" + if (!(Test-Path $regPath)) { + New-Item -Path $regPath -Force | Out-Null + } + $currentValue = 0 + try { + $currentValue = (Get-ItemProperty -Path $regPath -Name $regName -ErrorAction Stop).$regName + } catch { + $currentValue = 0 + } + if ($currentValue -eq 1) { + Write-Log -message "$regName failure occurred again. Initiating PXE boot." -severity 'ERROR' + Set-PXE + exit + } else { + Write-Log -message "$regName failure detected. Rebooting system (1st failure)." -severity 'ERROR' + Set-ItemProperty -Path $regPath -Name $regName -Value 1 -Force + Restart-Computer -Force + Exit + } +} - if (!(Test-Path $regPath)) { - New-Item -Path $regPath -Force | Out-Null - } +$bootstrap_stage = (Get-ItemProperty -path "HKLM:\SOFTWARE\Mozilla\ronin_puppet").bootstrap_stage +If ($bootstrap_stage -ne 'complete') { + Write-Log -message ('{0} :: Bootstrap has not completed. EXITING!' -f $($MyInvocation.MyCommand.Name)) -severity 'DEBUG' + Exit +} - $currentValue = $null - Try { - $currentValue = (Get-ItemProperty -Path $regPath -Name $regName -ErrorAction Stop).$regName - } Catch { - # If the property does not exist, we'll treat it as first failure - $currentValue = $null - } +# Uptime check — allow 15-minute grace period before enforcing logic +$lastBoot = (Get-CimInstance -ClassName Win32_OperatingSystem).LastBootUpTime +$uptimeMinutes = (New-TimeSpan -Start $lastBoot -End (Get-Date)).TotalMinutes +if ($uptimeMinutes -lt 15) { + Write-Log -message "System has only been up for $([math]::Round($uptimeMinutes, 1)) minutes. Skipping generic-worker check until 15-minute threshold is met." -severity 'DEBUG' + exit +} - if ($currentValue -eq 1) { - Write-Log -message "Generic Worker still missing after previous failure. Initiating PXE boot..." -severity 'ERROR' - Set-PXE - # Set-PXE will reboot and exit - } else { - Write-Log -message "First failure detected. Setting GW_failed=1." -severity 'WARN' - Set-ItemProperty -Path $regPath -Name $regName -Value 1 -Force - } - } else { - Write-Log -message "Generic Worker process is running." -severity 'DEBUG' +# Check gw_initiated env var +if ($env:gw_initiated -ne 'true') { + Write-Log -message "Environment variable gw_initiated is not true." -severity 'WARN' + Register-FailureAndMaybePXE -regName 'gw_initiated_failed' +} - if (Test-Path $regPath) { - $currentValue = $null - Try { - $currentValue = (Get-ItemProperty -Path $regPath -Name $regName -ErrorAction Stop).$regName - } Catch { - $currentValue = $null - } +# Check for generic-worker process +# Write-Log -message "Checking for 'generic-worker' process..." -severity 'DEBUG' +$process = Get-Process -Name "generic-worker" -ErrorAction SilentlyContinue +if (-not $process) { + Write-Log -message "generic-worker has not started." -severity 'WARN' + Register-FailureAndMaybePXE -regName 'process_failed' +} - if ($currentValue -eq 1) { - Write-Log -message "Generic Worker recovered. Removing GW_failed flag." -severity 'DEBUG' - Remove-ItemProperty -Path $regPath -Name $regName -Force +# Success path – clear failure flags +Write-Log -message "Generic-worker process is up and running." -severity 'DEBUG' +$regPath = "HKLM:\SOFTWARE\Mozilla\Ronin\GW_check_failures" +$failKeys = @('gw_initiated_failed', 'process_failed') +foreach ($key in $failKeys) { + if (Test-Path $regPath) { + try { + if ((Get-ItemProperty -Path $regPath -Name $key -ErrorAction Stop).$key -eq 1) { + Write-Log -message "Clearing $key failure flag." -severity 'DEBUG' + Remove-ItemProperty -Path $regPath -Name $key -Force } - } + } catch {} } - - # Sleep 5 minutes before next check - Write-Log -message "Sleeping 5 minutes until next check..." -severity 'DEBUG' - Start-Sleep -Seconds (5 * 60) } diff --git a/modules/win_scheduled_tasks/files/maintainsystem-hw.ps1 b/modules/win_scheduled_tasks/files/maintainsystem-hw.ps1 index db5803445..a7303f9d5 100644 --- a/modules/win_scheduled_tasks/files/maintainsystem-hw.ps1 +++ b/modules/win_scheduled_tasks/files/maintainsystem-hw.ps1 @@ -55,6 +55,168 @@ function Run-MaintainSystem { Write-Log -message ('{0} :: end - {1:o}' -f $($MyInvocation.MyCommand.Name), (Get-Date).ToUniversalTime()) -severity 'DEBUG' } } +function CompareConfigBasic { + param ( + [string]$yaml_url = "https://raw.githubusercontent.com/mozilla-platform-ops/worker-images/refs/heads/main/provisioners/windows/MDC1Windows/pools.yml", + [string]$PAT + ) + + begin { + Write-Log -message ('{0} :: begin - {1:o}' -f $($MyInvocation.MyCommand.Name), (Get-Date).ToUniversalTime()) -severity 'DEBUG' + } + + process { + $yaml = $null + $SETPXE = $false + $yamlHash = $null + $IPAddress = $null + + $Ethernet = [System.Net.NetworkInformation.NetworkInterface]::GetAllNetworkInterfaces() | + Where-Object { $_.Name -match "ethernet" } + + try { + $IPAddress = ($Ethernet.GetIPProperties().UnicastAddresses | + Where-Object { $_.Address.AddressFamily -eq [System.Net.Sockets.AddressFamily]::InterNetwork -and $_.Address.IPAddressToString -ne "127.0.0.1" } | + Select-Object -First 1 -ExpandProperty Address).IPAddressToString + } + catch { + try { + $NetshOutput = netsh interface ip show addresses + $IPAddress = ($NetshOutput -match "IP Address" | ForEach-Object { + if ($_ -notmatch "127.0.0.1") { $_ -replace ".*?:\s*", "" } + })[0] + } + catch { + Write-Log -message "Failed to get IP address" -severity 'ERROR' + } + } + + if (-not $IPAddress) { + Write-Log -message "No IP Address could be determined." -severity 'ERROR' + Restart-Computer -Force + return + } + + Write-Log -message "IP Address: $IPAddress" -severity 'INFO' + + try { + $ResolvedName = (Resolve-DnsName -Name $IPAddress -Server "10.48.75.120").NameHost + } + catch { + Write-Log -message "DNS resolution failed." -severity 'ERROR' + Restart-Computer -Force + return + } + + Write-Log -message "Resolved Name: $ResolvedName" -severity 'INFO' + + $index = $ResolvedName.IndexOf('.') + if ($index -lt 0) { + Write-Log -message "Invalid hostname format." -severity 'ERROR' + Restart-Computer -Force + return + } + + $worker_node_name = $ResolvedName.Substring(0, $index) + Write-Log -message "Host name set to: $worker_node_name" -severity 'INFO' + + $localHash = (Get-ItemProperty -Path HKLM:\SOFTWARE\Mozilla\ronin_puppet).GITHASH + $localPool = (Get-ItemProperty -Path HKLM:\SOFTWARE\Mozilla\ronin_puppet).worker_pool_id + + $maxRetries = 5 + $retryDelay = 10 + $attempt = 0 + $success = $false + + while ($attempt -lt $maxRetries -and -not $success) { + try { + $Headers = @{ + Accept = "application/vnd.github+json" + Authorization = "Bearer $($PAT)" + "X-GitHub-Api-Version" = "2022-11-28" + } + $response = Invoke-WebRequest -Uri $yaml_url -UseBasicParsing -TimeoutSec 10 -ErrorAction Stop -Headers $Headers + $yaml = $response.Content | ConvertFrom-Yaml + + if ($yaml) { + $success = $true + } + else { + throw "YAML content empty" + } + } + catch { + Write-Log -message "Attempt $($attempt + 1): Failed to fetch YAML - $_" -severity 'WARN' + Start-Sleep -Seconds $retryDelay + $attempt++ + } + } + + if (-not $success) { + Write-Log -message "YAML could not be loaded. Forcing PXE + reboot." -severity 'ERROR' + Set-PXE + Restart-Computer -Force + return + } + + $found = $false + foreach ($pool in $yaml.pools) { + if ($pool.nodes -contains $worker_node_name) { + $WorkerPool = $pool.name + $yamlHash = $pool.hash + $yamlImageName = $pool.image + $yamlImageDir = "D:\" + $yamlImageName + $found = $true + break + } + } + + if (-not $found) { + Write-Log -message "Node not found in YAML. Forcing PXE + reboot." -severity 'ERROR' + Set-PXE + Restart-Computer -Force + return + } + + Write-Log -message "=== Configuration Comparison ===" -severity 'INFO' + + if ($localPool -ne $WorkerPool) { + Write-Log -message "Worker Pool MISMATCH!" -severity 'ERROR' + $SETPXE = $true + } + else { + Write-Log -message "Worker Pool Match: $WorkerPool" -severity 'INFO' + } + + if ([string]::IsNullOrWhiteSpace($yamlHash) -or $localHash -ne $yamlHash) { + Write-Log -message "Git Hash MISMATCH or missing YAML hash!" -severity 'ERROR' + Write-Log -message "Local: $localHash" -severity 'WARN' + Write-Log -message "YAML : $yamlHash" -severity 'WARN' + $SETPXE = $true + } + else { + Write-Log -message "Git Hash Match: $yamlHash" -severity 'INFO' + } + + if (!(Test-Path $yamlImageDir)) { + Write-Log -message "Image directory missing: $yamlImageDir" -severity 'ERROR' + $SETPXE = $true + } + + if ($SETPXE) { + Write-Log -message "Configuration mismatch — initiating PXE + reboot." -severity 'ERROR' + Set-PXE + Restart-Computer -Force + return + } + + Write-Log -message "Configuration is correct. No reboot required." -severity 'INFO' + } + + end { + Write-Log -message ('{0} :: end - {1:o}' -f $($MyInvocation.MyCommand.Name), (Get-Date).ToUniversalTime()) -severity 'DEBUG' + } +} function Remove-OldTaskDirectories { param ( [string[]] $targets = @('Z:\task_*', 'C:\Users\task_*') @@ -161,7 +323,7 @@ function Puppet-Run { [string] $lock = "$env:programdata\PuppetLabs\ronin\semaphore\ronin_run.lock", [int] $last_exit = (Get-ItemProperty "HKLM:\SOFTWARE\Mozilla\ronin_puppet").last_run_exit, [string] $run_to_success = (Get-ItemProperty "HKLM:\SOFTWARE\Mozilla\ronin_puppet").runtosuccess, - [string] $nodes_def = "$env:systemdrive\ronin\manifests\nodes\nodes.pp", + [string] $nodes_def = "$env:systemdrive\ronin\manifests\nodes\odes.pp", [string] $logdir = "$env:systemdrive\logs", [string] $fail_dir = "$env:systemdrive\fail_logs", [string] $log_file = "$datetime-puppetrun.log", @@ -282,245 +444,6 @@ function StartWorkerRunner { } } -function CompareConfig { - param ( - [string]$yaml_url = "https://raw.githubusercontent.com/mozilla-platform-ops/worker-images/refs/heads/main/provisioners/windows/MDC1Windows/pools.yml", - [string]$PAT - ) - - begin { - Write-Log -message ('{0} :: begin - {1:o}' -f $($MyInvocation.MyCommand.Name), (Get-Date).ToUniversalTime()) -severity 'DEBUG' - } - - process { - - $yaml = $null - - $SETPXE = $false - - $IPAddress = $null - $Ethernet = [System.Net.NetworkInformation.NetworkInterface]::GetAllNetworkInterfaces() | Where-Object { $_.Name -match "ethernet" } - - try { - $IPAddress = ($Ethernet.GetIPProperties().UnicastAddresses | - Where-Object { $_.Address.AddressFamily -eq [System.Net.Sockets.AddressFamily]::InterNetwork -and $_.Address.IPAddressToString -ne "127.0.0.1" } | - Select-Object -First 1 -ExpandProperty Address).IPAddressToString - - if (-not $IPAddress) { - throw "No IP address found using .NET method." - } - } - catch { - try { - $NetshOutput = netsh interface ip show addresses - $IPAddress = ($NetshOutput -match "IP Address" | ForEach-Object { - if ($_ -notmatch "127.0.0.1") { - $_ -replace ".*?:\s*", "" - } - })[0] - } - catch { - Write-Log -message "Failed to get IP address" -severity 'ERROR' - } - } - - if ($IPAddress) { - Write-Log -message "IP Address: $IPAddress" -severity 'INFO' - } - else { - Write-Log -message "No IP Address could be determined." -severity 'ERROR' - return - } - - try { - $ResolvedName = (Resolve-DnsName -Name $IPAddress -Server "10.48.75.120").NameHost - } - catch { - Write-Log -message "DNS resolution failed." -severity 'ERROR' - return - } - - Write-Log -message "Resolved Name: $ResolvedName" -severity 'INFO' - - $index = $ResolvedName.IndexOf('.') - if ($index -lt 0) { - Write-Log -message "Invalid hostname format." -severity 'ERROR' - return - } - - $worker_node_name = $ResolvedName.Substring(0, $index) - $domain_suffix = $ResolvedName.Substring($index + 1) - - Write-Log -message "Host name set to: $worker_node_name" -severity 'INFO' - - $localHash = (Get-ItemProperty -Path HKLM:\SOFTWARE\Mozilla\ronin_puppet).GITHASH - $localPool = (Get-ItemProperty -Path HKLM:\SOFTWARE\Mozilla\ronin_puppet).worker_pool_id - - $maxRetries = 5 - $retryDelay = 10 - $attempt = 0 - $success = $false - - while ($attempt -lt $maxRetries -and -not $success) { - try { - $Headers = @{ - Accept = "application/vnd.github+json" - Authorization = "Bearer $($PAT)" - "X-GitHub-Api-Version" = "2022-11-28" - } - $response = Invoke-WebRequest -Uri $yaml_url -UseBasicParsing -TimeoutSec 10 -ErrorAction Stop -Headers $Headers - $yaml = $response.Content | ConvertFrom-Yaml - if ($yaml) { - $success = $true - } - else { - throw "YAML content is empty" - Write-Log -message "YAML content is empty" -severity 'WARN' - } - } - catch { - Write-Log -message "Attempt $($attempt + 1): Failed to fetch YAML - $_" -severity 'WARN' - Start-Sleep -Seconds $retryDelay - $attempt++ - } - } - - if (-not $success) { - Write-Log -message "YAML could not be loaded after $maxRetries attempts." -severity 'ERROR' - return - } - - $found = $false - foreach ($pool in $yaml.pools) { - foreach ($node in $pool.nodes) { - if ($node -eq $worker_node_name) { - $WorkerPool = $pool.name - $yamlHash = $pool.hash - $yamlImageName = $pool.image - $yamlImageDir = "D:\" + $yamlImageName - $found = $true - break - } - } - if ($found) { break } - } - - if (-not $found) { - Write-Log -message "Node name not found in YAML!!" -severity 'ERROR' - exit 96 - } - - Write-Log -message "=== Configuration Comparison ===" -severity 'INFO' - - if ($localPool -eq $WorkerPool) { - Write-Log -message "Worker Pool Match: $WorkerPool" -severity 'INFO' - } - else { - Write-Log -message "Worker Pool MISMATCH!" -severity 'ERROR' - $SETPXE = $true - Start-Sleep -s 1 - } - - if ($localHash -eq $yamlHash) { - Write-Log -message "Git Hash Match: $yamlHash" -severity 'INFO' - } - else { - Write-Log -message "Git Hash MISMATCH!" -severity 'ERROR' - Write-Log -message "Local: $localHash" -severity 'WARN' - Write-Log -message "YAML : $yamlHash" -severity 'WARN' - $SETPXE = $true - Start-Sleep -s 1 - } - - - if (!(Test-Path $yamlImageDir)) { - Write-Log -message "Image Directory MISMATCH!" -severity 'ERROR' - Write-Log -message "YAML : $yamlImageDir NOT FOUND" -severity 'WARN' - $SETPXE = $true - Start-Sleep -s 1 - } - if ($SETPXE) { - Write-Log -message "Configuration MISMATCH! Initiating self re-deploy!" -severity 'ERROR' - Set-PXE - } - Write-Log -message "SETPXE set to: $SETPXE" -severity 'DEBUG' - } - - - end { - Write-Log -message ('{0} :: end - {1:o}' -f $($MyInvocation.MyCommand.Name), (Get-Date).ToUniversalTime()) -severity 'DEBUG' - } -} - - -function StartGenericWorker { - param ( - [string] $GW_dir = "$env:systemdrive\generic-worker" - ) - begin { - Write-Log -message ('{0} :: begin - {1:o}' -f $($MyInvocation.MyCommand.Name), (Get-Date).ToUniversalTime()) -severity 'DEBUG' - } - process { - # Check for user profile issues - $lastBootTime = Get-WinEvent -LogName "System" -FilterXPath "" | - Select-Object -First 1 | - ForEach-Object { $_.TimeCreated } - - $eventIDs = @(1511, 1515) - $events = Get-WinEvent -LogName "Application" | - Where-Object { $_.ID -in $eventIDs -and $_.TimeCreated -gt $lastBootTime } | - Sort-Object TimeCreated -Descending | Select-Object -First 1 - - if ($events) { - Write-Log -message ('{0} :: Possible User Profile Corruption. Restarting' -f $($MyInvocation.MyCommand.Name)) -severity 'DEBUG' - Start-Sleep -Seconds 5 - Restart-Computer -Force - exit - } - - Set-Location -Path $GW_dir - - & $GW_dir\generic-worker.exe run --config generic-worker.config 2>&1 | Out-File -FilePath generic-worker.log -Encoding utf8 - $exitCode = $LASTEXITCODE - - Write-Log -message ('{0} :: GW exited with code {1}' -f $($MyInvocation.MyCommand.Name), $exitCode) -severity 'DEBUG' - - switch ($exitCode) { - 68 { - - Write-Log -message ('{0} :: Idle timeout detected (exit code 68). Checking for latest Config.' -f $($MyInvocation.MyCommand.Name)) -severity 'DEBUG' - CompareConfig -PAT (Get-Content "D:\Secrets\pat.txt") - - Write-Log -message ('{0} :: Copying current-task-user.json to next-task-user.json' -f $($MyInvocation.MyCommand.Name)) -severity 'DEBUG' - $src = Join-Path $GW_dir 'current-task-user.json' - $dest = Join-Path $GW_dir 'next-task-user.json' - if (Test-Path $src) { - Copy-Item -Path $src -Destination $dest -Force - Write-Log -message ('{0} :: File copied successfully' -f $($MyInvocation.MyCommand.Name)) -severity 'DEBUG' - } - else { - Write-Log -message ('{0} :: Source file not found: {1}' -f $($MyInvocation.MyCommand.Name), $src) -severity 'WARNING' - } - - ## Restart Explorer/close out exisiting windows - Stop-Process -Name explorer -Force - - Start-Sleep -s 2 - StartGenericWorker - return - } - default { - Write-Log -message ('{0} :: Non-idle exit code {1}. Rebooting' -f $($MyInvocation.MyCommand.Name), $exitCode) -severity 'DEBUG' - Start-Sleep -Seconds 1 - Restart-Computer -Force - } - } - } - end { - Write-Log -message ('{0} :: end - {1:o}' -f $($MyInvocation.MyCommand.Name), (Get-Date).ToUniversalTime()) -severity 'DEBUG' - } -} - function Get-LoggedInUser { [CmdletBinding()] param ( @@ -606,7 +529,6 @@ function Set-PXE { Write-Log -message ('{0} :: Device will PXE boot. Restarting' -f $($MyInvocation.MyCommand.Name)) -severity 'DEBUG' Restart-Computer -Force - Exit } Catch { Write-Log -message ('{0} :: Unable to set next boot to PXE. Exiting!' -f $($MyInvocation.MyCommand.Name)) -severity 'DEBUG' @@ -656,16 +578,8 @@ if ($refresh_rate -ne "60") { $bootstrap_stage = (Get-ItemProperty -path "HKLM:\SOFTWARE\Mozilla\ronin_puppet").bootstrap_stage If ($bootstrap_stage -eq 'complete') { - - $tasks = Get-ScheduledTask | Where-Object { $_.TaskName -eq "bootstrap" } - - if ($tasks) { - $tasks | ForEach-Object { - Stop-ScheduledTask -TaskName $task.TaskName -TaskPath $task.TaskPath - Unregister-ScheduledTask -TaskName $_.TaskName -TaskPath $_.TaskPath -Confirm:$false - Write-Host "Deleted task '$($_.TaskName)' at path '$($_.TaskPath)'." - } - } + CompareConfigBasic + Start-Sleep -Seconds 2 Run-MaintainSystem ## We're getting user profile corruption errors, so let's check that the user is logged in using quser.exe for ($i = 0; $i -lt 3; $i++) { @@ -687,12 +601,7 @@ If ($bootstrap_stage -eq 'complete') { ## Instead of querying chocolatey each time this runs, let's query chrome json endoint and check locally installed version Get-LatestGoogleChrome - $processname = "StartMenuExperienceHost" - if ($null -ne $process) { - Stop-Process -Name $processname -force - } - CompareConfig -PAT (Get-Content "D:\Secrets\pat.txt") - StartGenericWorker + StartWorkerRunner } else { Write-Log -message ('{0} :: Bootstrap has not completed. EXITING!' -f $($MyInvocation.MyCommand.Name)) -severity 'DEBUG' diff --git a/modules/win_scheduled_tasks/files/self_redeploy_check.ps1 b/modules/win_scheduled_tasks/files/self_redeploy_check.ps1 new file mode 100644 index 000000000..66407c37d --- /dev/null +++ b/modules/win_scheduled_tasks/files/self_redeploy_check.ps1 @@ -0,0 +1,281 @@ +<# +This Source Code Form is subject to the terms of the Mozilla Public +License, v. 2.0. If a copy of the MPL was not distributed with this +file, You can obtain one at http://mozilla.org/MPL/2.0/. +#> + +function Write-Log { + param ( + [string] $message, + [string] $severity = 'INFO', + [string] $source = 'MaintainSystem', + [string] $logName = 'Application' + ) + if (!([Diagnostics.EventLog]::Exists($logName)) -or !([Diagnostics.EventLog]::SourceExists($source))) { + New-EventLog -LogName $logName -Source $source + } + switch ($severity) { + 'DEBUG' { + $entryType = 'SuccessAudit' + $eventId = 2 + break + } + 'WARN' { + $entryType = 'Warning' + $eventId = 3 + break + } + 'ERROR' { + $entryType = 'Error' + $eventId = 4 + break + } + default { + $entryType = 'Information' + $eventId = 1 + break + } + } + Write-EventLog -LogName $logName -Source $source -EntryType $entryType -Category 0 -EventID $eventId -Message $message + if ([Environment]::UserInteractive) { + $fc = @{ 'Information' = 'White'; 'Error' = 'Red'; 'Warning' = 'DarkYellow'; 'SuccessAudit' = 'DarkGray' }[$entryType] + Write-Host -object $message -ForegroundColor $fc + } +} +function CompareConfig { + param ( + [string]$yaml_url = "https://raw.githubusercontent.com/mozilla-platform-ops/worker-images/refs/heads/main/provisioners/windows/MDC1Windows/pools.yml", + [string]$PAT + ) + + begin { + Write-Log -message ('{0} :: begin - {1:o}' -f $($MyInvocation.MyCommand.Name), (Get-Date).ToUniversalTime()) -severity 'DEBUG' + } + + process { + $yaml = $null + $SETPXE = $false + $yamlHash = $null + $IPAddress = $null + + # ------------------------------- + # Resolve IP + # ------------------------------- + $Ethernet = [System.Net.NetworkInformation.NetworkInterface]::GetAllNetworkInterfaces() | + Where-Object { $_.Name -match "ethernet" } + + try { + $IPAddress = ($Ethernet.GetIPProperties().UnicastAddresses | + Where-Object { $_.Address.AddressFamily -eq [System.Net.Sockets.AddressFamily]::InterNetwork -and $_.Address.IPAddressToString -ne "127.0.0.1" } | + Select-Object -First 1 -ExpandProperty Address).IPAddressToString + } + catch { + try { + $NetshOutput = netsh interface ip show addresses + $IPAddress = ($NetshOutput -match "IP Address" | ForEach-Object { + if ($_ -notmatch "127.0.0.1") { $_ -replace ".*?:\s*", "" } + })[0] + } + catch { + Write-Log -message "Failed to get IP address" -severity 'ERROR' + } + } + + if ($IPAddress) { + Write-Log -message "IP Address: $IPAddress" -severity 'INFO' + } + else { + Write-Log -message "No IP Address could be determined." -severity 'ERROR' + return + } + + # ------------------------------- + # Reverse DNS + # ------------------------------- + try { + $ResolvedName = (Resolve-DnsName -Name $IPAddress -Server "10.48.75.120").NameHost + } + catch { + Write-Log -message "DNS resolution failed." -severity 'ERROR' + return + } + + Write-Log -message "Resolved Name: $ResolvedName" -severity 'INFO' + + $index = $ResolvedName.IndexOf('.') + if ($index -lt 0) { + Write-Log -message "Invalid hostname format." -severity 'ERROR' + return + } + + $worker_node_name = $ResolvedName.Substring(0, $index) + Write-Log -message "Host name set to: $worker_node_name" -severity 'INFO' + + # ------------------------------- + # Registry Values + # ------------------------------- + $localHash = (Get-ItemProperty -Path HKLM:\SOFTWARE\Mozilla\ronin_puppet).GITHASH + $localPool = (Get-ItemProperty -Path HKLM:\SOFTWARE\Mozilla\ronin_puppet).worker_pool_id + + # ------------------------------- + # Load YAML with retry + # ------------------------------- + $maxRetries = 5 + $retryDelay = 10 + $attempt = 0 + $success = $false + + while ($attempt -lt $maxRetries -and -not $success) { + try { + $Headers = @{ + Accept = "application/vnd.github+json" + Authorization = "Bearer $($PAT)" + "X-GitHub-Api-Version" = "2022-11-28" + } + $response = Invoke-WebRequest -Uri $yaml_url -UseBasicParsing -TimeoutSec 10 -ErrorAction Stop -Headers $Headers + $yaml = $response.Content | ConvertFrom-Yaml + + if ($yaml) { + $success = $true + } + else { + throw "YAML content is empty" + } + } + catch { + Write-Log -message "Attempt $($attempt + 1): Failed to fetch YAML - $_" -severity 'WARN' + Start-Sleep -Seconds $retryDelay + $attempt++ + } + } + + if (-not $success) { + Write-Log -message "YAML could not be loaded after $maxRetries attempts." -severity 'ERROR' + $SETPXE = $true + } + + # ------------------------------- + # Find pool entry + # ------------------------------- + $found = $false + if ($yaml) { + foreach ($pool in $yaml.pools) { + foreach ($node in $pool.nodes) { + if ($node -eq $worker_node_name) { + $WorkerPool = $pool.name + $yamlHash = $pool.hash + $yamlImageName = $pool.image + $yamlImageDir = "D:\" + $yamlImageName + $found = $true + break + } + } + if ($found) { break } + } + } + + if (-not $found) { + Write-Log -message "Node name not found in YAML!!" -severity 'ERROR' + $SETPXE = $true + } + + Write-Log -message "=== Configuration Comparison ===" -severity 'INFO' + + # ------------------------------- + # Compare Worker Pool + # ------------------------------- + if ($localPool -eq $WorkerPool) { + Write-Log -message "Worker Pool Match: $WorkerPool" -severity 'INFO' + } + else { + Write-Log -message "Worker Pool MISMATCH!" -severity 'ERROR' + $SETPXE = $true + } + + # ------------------------------- + # Compare Git Hash, including empty or null yamlHash + # ------------------------------- + if ([string]::IsNullOrWhiteSpace($yamlHash)) { + Write-Log -message "YAML hash is missing or invalid. Treating as mismatch." -severity 'ERROR' + $SETPXE = $true + } + elseif ($localHash -ne $yamlHash) { + Write-Log -message "Git Hash MISMATCH!" -severity 'ERROR' + Write-Log -message "Local: $localHash" -severity 'WARN' + Write-Log -message "YAML : $yamlHash" -severity 'WARN' + $SETPXE = $true + } + else { + Write-Log -message "Git Hash Match: $yamlHash" -severity 'INFO' + } + + # ------------------------------- + # Check Image Directory + # ------------------------------- + if (!(Test-Path $yamlImageDir)) { + Write-Log -message "Image Directory MISMATCH! YAML: $yamlImageDir NOT FOUND" -severity 'ERROR' + $SETPXE = $true + } + + # ==================================================================================== + # NEW LOGIC: Evaluate worker-status.json BEFORE reboot or PXE trigger + # ==================================================================================== + if ($SETPXE) { + Write-Log -message "Configuration mismatch detected. Evaluating worker-status.json..." -severity 'WARN' + + $searchPaths = @( + "C:\WINDOWS\SystemTemp", + $env:TMP, + $env:TEMP, + $env:USERPROFILE + ) + + $workerStatus = $null + foreach ($path in $searchPaths) { + if ($null -ne $path) { + $candidate = Join-Path $path "worker-status.json" + if (Test-Path $candidate) { + $workerStatus = $candidate + break + } + } + } + + if (-not $workerStatus) { + Write-Log -message "worker-status.json not found. Rebooting now!" -severity 'ERROR' + Restart-Computer -Force + return + } + + # ------------------------------- + # Parse worker-status.json + # ------------------------------- + try { + $json = Get-Content $workerStatus -Raw | ConvertFrom-Json + } + catch { + Write-Log -message "worker-status.json is unreadable. Rebooting now!" -severity 'ERROR' + Restart-Computer -Force + return + } + + if (($json.currentTaskIds).Count -eq 0) { + Write-Log -message "No active tasks. Rebooting now!" -severity 'WARN' + Restart-Computer -Force + return + } + else { + $task = $json.currentTaskIds[0] + Write-Log -message "Task $task is active. Reboot will occur on next boot." -severity 'INFO' + Set-PXE + return + } + } + + Write-Log -message "SETPXE set to: $SETPXE" -severity 'DEBUG' + } + + end { + Write-Log -message ('{0} :: end - {1:o}' -f $($MyInvocation.MyCommand.Name), (Get-Date).ToUniversalTime()) -severity 'DEBUG' + } +} diff --git a/modules/win_scheduled_tasks/manifests/gw_exe_check.pp b/modules/win_scheduled_tasks/manifests/gw_exe_check.pp index 833ba77a4..438a7d9fc 100644 --- a/modules/win_scheduled_tasks/manifests/gw_exe_check.pp +++ b/modules/win_scheduled_tasks/manifests/gw_exe_check.pp @@ -5,22 +5,23 @@ class win_scheduled_tasks::gw_exe_check ( ) { - $gw_exe_check_ps1 = "${facts['custom_win_roninprogramdata']}\\gw_exe_check.ps1" + $gw_exe_check_ps1 = "${facts['custom_win_roninprogramdata']}\\gw_exe_check.ps1" - file { $gw_exe_check_ps1: - content => file('win_scheduled_tasks/gw_exe_check.ps1'), - } - # Resource from puppetlabs-scheduled_task - scheduled_task { 'gw_exe_check': - ensure => 'present', - command => "${facts['custom_win_system32']}\\WindowsPowerShell\\v1.0\\powershell.exe", - arguments => "-executionpolicy bypass -File ${gw_exe_check_ps1}", - enabled => true, - trigger => [{ - 'schedule' => 'boot', - 'minutes_interval' => '0', - 'minutes_duration' => '0' - }], - user => 'system', - } + file { $gw_exe_check_ps1: + content => file('win_scheduled_tasks/gw_exe_check.ps1'), + } + + scheduled_task { 'gw_exe_check': + ensure => 'present', + command => "${facts['custom_win_system32']}\\WindowsPowerShell\\v1.0\\powershell.exe", + arguments => "-executionpolicy bypass -File ${gw_exe_check_ps1}", + enabled => true, + trigger => [{ + schedule => 'daily', + start_time => '00:00', + minutes_interval => 5, + minutes_duration => 1440, # 24 hours = repeat every 5 minutes all day + }], + user => 'SYSTEM', + } } diff --git a/modules/win_scheduled_tasks/manifests/self_redeploy_check.pp b/modules/win_scheduled_tasks/manifests/self_redeploy_check.pp new file mode 100644 index 000000000..ac5f5f4f7 --- /dev/null +++ b/modules/win_scheduled_tasks/manifests/self_redeploy_check.pp @@ -0,0 +1,27 @@ +# This Source Code Form is subject to the terms of the Mozilla Public +# License, v. 2.0. If a copy of the MPL was not distributed with this +# file, You can obtain one at http://mozilla.org/MPL/2.0/. + +class win_scheduled_tasks::self_redeploy_check ( +) { + + $gw_exe_check_ps1 = "${facts['custom_win_roninprogramdata']}\\self_redeploy_check.ps1" + + file { $gw_exe_check_ps1: + content => file('win_scheduled_tasks/self_redeploy_check.ps1'), + } + + scheduled_task { 'self_redeploy_check': + ensure => 'present', + command => "${facts['custom_win_system32']}\\WindowsPowerShell\\v1.0\\powershell.exe", + arguments => "-executionpolicy bypass -File ${gw_exe_check_ps1}", + enabled => true, + trigger => [{ + schedule => 'daily', + start_time => '00:00', + minutes_interval => 120, + minutes_duration => 1440, # 24 hours = repeat every 2 hours all day + }], + user => 'SYSTEM', + } +} From 8890ea4725ebb53b4338b2745fafee2fe0c9a6d3 Mon Sep 17 00:00:00 2001 From: Mark Cornmesser Date: Fri, 5 Dec 2025 16:37:03 -0800 Subject: [PATCH 002/105] download binaries from Az --- .../roles_profiles/manifests/profiles/windows_worker_runner.pp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/modules/roles_profiles/manifests/profiles/windows_worker_runner.pp b/modules/roles_profiles/manifests/profiles/windows_worker_runner.pp index 08ffb3f94..c018d25bf 100644 --- a/modules/roles_profiles/manifests/profiles/windows_worker_runner.pp +++ b/modules/roles_profiles/manifests/profiles/windows_worker_runner.pp @@ -11,7 +11,7 @@ case $facts['custom_win_location'] { 'datacenter': { - $ext_pkg_src_loc = lookup('windows.taskcluster.relops_s3') + $ext_pkg_src_loc = lookup('windows.taskcluster.relops_az') $provider = 'standalone' } default: { From 1b54509daf85a25b34f4ce921377d7b523d41b26 Mon Sep 17 00:00:00 2001 From: Mark Cornmesser Date: Sat, 6 Dec 2025 13:06:16 -0800 Subject: [PATCH 003/105] download binaries from Az --- .../roles_profiles/manifests/profiles/windows_worker_runner.pp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/modules/roles_profiles/manifests/profiles/windows_worker_runner.pp b/modules/roles_profiles/manifests/profiles/windows_worker_runner.pp index c018d25bf..f144eaafc 100644 --- a/modules/roles_profiles/manifests/profiles/windows_worker_runner.pp +++ b/modules/roles_profiles/manifests/profiles/windows_worker_runner.pp @@ -135,7 +135,7 @@ generic_worker_dir => $generic_worker_dir, desired_gw_version => $desired_gw_version, current_gw_version => $facts['custom_win_genericworker_version'], - gw_exe_source => "${ext_pkg_src_loc}${desired_gw_version}/${gw_name}", + gw_exe_source => "${ext_pkg_src_loc}/${desired_gw_version}/${gw_name}", init_file => $init, gw_exe_path => $gw_exe_path, } From 7f7f8c31e131cb90f0001fe4c1bf3f9bd216a50e Mon Sep 17 00:00:00 2001 From: Mark Cornmesser Date: Sat, 6 Dec 2025 13:51:08 -0800 Subject: [PATCH 004/105] download binaries from Az --- .../manifests/profiles/windows_worker_runner.pp | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/modules/roles_profiles/manifests/profiles/windows_worker_runner.pp b/modules/roles_profiles/manifests/profiles/windows_worker_runner.pp index f144eaafc..045b8fe1d 100644 --- a/modules/roles_profiles/manifests/profiles/windows_worker_runner.pp +++ b/modules/roles_profiles/manifests/profiles/windows_worker_runner.pp @@ -143,18 +143,18 @@ generic_worker_dir => $generic_worker_dir, desired_proxy_version => $desired_proxy_version, current_proxy_version => $facts['custom_win_taskcluster_proxy_version'], - proxy_exe_source => "${ext_pkg_src_loc}${desired_proxy_version}/${proxy_name}", + proxy_exe_source => "${ext_pkg_src_loc}/${desired_proxy_version}/${proxy_name}", } class { 'win_taskcluster::livelog': generic_worker_dir => $generic_worker_dir, - livelog_exe_source => "${ext_pkg_src_loc}${livelog_version}/${livelog_name}", + livelog_exe_source => "${ext_pkg_src_loc}/${livelog_version}/${livelog_name}", } class { 'win_taskcluster::worker_runner': # Runner EXE worker_runner_dir => $worker_runner_dir, desired_runner_version => $desired_rnr_version, current_runner_version => $facts['custom_win_runner_version'], - runner_exe_source => "${ext_pkg_src_loc}${desired_rnr_version}/${runner_name}", + runner_exe_source => "${ext_pkg_src_loc}/${desired_rnr_version}/${runner_name}", runner_exe_path => "${worker_runner_dir}\\start-worker.exe", runner_yml => "${worker_runner_dir}\\runner.yml", # Runner service install From ec1dccb009390ccaf4d97b32ea6ff40a2d39ec7e Mon Sep 17 00:00:00 2001 From: Mark Cornmesser Date: Mon, 8 Dec 2025 10:45:37 -0800 Subject: [PATCH 005/105] troubelshooting --- modules/roles_profiles/manifests/profiles/disable_services.pp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/modules/roles_profiles/manifests/profiles/disable_services.pp b/modules/roles_profiles/manifests/profiles/disable_services.pp index 5d4ce9175..29003d161 100644 --- a/modules/roles_profiles/manifests/profiles/disable_services.pp +++ b/modules/roles_profiles/manifests/profiles/disable_services.pp @@ -41,8 +41,8 @@ include win_disable_services::disable_wsearch ## Let's Uninstall Appx Packages ## Taken from https://github.com/The-Virtual-Desktop-Team/Virtual-Desktop-Optimization-Tool - ## Bug 1913499 https://bugzilla.mozilla.org/show_bug.cgi?id=1913499 - include win_disable_services::uninstall_appx_packages + ## Bug 1913499 https://bugzilla.mozilla.org/show_bug.cgi?id=1913499 + #include win_disable_services::uninstall_appx_packages if ($facts['custom_win_location'] == 'azure') { include win_scheduled_tasks::kill_local_clipboard } From 51fbbadb8fedf5d1a0f35645d594b9764ba99410 Mon Sep 17 00:00:00 2001 From: Mark Cornmesser Date: Mon, 8 Dec 2025 12:47:49 -0800 Subject: [PATCH 006/105] troubelshooting --- .../files/maintainsystem-hw.ps1 | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) diff --git a/modules/win_scheduled_tasks/files/maintainsystem-hw.ps1 b/modules/win_scheduled_tasks/files/maintainsystem-hw.ps1 index a7303f9d5..2f4d49411 100644 --- a/modules/win_scheduled_tasks/files/maintainsystem-hw.ps1 +++ b/modules/win_scheduled_tasks/files/maintainsystem-hw.ps1 @@ -341,15 +341,15 @@ function Puppet-Run { # Setting Env variabes for PuppetFile install and Puppet run # The ssl variables are needed for R10k Write-Log -message ('{0} :: Setting Puppet enviroment.' -f $($MyInvocation.MyCommand.Name)) -severity 'DEBUG' - $env:path = "$env:programfiles\Puppet Labs\Puppet\puppet\bin;$env:programfiles\Puppet Labs\Puppet\bin;$env:path" - $env:SSL_CERT_FILE = "$env:programfiles\Puppet Labs\Puppet\puppet\ssl\cert.pem" - $env:SSL_CERT_DIR = "$env:programfiles\Puppet Labs\Puppet\puppet\ssl" - $env:FACTER_env_windows_installdir = "$env:programfiles\Puppet Labs\Puppet" - $env:HOMEPATH = "\Users\Administrator" - $env:HOMEDRIVE = "C:" - $env:PL_BASEDIR = "$env:programfiles\Puppet Labs\Puppet" - $env:PUPPET_DIR = "$env:programfiles\Puppet Labs\Puppet" - $env:RUBYLIB = "$env:programfiles\Puppet Labs\Puppet\lib" + $env:path = "$($env:ProgramFiles)\Puppet Labs\Puppet\puppet\bin;$($env:ProgramFiles)\Puppet Labs\Puppet\bin;$env:path" + + $env:SSL_CERT_FILE = "$($env:ProgramFiles)\Puppet Labs\Puppet\puppet\ssl\cert.pem" + $env:SSL_CERT_DIR = "$($env:ProgramFiles)\Puppet Labs\Puppet\puppet\ssl" + $env:FACTER_env_windows_installdir = "$($env:ProgramFiles)\Puppet Labs\Puppet" + $env:PL_BASEDIR = "$($env:ProgramFiles)\Puppet Labs\Puppet" + $env:PUPPET_DIR = "$($env:ProgramFiles)\Puppet Labs\Puppet" + $env:RUBYLIB = "$($env:ProgramFiles)\Puppet Labs\Puppet\lib" + $env:USERNAME = "Administrator" $env:USERPROFILE = "$env:systemdrive\Users\Administrator" From b239d57771085baa857d24dcfe248353bf18ae73 Mon Sep 17 00:00:00 2001 From: Mark Cornmesser Date: Mon, 8 Dec 2025 14:15:49 -0800 Subject: [PATCH 007/105] troubelshooting --- .../files/BAKmaintainsystem-hw.ps1 | 609 ++++++++++++++++++ .../files/maintainsystem-hw.ps1 | 40 +- 2 files changed, 629 insertions(+), 20 deletions(-) create mode 100644 modules/win_scheduled_tasks/files/BAKmaintainsystem-hw.ps1 diff --git a/modules/win_scheduled_tasks/files/BAKmaintainsystem-hw.ps1 b/modules/win_scheduled_tasks/files/BAKmaintainsystem-hw.ps1 new file mode 100644 index 000000000..2f4d49411 --- /dev/null +++ b/modules/win_scheduled_tasks/files/BAKmaintainsystem-hw.ps1 @@ -0,0 +1,609 @@ +<# +This Source Code Form is subject to the terms of the Mozilla Public +License, v. 2.0. If a copy of the MPL was not distributed with this +file, You can obtain one at http://mozilla.org/MPL/2.0/. +#> + +function Write-Log { + param ( + [string] $message, + [string] $severity = 'INFO', + [string] $source = 'MaintainSystem', + [string] $logName = 'Application' + ) + if (!([Diagnostics.EventLog]::Exists($logName)) -or !([Diagnostics.EventLog]::SourceExists($source))) { + New-EventLog -LogName $logName -Source $source + } + switch ($severity) { + 'DEBUG' { + $entryType = 'SuccessAudit' + $eventId = 2 + break + } + 'WARN' { + $entryType = 'Warning' + $eventId = 3 + break + } + 'ERROR' { + $entryType = 'Error' + $eventId = 4 + break + } + default { + $entryType = 'Information' + $eventId = 1 + break + } + } + Write-EventLog -LogName $logName -Source $source -EntryType $entryType -Category 0 -EventID $eventId -Message $message + if ([Environment]::UserInteractive) { + $fc = @{ 'Information' = 'White'; 'Error' = 'Red'; 'Warning' = 'DarkYellow'; 'SuccessAudit' = 'DarkGray' }[$entryType] + Write-Host -object $message -ForegroundColor $fc + } +} + +function Run-MaintainSystem { + begin { + Write-Log -message ('{0} :: begin - {1:o}' -f $($MyInvocation.MyCommand.Name), (Get-Date).ToUniversalTime()) -severity 'DEBUG' + } + process { + #Remove-OldTaskDirectories + Get-ChildItem "$env:systemdrive\logs\old" -Recurse -File | Where-Object CreationTime -lt (Get-Date).AddDays(-7) | Remove-Item -Force + } + end { + Write-Log -message ('{0} :: end - {1:o}' -f $($MyInvocation.MyCommand.Name), (Get-Date).ToUniversalTime()) -severity 'DEBUG' + } +} +function CompareConfigBasic { + param ( + [string]$yaml_url = "https://raw.githubusercontent.com/mozilla-platform-ops/worker-images/refs/heads/main/provisioners/windows/MDC1Windows/pools.yml", + [string]$PAT + ) + + begin { + Write-Log -message ('{0} :: begin - {1:o}' -f $($MyInvocation.MyCommand.Name), (Get-Date).ToUniversalTime()) -severity 'DEBUG' + } + + process { + $yaml = $null + $SETPXE = $false + $yamlHash = $null + $IPAddress = $null + + $Ethernet = [System.Net.NetworkInformation.NetworkInterface]::GetAllNetworkInterfaces() | + Where-Object { $_.Name -match "ethernet" } + + try { + $IPAddress = ($Ethernet.GetIPProperties().UnicastAddresses | + Where-Object { $_.Address.AddressFamily -eq [System.Net.Sockets.AddressFamily]::InterNetwork -and $_.Address.IPAddressToString -ne "127.0.0.1" } | + Select-Object -First 1 -ExpandProperty Address).IPAddressToString + } + catch { + try { + $NetshOutput = netsh interface ip show addresses + $IPAddress = ($NetshOutput -match "IP Address" | ForEach-Object { + if ($_ -notmatch "127.0.0.1") { $_ -replace ".*?:\s*", "" } + })[0] + } + catch { + Write-Log -message "Failed to get IP address" -severity 'ERROR' + } + } + + if (-not $IPAddress) { + Write-Log -message "No IP Address could be determined." -severity 'ERROR' + Restart-Computer -Force + return + } + + Write-Log -message "IP Address: $IPAddress" -severity 'INFO' + + try { + $ResolvedName = (Resolve-DnsName -Name $IPAddress -Server "10.48.75.120").NameHost + } + catch { + Write-Log -message "DNS resolution failed." -severity 'ERROR' + Restart-Computer -Force + return + } + + Write-Log -message "Resolved Name: $ResolvedName" -severity 'INFO' + + $index = $ResolvedName.IndexOf('.') + if ($index -lt 0) { + Write-Log -message "Invalid hostname format." -severity 'ERROR' + Restart-Computer -Force + return + } + + $worker_node_name = $ResolvedName.Substring(0, $index) + Write-Log -message "Host name set to: $worker_node_name" -severity 'INFO' + + $localHash = (Get-ItemProperty -Path HKLM:\SOFTWARE\Mozilla\ronin_puppet).GITHASH + $localPool = (Get-ItemProperty -Path HKLM:\SOFTWARE\Mozilla\ronin_puppet).worker_pool_id + + $maxRetries = 5 + $retryDelay = 10 + $attempt = 0 + $success = $false + + while ($attempt -lt $maxRetries -and -not $success) { + try { + $Headers = @{ + Accept = "application/vnd.github+json" + Authorization = "Bearer $($PAT)" + "X-GitHub-Api-Version" = "2022-11-28" + } + $response = Invoke-WebRequest -Uri $yaml_url -UseBasicParsing -TimeoutSec 10 -ErrorAction Stop -Headers $Headers + $yaml = $response.Content | ConvertFrom-Yaml + + if ($yaml) { + $success = $true + } + else { + throw "YAML content empty" + } + } + catch { + Write-Log -message "Attempt $($attempt + 1): Failed to fetch YAML - $_" -severity 'WARN' + Start-Sleep -Seconds $retryDelay + $attempt++ + } + } + + if (-not $success) { + Write-Log -message "YAML could not be loaded. Forcing PXE + reboot." -severity 'ERROR' + Set-PXE + Restart-Computer -Force + return + } + + $found = $false + foreach ($pool in $yaml.pools) { + if ($pool.nodes -contains $worker_node_name) { + $WorkerPool = $pool.name + $yamlHash = $pool.hash + $yamlImageName = $pool.image + $yamlImageDir = "D:\" + $yamlImageName + $found = $true + break + } + } + + if (-not $found) { + Write-Log -message "Node not found in YAML. Forcing PXE + reboot." -severity 'ERROR' + Set-PXE + Restart-Computer -Force + return + } + + Write-Log -message "=== Configuration Comparison ===" -severity 'INFO' + + if ($localPool -ne $WorkerPool) { + Write-Log -message "Worker Pool MISMATCH!" -severity 'ERROR' + $SETPXE = $true + } + else { + Write-Log -message "Worker Pool Match: $WorkerPool" -severity 'INFO' + } + + if ([string]::IsNullOrWhiteSpace($yamlHash) -or $localHash -ne $yamlHash) { + Write-Log -message "Git Hash MISMATCH or missing YAML hash!" -severity 'ERROR' + Write-Log -message "Local: $localHash" -severity 'WARN' + Write-Log -message "YAML : $yamlHash" -severity 'WARN' + $SETPXE = $true + } + else { + Write-Log -message "Git Hash Match: $yamlHash" -severity 'INFO' + } + + if (!(Test-Path $yamlImageDir)) { + Write-Log -message "Image directory missing: $yamlImageDir" -severity 'ERROR' + $SETPXE = $true + } + + if ($SETPXE) { + Write-Log -message "Configuration mismatch — initiating PXE + reboot." -severity 'ERROR' + Set-PXE + Restart-Computer -Force + return + } + + Write-Log -message "Configuration is correct. No reboot required." -severity 'INFO' + } + + end { + Write-Log -message ('{0} :: end - {1:o}' -f $($MyInvocation.MyCommand.Name), (Get-Date).ToUniversalTime()) -severity 'DEBUG' + } +} +function Remove-OldTaskDirectories { + param ( + [string[]] $targets = @('Z:\task_*', 'C:\Users\task_*') + ) + begin { + Write-Log -message ('{0} :: begin - {1:o}' -f $($MyInvocation.MyCommand.Name), (Get-Date).ToUniversalTime()) -severity 'DEBUG' + } + process { + foreach ($target in ($targets | Where-Object { (Test-Path -Path ('{0}:\' -f $_[0]) -ErrorAction SilentlyContinue) })) { + $all_task_paths = @(Get-ChildItem -Path $target | Sort-Object -Property { $_.LastWriteTime }) + if ($all_task_paths.length -gt 1) { + Write-Log -message ('{0} :: {1} task directories detected matching pattern: {2}' -f $($MyInvocation.MyCommand.Name), $all_task_paths.length, $target) -severity 'INFO' + $old_task_paths = $all_task_paths[0..($all_task_paths.Length - 2)] + foreach ($old_task_path in $old_task_paths) { + try { + & takeown.exe @('/a', '/f', $old_task_path, '/r', '/d', 'Y') + & icacls.exe @($old_task_path, '/grant', 'Administrators:F', '/t') + Remove-Item -Path $old_task_path -Force -Recurse + Write-Log -message ('{0} :: removed task directory: {1}, with last write time: {2}' -f $($MyInvocation.MyCommand.Name), $old_task_path.FullName, $old_task_path.LastWriteTime) -severity 'INFO' + } + catch { + Write-Log -message ('{0} :: failed to remove task directory: {1}, with last write time: {2}. {3}' -f $($MyInvocation.MyCommand.Name), $old_task_path.FullName, $old_task_path.LastWriteTime, $_.Exception.Message) -severity 'ERROR' + } + } + } + elseif ($all_task_paths.length -eq 1) { + Write-Log -message ('{0} :: a single task directory was detected at: {1}, with last write time: {2}' -f $($MyInvocation.MyCommand.Name), $all_task_paths[0].FullName, $all_task_paths[0].LastWriteTime) -severity 'DEBUG' + } + else { + Write-Log -message ('{0} :: no task directories detected matching pattern: {1}' -f $($MyInvocation.MyCommand.Name), $target) -severity 'DEBUG' + } + } + } + end { + Write-Log -message ('{0} :: end - {1:o}' -f $($MyInvocation.MyCommand.Name), (Get-Date).ToUniversalTime()) -severity 'DEBUG' + } +} +function Check-RoninNodeOptions { + param ( + [string] $inmutable = (Get-ItemProperty -path "HKLM:\SOFTWARE\Mozilla\ronin_puppet").inmutable, + [string] $flagfile = "$env:programdata\PuppetLabs\ronin\semaphore\task-claim-state.valid" + ) + begin { + Write-Log -message ('{0} :: begin - {1:o}' -f $($MyInvocation.MyCommand.Name), (Get-Date).ToUniversalTime()) -severity 'DEBUG' + } + process { + Write-Host $inmutable + if ($inmutable -eq 'true') { + Write-Log -message ('{0} :: Node is set to be inmutable' -f $($MyInvocation.MyCommand.Name)) -severity 'DEBUG' + Remove-Item -path $lock -ErrorAction SilentlyContinue + write-host New-item -path $flagfile + Exit-PSSession + } + } + end { + Write-Log -message ('{0} :: end - {1:o}' -f $($MyInvocation.MyCommand.Name), (Get-Date).ToUniversalTime()) -severity 'DEBUG' + } +} + +Function UpdateRonin { + param ( + [string] $sourceOrg, + [string] $sourceRepo, + [string] $sourceBranch, + [string] $ronin_repo = "$env:systemdrive\ronin" + ) + begin { + Write-Log -message ('{0} :: begin - {1:o}' -f $($MyInvocation.MyCommand.Name), (Get-Date).ToUniversalTime()) -severity 'DEBUG' + } + process { + $sourceOrg = $(if ((Test-Path -Path 'HKLM:\SOFTWARE\Mozilla\ronin_puppet\Source' -ErrorAction SilentlyContinue) -and (Get-ItemProperty -Path 'HKLM:\SOFTWARE\Mozilla\ronin_puppet\Source' -Name 'Organisation' -ErrorAction SilentlyContinue)) { (Get-ItemProperty -Path 'HKLM:\SOFTWARE\Mozilla\ronin_puppet\Source' -Name 'Organisation').Organisation } else { 'mozilla-platform-ops' }) + $sourceRepo = $(if ((Test-Path -Path 'HKLM:\SOFTWARE\Mozilla\ronin_puppet\Source' -ErrorAction SilentlyContinue) -and (Get-ItemProperty -Path 'HKLM:\SOFTWARE\Mozilla\ronin_puppet\Source' -Name 'Repository' -ErrorAction SilentlyContinue)) { (Get-ItemProperty -Path 'HKLM:\SOFTWARE\Mozilla\ronin_puppet\Source' -Name 'Repository').Repository } else { 'ronin_puppet' }) + $sourceBranch = $(if ((Test-Path -Path 'HKLM:\SOFTWARE\Mozilla\ronin_puppet\Source' -ErrorAction SilentlyContinue) -and (Get-ItemProperty -Path 'HKLM:\SOFTWARE\Mozilla\ronin_puppet\Source' -Name 'Branch' -ErrorAction SilentlyContinue)) { (Get-ItemProperty -Path 'HKLM:\SOFTWARE\Mozilla\ronin_puppet\Source' -Name 'Branch').Branch } else { 'master' }) + + Set-Location $ronin_repo + git config --global --add safe.directory "C:/ronin" + git pull https://github.com/$sourceOrg/$sourceRepo $sourceBranch + $git_exit = $LastExitCode + if ($git_exit -eq 0) { + $git_hash = (git rev-parse --verify HEAD) + Set-ItemProperty -Path HKLM:\SOFTWARE\Mozilla\ronin_puppet -name githash -type string -value $git_hash + Write-Log -message ('{0} :: Checking/pulling updates from https://github.com/{1}/{2}. Branch: {3}.' -f $($MyInvocation.MyCommand.Name), ($sourceOrg), ($sourceRepo), ($sourceRev)) -severity 'DEBUG' + } + else { + # Fall back to clone if pull fails + Write-Log -message ('{0} :: Git pull failed! https://github.com/{1}/{2}. Branch: {3}.' -f $($MyInvocation.MyCommand.Name), ($sourceOrg), ($sourceRepo), ($sourceRev)) -severity 'DEBUG' + Write-Log -message ('{0} :: Deleting old repository and cloning repository .' -f $($MyInvocation.MyCommand.Name)) -severity 'DEBUG' + Move-item -Path $ronin_repo\manifests\nodes.pp -Destination $env:TEMP\nodes.pp + Move-item -Path $ronin_repo\data\secrets\vault.yaml -Destination $env:TEMP\vault.yaml + #Remove-Item -Recurse -Force $ronin_repo + Start-Sleep -s 2 + git clone --single-branch --branch $sourceRev https://github.com/$sourceOrg/$sourceRepo $ronin_repo + Move-item -Path $env:TEMP\nodes.pp -Destination $ronin_repo\manifests\nodes.pp + Move-item -Path $env:TEMP\vault.yaml -Destination $ronin_repo\data\secrets\vault.yaml + } + } + end { + Write-Log -message ('{0} :: end - {1:o}' -f $($MyInvocation.MyCommand.Name), (Get-Date).ToUniversalTime()) -severity 'DEBUG' + } +} +function Puppet-Run { + param ( + [int] $exit, + [string] $lock = "$env:programdata\PuppetLabs\ronin\semaphore\ronin_run.lock", + [int] $last_exit = (Get-ItemProperty "HKLM:\SOFTWARE\Mozilla\ronin_puppet").last_run_exit, + [string] $run_to_success = (Get-ItemProperty "HKLM:\SOFTWARE\Mozilla\ronin_puppet").runtosuccess, + [string] $nodes_def = "$env:systemdrive\ronin\manifests\nodes\odes.pp", + [string] $logdir = "$env:systemdrive\logs", + [string] $fail_dir = "$env:systemdrive\fail_logs", + [string] $log_file = "$datetime-puppetrun.log", + [string] $datetime = (get-date -format yyyyMMdd-HHmm), + [string] $flagfile = "$env:programdata\PuppetLabs\ronin\semaphore\task-claim-state.valid" + ) + begin { + Write-Log -message ('{0} :: begin - {1:o}' -f $($MyInvocation.MyCommand.Name), (Get-Date).ToUniversalTime()) -severity 'DEBUG' + } + process { + + Check-RoninNodeOptions + UpdateRonin + + # Setting Env variabes for PuppetFile install and Puppet run + # The ssl variables are needed for R10k + Write-Log -message ('{0} :: Setting Puppet enviroment.' -f $($MyInvocation.MyCommand.Name)) -severity 'DEBUG' + $env:path = "$($env:ProgramFiles)\Puppet Labs\Puppet\puppet\bin;$($env:ProgramFiles)\Puppet Labs\Puppet\bin;$env:path" + + $env:SSL_CERT_FILE = "$($env:ProgramFiles)\Puppet Labs\Puppet\puppet\ssl\cert.pem" + $env:SSL_CERT_DIR = "$($env:ProgramFiles)\Puppet Labs\Puppet\puppet\ssl" + $env:FACTER_env_windows_installdir = "$($env:ProgramFiles)\Puppet Labs\Puppet" + $env:PL_BASEDIR = "$($env:ProgramFiles)\Puppet Labs\Puppet" + $env:PUPPET_DIR = "$($env:ProgramFiles)\Puppet Labs\Puppet" + $env:RUBYLIB = "$($env:ProgramFiles)\Puppet Labs\Puppet\lib" + + $env:USERNAME = "Administrator" + $env:USERPROFILE = "$env:systemdrive\Users\Administrator" + + # This is temporary and should be removed after the cloud_windows branch is merged + # Hiera lookups will fail after the merge if this is not in place following the merge + <# + if((test-path $env:systemdrive\ronin\win_hiera.yaml)) { + $hiera = "win_hiera.yaml" + } else { + $hiera = "hiera.yaml" + } + #> + # this will break Win 10 1803 if this is merged into the master brnach + $hiera = "hiera.yaml" + + # Needs to be removed from path or a wrong puppet file will be used + $env:path = ($env:path.Split(';') | Where-Object { $_ -ne "$env:programfiles\Puppet Labs\Puppet\puppet\bin" }) -join ';' + If (!(test-path $fail_dir)) { + New-Item -ItemType Directory -Force -Path $fail_dir + } + Get-ChildItem -Path $logdir\*.log -Recurse | Move-Item -Destination $logdir\old -ErrorAction SilentlyContinue + Write-Log -message ('{0} :: Initiating Puppet apply .' -f $($MyInvocation.MyCommand.Name)) -severity 'DEBUG' + puppet apply manifests\nodes.pp --onetime --verbose --no-daemonize --no-usecacheonfailure --detailed-exitcodes --no-splay --show_diff --modulepath=modules`;r10k_modules --hiera_config=$hiera --logdest $logdir\$log_file + [int]$puppet_exit = $LastExitCode + + if ($run_to_success -eq 'true') { + if (($puppet_exit -ne 0) -and ($puppet_exit -ne 2)) { + if ($last_exit -eq 0) { + Write-Log -message ('{0} :: Puppet apply failed.' -f $($MyInvocation.MyCommand.Name)) -severity 'DEBUG' + Set-ItemProperty -Path HKLM:\SOFTWARE\Mozilla\ronin_puppet -name last_exit -type dword -value $puppet_exit + Remove-Item $lock -ErrorAction SilentlyContinue + # If the Puppet run fails send logs to papertrail + # Nxlog watches $fail_dir for files names *-puppetrun.log + Move-Item $logdir\$log_file -Destination $fail_dir + shutdown @('-r', '-t', '0', '-c', 'Reboot; Puppet apply failed', '-f', '-d', '4:5') + } + elseif ($last_exit -ne 0) { + Set-ItemProperty -Path HKLM:\SOFTWARE\Mozilla\ronin_puppet -name last_exit -type dword -value $puppet_exit + Remove-Item $lock + Move-Item $logdir\$log_file -Destination $fail_dir + Write-Log -message ('{0} :: Puppet apply failed. Waiting 10 minutes beofre Reboot' -f $($MyInvocation.MyCommand.Name)) -severity 'DEBUG' + Start-Sleep 600 + shutdown @('-r', '-t', '0', '-c', 'Reboot; Puppet apply failed', '-f', '-d', '4:5') + } + } + elseif (($puppet_exit -match 0) -or ($puppet_exit -match 2)) { + Write-Log -message ('{0} :: Puppet apply successful' -f $($MyInvocation.MyCommand.Name)) -severity 'DEBUG' + Set-ItemProperty -Path HKLM:\SOFTWARE\Mozilla\ronin_puppet -name last_exit -type dword -value $puppet_exit + Remove-Item -path $lock + New-item -path $flagfile + } + else { + Write-Log -message ('{0} :: Unable to detrimine state post Puppet apply' -f $($MyInvocation.MyCommand.Name)) -severity 'DEBUG' + Set-ItemProperty -Path HKLM:\SOFTWARE\Mozilla\ronin_puppet -name last_exit -type dword -value $last_exit + Move-Item $logdir\$log_file -Destination $fail_dir + Remove-Item -path $lock + shutdown @('-r', '-t', '600', '-c', 'Reboot; Unveriable state', '-f', '-d', '4:5') + } + } + } + end { + Write-Log -message ('{0} :: end - {1:o}' -f $($MyInvocation.MyCommand.Name), (Get-Date).ToUniversalTime()) -severity 'DEBUG' + } +} + +function StartWorkerRunner { + param ( + ) + begin { + Write-Log -message ('{0} :: begin - {1:o}' -f $($MyInvocation.MyCommand.Name), (Get-Date).ToUniversalTime()) -severity 'DEBUG' + } + process { + ## Checking for issues with the user profile. + $lastBootTime = Get-WinEvent -LogName "System" -FilterXPath "" | + Select-Object -First 1 | + ForEach-Object { $_.TimeCreated } + $eventIDs = @(1511, 1515) + + $events = Get-WinEvent -LogName "Application" | + Where-Object { $_.ID -in $eventIDs -and $_.TimeCreated -gt $lastBootTime } | + Sort-Object TimeCreated -Descending | Select-Object -First 1 + + if ($events) { + Write-Log -message ('{0} :: Possible User Profile Corruption. Restarting' -f $($MyInvocation.MyCommand.Name)) -severity 'DEBUG' + Restart-Computer -Force + exit + } + Start-Service -Name worker-runner + } + end { + Write-Log -message ('{0} :: end - {1:o}' -f $($MyInvocation.MyCommand.Name), (Get-Date).ToUniversalTime()) -severity 'DEBUG' + } +} + +function Get-LoggedInUser { + [CmdletBinding()] + param ( + + ) + + @(((query user) -replace '\s{20,39}', ',,') -replace '\s{2,}', ',' | ConvertFrom-Csv) +} + +function Get-LatestGoogleChrome { + [CmdletBinding()] + param ( + [String] + $Package = "googlechrome" + ) + + ## Current version of google chrome + $current_version = choco list --exact $Package --limit-output | ConvertFrom-Csv -Delimiter '|' -Header 'Name', 'CurrentVersion' + + ## Use chocolatey with outdated + $choco_packages = choco outdated --limit-output | ConvertFrom-Csv -Delimiter '|' -Header 'Name', 'CurrentVersion', 'AvailableVersion', 'Pinned' + + ## Check if Google Chrome is present + $pkg = $choco_packages | Where-Object { $_.Name -eq $Package } + + ## There is no google chrome update, so output the current version + if ([String]::IsNullOrEmpty($pkg)) { + Write-Log -message ('{0} :: Google Chrome version installed is {1}' -f $($MyInvocation.MyCommand.Name), $current_version.CurrentVersion) -severity 'DEBUG' + } + else { + ## Chrome is installed and needs to be updated + if ($pkg.CurrentVersion -ne $pkg.AvailableVersion) { + ## run choco upgrade + Write-Log -message ('{0} :: Updating Google Chrome from current: {1} to available: {2}' -f $($MyInvocation.MyCommand.Name), $pkg.currentVersion, $pkg.availableVersion) -severity 'DEBUG' + choco upgrade $Package -y "--ignore-checksums" "--ignore-package-exit-codes" "--log-file" $env:systemdrive\logs\googlechrome.log + if ($LASTEXITCODE -ne 0) { + ## output to papertrail + Write-Log -message ('{0} :: choco upgrade googlechrome failed with {1}' -f $($MyInvocation.MyCommand.Name), $LASTEXITCODE) -severity 'DEBUG' + ## output chocolatey logs to papertrail + Get-Content $env:systemdrive\logs\googlechrome.log | ForEach-Object { Write-Log -message $_ -severity 'DEBUG' } + ## Sending the logs to papertrail, wait 30 seconds + Start-Sleep -Seconds 60 + ## PXE Boot + Set-PXE + } + else { + ## Need to reboot in order to complete the upgrade + Write-Log -message ('{0} :: Google Chrome needs to reboot to complete upgrade. Rebooting..' -f $($MyInvocation.MyCommand.Name)) -severity 'DEBUG' + Start-Sleep -Seconds 10 + Restart-Computer -Force + } + } + } +} + +function Set-PXE { + param ( + ) + begin { + Write-Log -message ('{0} :: begin - {1:o}' -f $($MyInvocation.MyCommand.Name), (Get-Date).ToUniversalTime()) -severity 'DEBUG' + } + process { + $temp_dir = "$env:systemdrive\temp\" + New-Item -ItemType Directory -Force -Path $temp_dir -ErrorAction SilentlyContinue + + bcdedit /enum firmware > $temp_dir\firmware.txt + + $fwbootmgr = Select-String -Path "$temp_dir\firmware.txt" -Pattern "{fwbootmgr}" + if (!$fwbootmgr) { + Write-Log -message ('{0} :: Device is configured for Legacy Boot. Exiting!' -f $($MyInvocation.MyCommand.Name)) -severity 'DEBUG' + Exit 999 + } + Try { + # Get the line of text with the GUID for the PXE boot option. + # IPV4 = most PXE boot options + $FullLine = (( Get-Content $temp_dir\firmware.txt | Select-String "IPV4|EFI Network" -Context 1 -ErrorAction Stop ).context.precontext)[0] + + # Remove all text but the GUID + $GUID = '{' + $FullLine.split('{')[1] + + # Add the PXE boot option to the top of the boot order on next boot + bcdedit /set "{fwbootmgr}" bootsequence "$GUID" + + Write-Log -message ('{0} :: Device will PXE boot. Restarting' -f $($MyInvocation.MyCommand.Name)) -severity 'DEBUG' + Restart-Computer -Force + } + Catch { + Write-Log -message ('{0} :: Unable to set next boot to PXE. Exiting!' -f $($MyInvocation.MyCommand.Name)) -severity 'DEBUG' + Exit 888 + } + } + end { + Write-Log -message ('{0} :: end - {1:o}' -f $($MyInvocation.MyCommand.Name), (Get-Date).ToUniversalTime()) -severity 'DEBUG' + } +} + +function Test-ConnectionUntilOnline { + param ( + [string]$Hostname = "www.google.com", + [int]$Interval = 5, + [int]$TotalTime = 120 + ) + + $elapsedTime = 0 + + while ($elapsedTime -lt $totalTime) { + if (Test-Connection -ComputerName $hostname -Count 1 -Quiet) { + Write-Log -message ('{0} :: {1} is online! Continuing.' -f $($MyInvocation.MyCommand.Name), $ENV:COMPUTERNAME) -severity 'DEBUG' + return + } + else { + Write-Log -message ('{0} :: {1} is not online, checking again in {2}' -f $($MyInvocation.MyCommand.Name), $ENV:COMPUTERNAME, $interval) -severity 'DEBUG' + Start-Sleep -Seconds $interval + $elapsedTime += $interval + } + } + + Write-Log -message ('{0} :: {1} did not come online within {2} seconds' -f $($MyInvocation.MyCommand.Name), $ENV:COMPUTERNAME, $totalTime) -severity 'DEBUG' + throw "Connection timeout." +} + +## Bug https://bugzilla.mozilla.org/show_bug.cgi?id=1910123 +## The bug tracks when we reimaged a machine and the machine had a different refresh rate (64hz vs 60hz) +## This next line will check if the refresh rate is not 60hz and trigger a reimage if so +$hardware = Get-CimInstance -ClassName Win32_ComputerSystem | Select-Object -Property Manufacturer, Model +$model = $hardware.Model +$refresh_rate = (Get-WmiObject win32_videocontroller).CurrentRefreshRate +if ($refresh_rate -ne "60") { + Write-Log -message ('{0} :: Refresh rate is {1}. Reimaging {2}' -f $($MyInvocation.MyCommand.Name), $refresh_rate, $ENV:COMPUTERNAME) -severity 'DEBUG' + Set-PXE +} + +$bootstrap_stage = (Get-ItemProperty -path "HKLM:\SOFTWARE\Mozilla\ronin_puppet").bootstrap_stage +If ($bootstrap_stage -eq 'complete') { + CompareConfigBasic + Start-Sleep -Seconds 2 + Run-MaintainSystem + ## We're getting user profile corruption errors, so let's check that the user is logged in using quser.exe + for ($i = 0; $i -lt 3; $i++) { + $loggedInUser = (Get-LoggedInUser).UserName -replace ">" + if ($loggedInUser -notmatch "task") { + Write-Log -message ('{0} :: User logged in: {1}' -f $($MyInvocation.MyCommand.Name), $loggedInUser) -severity 'DEBUG' + Start-Sleep -Seconds 10 + } + else { + Write-Log -message ('{0} :: User logged in: {1}' -f $($MyInvocation.MyCommand.Name), $loggedInUser) -severity 'DEBUG' + break + } + } + + ## Let's make sure the machine is online before checking the internet + Test-ConnectionUntilOnline + + ## Let's check for the latest install of google chrome using chocolatey before starting worker runner + ## Instead of querying chocolatey each time this runs, let's query chrome json endoint and check locally installed version + Get-LatestGoogleChrome + + StartWorkerRunner +} +else { + Write-Log -message ('{0} :: Bootstrap has not completed. EXITING!' -f $($MyInvocation.MyCommand.Name)) -severity 'DEBUG' + Exit-PSSession +} diff --git a/modules/win_scheduled_tasks/files/maintainsystem-hw.ps1 b/modules/win_scheduled_tasks/files/maintainsystem-hw.ps1 index 2f4d49411..734b216ea 100644 --- a/modules/win_scheduled_tasks/files/maintainsystem-hw.ps1 +++ b/modules/win_scheduled_tasks/files/maintainsystem-hw.ps1 @@ -87,38 +87,38 @@ function CompareConfigBasic { })[0] } catch { - Write-Log -message "Failed to get IP address" -severity 'ERROR' + Write-Log -message ('{0} :: Failed to get IP address' -f $MyInvocation.MyCommand.Name) -severity 'ERROR' } } if (-not $IPAddress) { - Write-Log -message "No IP Address could be determined." -severity 'ERROR' + Write-Log -message ('{0} :: No IP Address could be determined.' -f $MyInvocation.MyCommand.Name) -severity 'ERROR' Restart-Computer -Force return } - Write-Log -message "IP Address: $IPAddress" -severity 'INFO' + Write-Log -message ('{0} :: IP Address: {1}' -f $MyInvocation.MyCommand.Name, $IPAddress) -severity 'INFO' try { $ResolvedName = (Resolve-DnsName -Name $IPAddress -Server "10.48.75.120").NameHost } catch { - Write-Log -message "DNS resolution failed." -severity 'ERROR' + Write-Log -message ('{0} :: DNS resolution failed.' -f $MyInvocation.MyCommand.Name) -severity 'ERROR' Restart-Computer -Force return } - Write-Log -message "Resolved Name: $ResolvedName" -severity 'INFO' + Write-Log -message ('{0} :: Resolved Name: {1}' -f $MyInvocation.MyCommand.Name, $ResolvedName) -severity 'INFO' $index = $ResolvedName.IndexOf('.') if ($index -lt 0) { - Write-Log -message "Invalid hostname format." -severity 'ERROR' + Write-Log -message ('{0} :: Invalid hostname format.' -f $MyInvocation.MyCommand.Name) -severity 'ERROR' Restart-Computer -Force return } $worker_node_name = $ResolvedName.Substring(0, $index) - Write-Log -message "Host name set to: $worker_node_name" -severity 'INFO' + Write-Log -message ('{0} :: Host name set to: {1}' -f $MyInvocation.MyCommand.Name, $worker_node_name) -severity 'INFO' $localHash = (Get-ItemProperty -Path HKLM:\SOFTWARE\Mozilla\ronin_puppet).GITHASH $localPool = (Get-ItemProperty -Path HKLM:\SOFTWARE\Mozilla\ronin_puppet).worker_pool_id @@ -146,14 +146,14 @@ function CompareConfigBasic { } } catch { - Write-Log -message "Attempt $($attempt + 1): Failed to fetch YAML - $_" -severity 'WARN' + Write-Log -message ('{0} :: Attempt {1}: Failed to fetch YAML - {2}' -f $MyInvocation.MyCommand.Name, ($attempt + 1), $_) -severity 'WARN' Start-Sleep -Seconds $retryDelay $attempt++ } } if (-not $success) { - Write-Log -message "YAML could not be loaded. Forcing PXE + reboot." -severity 'ERROR' + Write-Log -message ('{0} :: YAML could not be loaded. Forcing PXE + reboot.' -f $MyInvocation.MyCommand.Name) -severity 'ERROR' Set-PXE Restart-Computer -Force return @@ -172,45 +172,45 @@ function CompareConfigBasic { } if (-not $found) { - Write-Log -message "Node not found in YAML. Forcing PXE + reboot." -severity 'ERROR' + Write-Log -message ('{0} :: Node not found in YAML. Forcing PXE + reboot.' -f $MyInvocation.MyCommand.Name) -severity 'ERROR' Set-PXE Restart-Computer -Force return } - Write-Log -message "=== Configuration Comparison ===" -severity 'INFO' + Write-Log -message ('{0} :: === Configuration Comparison ===' -f $MyInvocation.MyCommand.Name) -severity 'INFO' if ($localPool -ne $WorkerPool) { - Write-Log -message "Worker Pool MISMATCH!" -severity 'ERROR' + Write-Log -message ('{0} :: Worker Pool MISMATCH!' -f $MyInvocation.MyCommand.Name) -severity 'ERROR' $SETPXE = $true } else { - Write-Log -message "Worker Pool Match: $WorkerPool" -severity 'INFO' + Write-Log -message ('{0} :: Worker Pool Match: {1}' -f $MyInvocation.MyCommand.Name, $WorkerPool) -severity 'INFO' } if ([string]::IsNullOrWhiteSpace($yamlHash) -or $localHash -ne $yamlHash) { - Write-Log -message "Git Hash MISMATCH or missing YAML hash!" -severity 'ERROR' - Write-Log -message "Local: $localHash" -severity 'WARN' - Write-Log -message "YAML : $yamlHash" -severity 'WARN' + Write-Log -message ('{0} :: Git Hash MISMATCH or missing YAML hash!' -f $MyInvocation.MyCommand.Name) -severity 'ERROR' + Write-Log -message ('{0} :: Local: {1}' -f $MyInvocation.MyCommand.Name, $localHash) -severity 'WARN' + Write-Log -message ('{0} :: YAML : {1}' -f $MyInvocation.MyCommand.Name, $yamlHash) -severity 'WARN' $SETPXE = $true } else { - Write-Log -message "Git Hash Match: $yamlHash" -severity 'INFO' + Write-Log -message ('{0} :: Git Hash Match: {1}' -f $MyInvocation.MyCommand.Name, $yamlHash) -severity 'INFO' } if (!(Test-Path $yamlImageDir)) { - Write-Log -message "Image directory missing: $yamlImageDir" -severity 'ERROR' + Write-Log -message ('{0} :: Image directory missing: {1}' -f $MyInvocation.MyCommand.Name, $yamlImageDir) -severity 'ERROR' $SETPXE = $true } if ($SETPXE) { - Write-Log -message "Configuration mismatch — initiating PXE + reboot." -severity 'ERROR' + Write-Log -message ('{0} :: Configuration mismatch — initiating PXE + reboot.' -f $MyInvocation.MyCommand.Name) -severity 'ERROR' Set-PXE Restart-Computer -Force return } - Write-Log -message "Configuration is correct. No reboot required." -severity 'INFO' + Write-Log -message ('{0} :: Configuration is correct. No reboot required.' -f $MyInvocation.MyCommand.Name) -severity 'INFO' } end { From 0ba321479d4c83b029511d7db55d430de36bb548 Mon Sep 17 00:00:00 2001 From: Mark Cornmesser Date: Mon, 8 Dec 2025 15:08:43 -0800 Subject: [PATCH 008/105] troubelshooting --- .../files/maintainsystem-hw.ps1 | 299 ++++++------------ 1 file changed, 105 insertions(+), 194 deletions(-) diff --git a/modules/win_scheduled_tasks/files/maintainsystem-hw.ps1 b/modules/win_scheduled_tasks/files/maintainsystem-hw.ps1 index 734b216ea..df4824b8a 100644 --- a/modules/win_scheduled_tasks/files/maintainsystem-hw.ps1 +++ b/modules/win_scheduled_tasks/files/maintainsystem-hw.ps1 @@ -55,6 +55,55 @@ function Run-MaintainSystem { Write-Log -message ('{0} :: end - {1:o}' -f $($MyInvocation.MyCommand.Name), (Get-Date).ToUniversalTime()) -severity 'DEBUG' } } +function Invoke-DownloadWithRetryGithub { + Param( + [Parameter(Mandatory)] [string] $Url, + [Alias("Destination")] [string] $Path, + [string] $PAT + ) + if (-not $Path) { + $invalidChars = [IO.Path]::GetInvalidFileNameChars() -join '' + $re = "[{0}]" -f [RegEx]::Escape($invalidChars) + $fileName = [IO.Path]::GetFileName($Url) -replace $re + if ([String]::IsNullOrEmpty($fileName)) { $fileName = [System.IO.Path]::GetRandomFileName() } + $Path = Join-Path -Path "${env:Temp}" -ChildPath $fileName + } + Write-Host "Downloading package from $Url to $Path..." + $interval = 30 + $downloadStartTime = Get-Date + for ($retries = 20; $retries -gt 0; $retries--) { + try { + $attemptStartTime = Get-Date + $Headers = @{ + Accept = "application/vnd.github+json" + Authorization = "Bearer $($PAT)" + "X-GitHub-Api-Version" = "2022-11-28" + } + $response = Invoke-WebRequest -Uri $Url -Headers $Headers -OutFile $Path + $attemptSeconds = [math]::Round(($(Get-Date) - $attemptStartTime).TotalSeconds, 2) + Write-Host "Package downloaded in $attemptSeconds seconds" + Write-Host "Status: $($response.statuscode)" + break + } catch { + $attemptSeconds = [math]::Round(($(Get-Date) - $attemptStartTime).TotalSeconds, 2) + Write-Warning "Package download failed in $attemptSeconds seconds" + Write-Host "Status: $($response.statuscode)" + Write-Warning $_.Exception.Message + if ($_.Exception.InnerException.Response.StatusCode -eq [System.Net.HttpStatusCode]::NotFound) { + Write-Warning "Request returned 404 Not Found. Aborting download." + $retries = 0 + } + } + if ($retries -eq 0) { + $totalSeconds = [math]::Round(($(Get-Date) - $downloadStartTime).TotalSeconds, 2) + throw "Package download failed after $totalSeconds seconds" + } + Write-Warning "Waiting $interval seconds before retrying (retries left: $retries)..." + Start-Sleep -Seconds $interval + } + return $Path +} + function CompareConfigBasic { param ( [string]$yaml_url = "https://raw.githubusercontent.com/mozilla-platform-ops/worker-images/refs/heads/main/provisioners/windows/MDC1Windows/pools.yml", @@ -66,11 +115,13 @@ function CompareConfigBasic { } process { - $yaml = $null + $SETPXE = $false + $yaml = $null $yamlHash = $null $IPAddress = $null + # === Retrieve IP address === $Ethernet = [System.Net.NetworkInformation.NetworkInterface]::GetAllNetworkInterfaces() | Where-Object { $_.Name -match "ethernet" } @@ -99,11 +150,13 @@ function CompareConfigBasic { Write-Log -message ('{0} :: IP Address: {1}' -f $MyInvocation.MyCommand.Name, $IPAddress) -severity 'INFO' + + # === Resolve DNS to get worker name === try { $ResolvedName = (Resolve-DnsName -Name $IPAddress -Server "10.48.75.120").NameHost } catch { - Write-Log -message ('{0} :: DNS resolution failed.' -f $MyInvocation.MyCommand.Name) -severity 'ERROR' + Write-Log -message ('{0} :: DNS resolution failed' -f $MyInvocation.MyCommand.Name) -severity 'ERROR' Restart-Computer -Force return } @@ -120,59 +173,68 @@ function CompareConfigBasic { $worker_node_name = $ResolvedName.Substring(0, $index) Write-Log -message ('{0} :: Host name set to: {1}' -f $MyInvocation.MyCommand.Name, $worker_node_name) -severity 'INFO' + + # === Load local ronin puppet values === $localHash = (Get-ItemProperty -Path HKLM:\SOFTWARE\Mozilla\ronin_puppet).GITHASH $localPool = (Get-ItemProperty -Path HKLM:\SOFTWARE\Mozilla\ronin_puppet).worker_pool_id - $maxRetries = 5 - $retryDelay = 10 - $attempt = 0 - $success = $false - while ($attempt -lt $maxRetries -and -not $success) { - try { - $Headers = @{ - Accept = "application/vnd.github+json" - Authorization = "Bearer $($PAT)" - "X-GitHub-Api-Version" = "2022-11-28" - } - $response = Invoke-WebRequest -Uri $yaml_url -UseBasicParsing -TimeoutSec 10 -ErrorAction Stop -Headers $Headers - $yaml = $response.Content | ConvertFrom-Yaml + # === Load PAT for YAML download === + $patFile = "D:\Secrets\pat.txt" + if (-not (Test-Path $patFile)) { + Write-Log -message ('{0} :: PAT file missing: {1}' -f $MyInvocation.MyCommand.Name, $patFile) -severity 'ERROR' + Set-PXE + Restart-Computer -Force + return + } - if ($yaml) { - $success = $true - } - else { - throw "YAML content empty" - } - } - catch { - Write-Log -message ('{0} :: Attempt {1}: Failed to fetch YAML - {2}' -f $MyInvocation.MyCommand.Name, ($attempt + 1), $_) -severity 'WARN' - Start-Sleep -Seconds $retryDelay - $attempt++ - } + $PAT = Get-Content $patFile -ErrorAction Stop + + + # === Download YAML using unified retry function === + $tempYamlPath = "$env:TEMP\pools.yml" + + $splat = @{ + Url = $yaml_url + Path = $tempYamlPath + PAT = $PAT } - if (-not $success) { - Write-Log -message ('{0} :: YAML could not be loaded. Forcing PXE + reboot.' -f $MyInvocation.MyCommand.Name) -severity 'ERROR' + if (-not (Invoke-DownloadWithRetryGithub @splat)) { + Write-Log -message ('{0} :: YAML download failed after retries. PXE rebooting.' -f $MyInvocation.MyCommand.Name) -severity 'ERROR' Set-PXE Restart-Computer -Force return } + + # === Parse YAML === + try { + $yaml = Get-Content $tempYamlPath -Raw | ConvertFrom-Yaml + } + catch { + Write-Log -message ('{0} :: YAML parsing failed: {1}' -f $MyInvocation.MyCommand.Name, $_) -severity 'ERROR' + Set-PXE + Restart-Computer -Force + return + } + + + # === Lookup this worker in pools.yml === $found = $false foreach ($pool in $yaml.pools) { if ($pool.nodes -contains $worker_node_name) { - $WorkerPool = $pool.name - $yamlHash = $pool.hash - $yamlImageName = $pool.image - $yamlImageDir = "D:\" + $yamlImageName + $WorkerPool = $pool.name + $yamlHash = $pool.hash + $yamlImageName = $pool.image + $yamlImageDir = "D:\" + $yamlImageName $found = $true break } } if (-not $found) { - Write-Log -message ('{0} :: Node not found in YAML. Forcing PXE + reboot.' -f $MyInvocation.MyCommand.Name) -severity 'ERROR' + Write-Log -message ('{0} :: Node not found in YAML. PXE rebooting.' -f $MyInvocation.MyCommand.Name) -severity 'ERROR' Set-PXE Restart-Computer -Force return @@ -180,6 +242,8 @@ function CompareConfigBasic { Write-Log -message ('{0} :: === Configuration Comparison ===' -f $MyInvocation.MyCommand.Name) -severity 'INFO' + + # === Compare pool === if ($localPool -ne $WorkerPool) { Write-Log -message ('{0} :: Worker Pool MISMATCH!' -f $MyInvocation.MyCommand.Name) -severity 'ERROR' $SETPXE = $true @@ -188,6 +252,8 @@ function CompareConfigBasic { Write-Log -message ('{0} :: Worker Pool Match: {1}' -f $MyInvocation.MyCommand.Name, $WorkerPool) -severity 'INFO' } + + # === Compare puppet githash === if ([string]::IsNullOrWhiteSpace($yamlHash) -or $localHash -ne $yamlHash) { Write-Log -message ('{0} :: Git Hash MISMATCH or missing YAML hash!' -f $MyInvocation.MyCommand.Name) -severity 'ERROR' Write-Log -message ('{0} :: Local: {1}' -f $MyInvocation.MyCommand.Name, $localHash) -severity 'WARN' @@ -198,11 +264,15 @@ function CompareConfigBasic { Write-Log -message ('{0} :: Git Hash Match: {1}' -f $MyInvocation.MyCommand.Name, $yamlHash) -severity 'INFO' } + + # === Verify local puppet image directory exists === if (!(Test-Path $yamlImageDir)) { Write-Log -message ('{0} :: Image directory missing: {1}' -f $MyInvocation.MyCommand.Name, $yamlImageDir) -severity 'ERROR' $SETPXE = $true } + + # === If anything mismatched, PXE reboot === if ($SETPXE) { Write-Log -message ('{0} :: Configuration mismatch — initiating PXE + reboot.' -f $MyInvocation.MyCommand.Name) -severity 'ERROR' Set-PXE @@ -217,6 +287,7 @@ function CompareConfigBasic { Write-Log -message ('{0} :: end - {1:o}' -f $($MyInvocation.MyCommand.Name), (Get-Date).ToUniversalTime()) -severity 'DEBUG' } } + function Remove-OldTaskDirectories { param ( [string[]] $targets = @('Z:\task_*', 'C:\Users\task_*') @@ -254,166 +325,6 @@ function Remove-OldTaskDirectories { Write-Log -message ('{0} :: end - {1:o}' -f $($MyInvocation.MyCommand.Name), (Get-Date).ToUniversalTime()) -severity 'DEBUG' } } -function Check-RoninNodeOptions { - param ( - [string] $inmutable = (Get-ItemProperty -path "HKLM:\SOFTWARE\Mozilla\ronin_puppet").inmutable, - [string] $flagfile = "$env:programdata\PuppetLabs\ronin\semaphore\task-claim-state.valid" - ) - begin { - Write-Log -message ('{0} :: begin - {1:o}' -f $($MyInvocation.MyCommand.Name), (Get-Date).ToUniversalTime()) -severity 'DEBUG' - } - process { - Write-Host $inmutable - if ($inmutable -eq 'true') { - Write-Log -message ('{0} :: Node is set to be inmutable' -f $($MyInvocation.MyCommand.Name)) -severity 'DEBUG' - Remove-Item -path $lock -ErrorAction SilentlyContinue - write-host New-item -path $flagfile - Exit-PSSession - } - } - end { - Write-Log -message ('{0} :: end - {1:o}' -f $($MyInvocation.MyCommand.Name), (Get-Date).ToUniversalTime()) -severity 'DEBUG' - } -} - -Function UpdateRonin { - param ( - [string] $sourceOrg, - [string] $sourceRepo, - [string] $sourceBranch, - [string] $ronin_repo = "$env:systemdrive\ronin" - ) - begin { - Write-Log -message ('{0} :: begin - {1:o}' -f $($MyInvocation.MyCommand.Name), (Get-Date).ToUniversalTime()) -severity 'DEBUG' - } - process { - $sourceOrg = $(if ((Test-Path -Path 'HKLM:\SOFTWARE\Mozilla\ronin_puppet\Source' -ErrorAction SilentlyContinue) -and (Get-ItemProperty -Path 'HKLM:\SOFTWARE\Mozilla\ronin_puppet\Source' -Name 'Organisation' -ErrorAction SilentlyContinue)) { (Get-ItemProperty -Path 'HKLM:\SOFTWARE\Mozilla\ronin_puppet\Source' -Name 'Organisation').Organisation } else { 'mozilla-platform-ops' }) - $sourceRepo = $(if ((Test-Path -Path 'HKLM:\SOFTWARE\Mozilla\ronin_puppet\Source' -ErrorAction SilentlyContinue) -and (Get-ItemProperty -Path 'HKLM:\SOFTWARE\Mozilla\ronin_puppet\Source' -Name 'Repository' -ErrorAction SilentlyContinue)) { (Get-ItemProperty -Path 'HKLM:\SOFTWARE\Mozilla\ronin_puppet\Source' -Name 'Repository').Repository } else { 'ronin_puppet' }) - $sourceBranch = $(if ((Test-Path -Path 'HKLM:\SOFTWARE\Mozilla\ronin_puppet\Source' -ErrorAction SilentlyContinue) -and (Get-ItemProperty -Path 'HKLM:\SOFTWARE\Mozilla\ronin_puppet\Source' -Name 'Branch' -ErrorAction SilentlyContinue)) { (Get-ItemProperty -Path 'HKLM:\SOFTWARE\Mozilla\ronin_puppet\Source' -Name 'Branch').Branch } else { 'master' }) - - Set-Location $ronin_repo - git config --global --add safe.directory "C:/ronin" - git pull https://github.com/$sourceOrg/$sourceRepo $sourceBranch - $git_exit = $LastExitCode - if ($git_exit -eq 0) { - $git_hash = (git rev-parse --verify HEAD) - Set-ItemProperty -Path HKLM:\SOFTWARE\Mozilla\ronin_puppet -name githash -type string -value $git_hash - Write-Log -message ('{0} :: Checking/pulling updates from https://github.com/{1}/{2}. Branch: {3}.' -f $($MyInvocation.MyCommand.Name), ($sourceOrg), ($sourceRepo), ($sourceRev)) -severity 'DEBUG' - } - else { - # Fall back to clone if pull fails - Write-Log -message ('{0} :: Git pull failed! https://github.com/{1}/{2}. Branch: {3}.' -f $($MyInvocation.MyCommand.Name), ($sourceOrg), ($sourceRepo), ($sourceRev)) -severity 'DEBUG' - Write-Log -message ('{0} :: Deleting old repository and cloning repository .' -f $($MyInvocation.MyCommand.Name)) -severity 'DEBUG' - Move-item -Path $ronin_repo\manifests\nodes.pp -Destination $env:TEMP\nodes.pp - Move-item -Path $ronin_repo\data\secrets\vault.yaml -Destination $env:TEMP\vault.yaml - #Remove-Item -Recurse -Force $ronin_repo - Start-Sleep -s 2 - git clone --single-branch --branch $sourceRev https://github.com/$sourceOrg/$sourceRepo $ronin_repo - Move-item -Path $env:TEMP\nodes.pp -Destination $ronin_repo\manifests\nodes.pp - Move-item -Path $env:TEMP\vault.yaml -Destination $ronin_repo\data\secrets\vault.yaml - } - } - end { - Write-Log -message ('{0} :: end - {1:o}' -f $($MyInvocation.MyCommand.Name), (Get-Date).ToUniversalTime()) -severity 'DEBUG' - } -} -function Puppet-Run { - param ( - [int] $exit, - [string] $lock = "$env:programdata\PuppetLabs\ronin\semaphore\ronin_run.lock", - [int] $last_exit = (Get-ItemProperty "HKLM:\SOFTWARE\Mozilla\ronin_puppet").last_run_exit, - [string] $run_to_success = (Get-ItemProperty "HKLM:\SOFTWARE\Mozilla\ronin_puppet").runtosuccess, - [string] $nodes_def = "$env:systemdrive\ronin\manifests\nodes\odes.pp", - [string] $logdir = "$env:systemdrive\logs", - [string] $fail_dir = "$env:systemdrive\fail_logs", - [string] $log_file = "$datetime-puppetrun.log", - [string] $datetime = (get-date -format yyyyMMdd-HHmm), - [string] $flagfile = "$env:programdata\PuppetLabs\ronin\semaphore\task-claim-state.valid" - ) - begin { - Write-Log -message ('{0} :: begin - {1:o}' -f $($MyInvocation.MyCommand.Name), (Get-Date).ToUniversalTime()) -severity 'DEBUG' - } - process { - - Check-RoninNodeOptions - UpdateRonin - - # Setting Env variabes for PuppetFile install and Puppet run - # The ssl variables are needed for R10k - Write-Log -message ('{0} :: Setting Puppet enviroment.' -f $($MyInvocation.MyCommand.Name)) -severity 'DEBUG' - $env:path = "$($env:ProgramFiles)\Puppet Labs\Puppet\puppet\bin;$($env:ProgramFiles)\Puppet Labs\Puppet\bin;$env:path" - - $env:SSL_CERT_FILE = "$($env:ProgramFiles)\Puppet Labs\Puppet\puppet\ssl\cert.pem" - $env:SSL_CERT_DIR = "$($env:ProgramFiles)\Puppet Labs\Puppet\puppet\ssl" - $env:FACTER_env_windows_installdir = "$($env:ProgramFiles)\Puppet Labs\Puppet" - $env:PL_BASEDIR = "$($env:ProgramFiles)\Puppet Labs\Puppet" - $env:PUPPET_DIR = "$($env:ProgramFiles)\Puppet Labs\Puppet" - $env:RUBYLIB = "$($env:ProgramFiles)\Puppet Labs\Puppet\lib" - - $env:USERNAME = "Administrator" - $env:USERPROFILE = "$env:systemdrive\Users\Administrator" - - # This is temporary and should be removed after the cloud_windows branch is merged - # Hiera lookups will fail after the merge if this is not in place following the merge - <# - if((test-path $env:systemdrive\ronin\win_hiera.yaml)) { - $hiera = "win_hiera.yaml" - } else { - $hiera = "hiera.yaml" - } - #> - # this will break Win 10 1803 if this is merged into the master brnach - $hiera = "hiera.yaml" - - # Needs to be removed from path or a wrong puppet file will be used - $env:path = ($env:path.Split(';') | Where-Object { $_ -ne "$env:programfiles\Puppet Labs\Puppet\puppet\bin" }) -join ';' - If (!(test-path $fail_dir)) { - New-Item -ItemType Directory -Force -Path $fail_dir - } - Get-ChildItem -Path $logdir\*.log -Recurse | Move-Item -Destination $logdir\old -ErrorAction SilentlyContinue - Write-Log -message ('{0} :: Initiating Puppet apply .' -f $($MyInvocation.MyCommand.Name)) -severity 'DEBUG' - puppet apply manifests\nodes.pp --onetime --verbose --no-daemonize --no-usecacheonfailure --detailed-exitcodes --no-splay --show_diff --modulepath=modules`;r10k_modules --hiera_config=$hiera --logdest $logdir\$log_file - [int]$puppet_exit = $LastExitCode - - if ($run_to_success -eq 'true') { - if (($puppet_exit -ne 0) -and ($puppet_exit -ne 2)) { - if ($last_exit -eq 0) { - Write-Log -message ('{0} :: Puppet apply failed.' -f $($MyInvocation.MyCommand.Name)) -severity 'DEBUG' - Set-ItemProperty -Path HKLM:\SOFTWARE\Mozilla\ronin_puppet -name last_exit -type dword -value $puppet_exit - Remove-Item $lock -ErrorAction SilentlyContinue - # If the Puppet run fails send logs to papertrail - # Nxlog watches $fail_dir for files names *-puppetrun.log - Move-Item $logdir\$log_file -Destination $fail_dir - shutdown @('-r', '-t', '0', '-c', 'Reboot; Puppet apply failed', '-f', '-d', '4:5') - } - elseif ($last_exit -ne 0) { - Set-ItemProperty -Path HKLM:\SOFTWARE\Mozilla\ronin_puppet -name last_exit -type dword -value $puppet_exit - Remove-Item $lock - Move-Item $logdir\$log_file -Destination $fail_dir - Write-Log -message ('{0} :: Puppet apply failed. Waiting 10 minutes beofre Reboot' -f $($MyInvocation.MyCommand.Name)) -severity 'DEBUG' - Start-Sleep 600 - shutdown @('-r', '-t', '0', '-c', 'Reboot; Puppet apply failed', '-f', '-d', '4:5') - } - } - elseif (($puppet_exit -match 0) -or ($puppet_exit -match 2)) { - Write-Log -message ('{0} :: Puppet apply successful' -f $($MyInvocation.MyCommand.Name)) -severity 'DEBUG' - Set-ItemProperty -Path HKLM:\SOFTWARE\Mozilla\ronin_puppet -name last_exit -type dword -value $puppet_exit - Remove-Item -path $lock - New-item -path $flagfile - } - else { - Write-Log -message ('{0} :: Unable to detrimine state post Puppet apply' -f $($MyInvocation.MyCommand.Name)) -severity 'DEBUG' - Set-ItemProperty -Path HKLM:\SOFTWARE\Mozilla\ronin_puppet -name last_exit -type dword -value $last_exit - Move-Item $logdir\$log_file -Destination $fail_dir - Remove-Item -path $lock - shutdown @('-r', '-t', '600', '-c', 'Reboot; Unveriable state', '-f', '-d', '4:5') - } - } - } - end { - Write-Log -message ('{0} :: end - {1:o}' -f $($MyInvocation.MyCommand.Name), (Get-Date).ToUniversalTime()) -severity 'DEBUG' - } -} function StartWorkerRunner { param ( From 8cce27e52b23a0a59debc48614822244d57cabdc Mon Sep 17 00:00:00 2001 From: Mark Cornmesser Date: Mon, 8 Dec 2025 15:56:35 -0800 Subject: [PATCH 009/105] add sched tasks --- modules/roles_profiles/manifests/profiles/scheduled_tasks.pp | 2 ++ modules/win_scheduled_tasks/manifests/self_redeploy_check.pp | 3 ++- 2 files changed, 4 insertions(+), 1 deletion(-) diff --git a/modules/roles_profiles/manifests/profiles/scheduled_tasks.pp b/modules/roles_profiles/manifests/profiles/scheduled_tasks.pp index 78440346d..a4db1b25a 100644 --- a/modules/roles_profiles/manifests/profiles/scheduled_tasks.pp +++ b/modules/roles_profiles/manifests/profiles/scheduled_tasks.pp @@ -12,6 +12,8 @@ } 'datacenter': { $startup_script = 'maintainsystem-hw.ps1' + include win_scheduled_tasks::self_redeploy_check + include win_scheduled_tasks::gw_exe_check } default: { $startup_script = 'maintainsystem.ps1' diff --git a/modules/win_scheduled_tasks/manifests/self_redeploy_check.pp b/modules/win_scheduled_tasks/manifests/self_redeploy_check.pp index ac5f5f4f7..909bcc2ed 100644 --- a/modules/win_scheduled_tasks/manifests/self_redeploy_check.pp +++ b/modules/win_scheduled_tasks/manifests/self_redeploy_check.pp @@ -19,7 +19,8 @@ trigger => [{ schedule => 'daily', start_time => '00:00', - minutes_interval => 120, + #minutes_interval => 120, + minutes_interval => 5, minutes_duration => 1440, # 24 hours = repeat every 2 hours all day }], user => 'SYSTEM', From b365ed905b44420566c08fc0acb381e7ea6241ac Mon Sep 17 00:00:00 2001 From: Mark Cornmesser Date: Mon, 8 Dec 2025 19:31:31 -0800 Subject: [PATCH 010/105] add sched tasks --- modules/roles_profiles/manifests/profiles/scheduled_tasks.pp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/modules/roles_profiles/manifests/profiles/scheduled_tasks.pp b/modules/roles_profiles/manifests/profiles/scheduled_tasks.pp index a4db1b25a..2ebe35685 100644 --- a/modules/roles_profiles/manifests/profiles/scheduled_tasks.pp +++ b/modules/roles_profiles/manifests/profiles/scheduled_tasks.pp @@ -13,7 +13,7 @@ 'datacenter': { $startup_script = 'maintainsystem-hw.ps1' include win_scheduled_tasks::self_redeploy_check - include win_scheduled_tasks::gw_exe_check + #include win_scheduled_tasks::gw_exe_check } default: { $startup_script = 'maintainsystem.ps1' From 266b5fcf3a293aa8477927c6e04e9ecdd4f4d8fd Mon Sep 17 00:00:00 2001 From: Mark Cornmesser Date: Tue, 9 Dec 2025 12:59:08 -0800 Subject: [PATCH 011/105] add in gw check sched task --- .../roles_profiles/manifests/profiles/scheduled_tasks.pp | 2 +- modules/win_scheduled_tasks/files/gw_exe_check.ps1 | 1 + modules/win_scheduled_tasks/files/maintainsystem-hw.ps1 | 1 + modules/win_scheduled_tasks/manifests/gw_exe_check.pp | 6 ++---- 4 files changed, 5 insertions(+), 5 deletions(-) diff --git a/modules/roles_profiles/manifests/profiles/scheduled_tasks.pp b/modules/roles_profiles/manifests/profiles/scheduled_tasks.pp index 2ebe35685..a4db1b25a 100644 --- a/modules/roles_profiles/manifests/profiles/scheduled_tasks.pp +++ b/modules/roles_profiles/manifests/profiles/scheduled_tasks.pp @@ -13,7 +13,7 @@ 'datacenter': { $startup_script = 'maintainsystem-hw.ps1' include win_scheduled_tasks::self_redeploy_check - #include win_scheduled_tasks::gw_exe_check + include win_scheduled_tasks::gw_exe_check } default: { $startup_script = 'maintainsystem.ps1' diff --git a/modules/win_scheduled_tasks/files/gw_exe_check.ps1 b/modules/win_scheduled_tasks/files/gw_exe_check.ps1 index 9816e0a8a..c687f33d1 100644 --- a/modules/win_scheduled_tasks/files/gw_exe_check.ps1 +++ b/modules/win_scheduled_tasks/files/gw_exe_check.ps1 @@ -94,6 +94,7 @@ if ($uptimeMinutes -lt 15) { exit } +# Var set by the maintain system script # Check gw_initiated env var if ($env:gw_initiated -ne 'true') { Write-Log -message "Environment variable gw_initiated is not true." -severity 'WARN' diff --git a/modules/win_scheduled_tasks/files/maintainsystem-hw.ps1 b/modules/win_scheduled_tasks/files/maintainsystem-hw.ps1 index df4824b8a..bd4dc06ec 100644 --- a/modules/win_scheduled_tasks/files/maintainsystem-hw.ps1 +++ b/modules/win_scheduled_tasks/files/maintainsystem-hw.ps1 @@ -349,6 +349,7 @@ function StartWorkerRunner { exit } Start-Service -Name worker-runner + [Environment]::SetEnvironmentVariable('gw_initiated', 'true', 'Machine') } end { Write-Log -message ('{0} :: end - {1:o}' -f $($MyInvocation.MyCommand.Name), (Get-Date).ToUniversalTime()) -severity 'DEBUG' diff --git a/modules/win_scheduled_tasks/manifests/gw_exe_check.pp b/modules/win_scheduled_tasks/manifests/gw_exe_check.pp index 438a7d9fc..55e293d07 100644 --- a/modules/win_scheduled_tasks/manifests/gw_exe_check.pp +++ b/modules/win_scheduled_tasks/manifests/gw_exe_check.pp @@ -17,10 +17,8 @@ arguments => "-executionpolicy bypass -File ${gw_exe_check_ps1}", enabled => true, trigger => [{ - schedule => 'daily', - start_time => '00:00', - minutes_interval => 5, - minutes_duration => 1440, # 24 hours = repeat every 5 minutes all day + schedule => 'boot', + minutes_delay => 16, # Run once, 16 minutes after startup }], user => 'SYSTEM', } From 9d9d9fa6a99c27099b055e547f99c0ecf57054a1 Mon Sep 17 00:00:00 2001 From: Mark Cornmesser Date: Tue, 9 Dec 2025 13:19:09 -0800 Subject: [PATCH 012/105] actually check config --- modules/win_scheduled_tasks/files/self_redeploy_check.ps1 | 2 ++ 1 file changed, 2 insertions(+) diff --git a/modules/win_scheduled_tasks/files/self_redeploy_check.ps1 b/modules/win_scheduled_tasks/files/self_redeploy_check.ps1 index 66407c37d..352a3b3b5 100644 --- a/modules/win_scheduled_tasks/files/self_redeploy_check.ps1 +++ b/modules/win_scheduled_tasks/files/self_redeploy_check.ps1 @@ -279,3 +279,5 @@ function CompareConfig { Write-Log -message ('{0} :: end - {1:o}' -f $($MyInvocation.MyCommand.Name), (Get-Date).ToUniversalTime()) -severity 'DEBUG' } } + +CompareConfig From 2ae6cc4a47da2a64481c532677120dd727ad89d2 Mon Sep 17 00:00:00 2001 From: Mark Cornmesser Date: Tue, 9 Dec 2025 14:29:50 -0800 Subject: [PATCH 013/105] actually check config --- modules/win_scheduled_tasks/manifests/gw_exe_check.pp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/modules/win_scheduled_tasks/manifests/gw_exe_check.pp b/modules/win_scheduled_tasks/manifests/gw_exe_check.pp index 55e293d07..94507dfe5 100644 --- a/modules/win_scheduled_tasks/manifests/gw_exe_check.pp +++ b/modules/win_scheduled_tasks/manifests/gw_exe_check.pp @@ -17,8 +17,8 @@ arguments => "-executionpolicy bypass -File ${gw_exe_check_ps1}", enabled => true, trigger => [{ - schedule => 'boot', - minutes_delay => 16, # Run once, 16 minutes after startup + schedule => 'boot', + delay => 'PT16M', # ISO8601 → wait 16 minutes after startup }], user => 'SYSTEM', } From f6840f2ce53ac9ab4e24bf09438f7abd4004c5b7 Mon Sep 17 00:00:00 2001 From: Mark Cornmesser Date: Tue, 9 Dec 2025 15:43:40 -0800 Subject: [PATCH 014/105] actually check config --- modules/win_scheduled_tasks/manifests/gw_exe_check.pp | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/modules/win_scheduled_tasks/manifests/gw_exe_check.pp b/modules/win_scheduled_tasks/manifests/gw_exe_check.pp index 94507dfe5..305a635fc 100644 --- a/modules/win_scheduled_tasks/manifests/gw_exe_check.pp +++ b/modules/win_scheduled_tasks/manifests/gw_exe_check.pp @@ -17,8 +17,10 @@ arguments => "-executionpolicy bypass -File ${gw_exe_check_ps1}", enabled => true, trigger => [{ - schedule => 'boot', - delay => 'PT16M', # ISO8601 → wait 16 minutes after startup + schedule => 'daily', + start_time => '00:00', + minutes_interval => 30, + minutes_duration => 1440, # 24 hours = repeat every 5 minutes all day }], user => 'SYSTEM', } From a0cb51be3f9c807fdbffedfecfe324a8b202a2da Mon Sep 17 00:00:00 2001 From: Mark Cornmesser Date: Wed, 10 Dec 2025 09:32:46 -0800 Subject: [PATCH 015/105] troubleshooting --- .../win_scheduled_tasks/files/maintainsystem-hw.ps1 | 1 + .../win_scheduled_tasks/files/self_redeploy_check.ps1 | 11 +++++++++-- 2 files changed, 10 insertions(+), 2 deletions(-) diff --git a/modules/win_scheduled_tasks/files/maintainsystem-hw.ps1 b/modules/win_scheduled_tasks/files/maintainsystem-hw.ps1 index bd4dc06ec..8d11732dc 100644 --- a/modules/win_scheduled_tasks/files/maintainsystem-hw.ps1 +++ b/modules/win_scheduled_tasks/files/maintainsystem-hw.ps1 @@ -514,6 +514,7 @@ If ($bootstrap_stage -eq 'complete') { Get-LatestGoogleChrome StartWorkerRunner + Exit-PSSession } else { Write-Log -message ('{0} :: Bootstrap has not completed. EXITING!' -f $($MyInvocation.MyCommand.Name)) -severity 'DEBUG' diff --git a/modules/win_scheduled_tasks/files/self_redeploy_check.ps1 b/modules/win_scheduled_tasks/files/self_redeploy_check.ps1 index 352a3b3b5..4285cf88f 100644 --- a/modules/win_scheduled_tasks/files/self_redeploy_check.ps1 +++ b/modules/win_scheduled_tasks/files/self_redeploy_check.ps1 @@ -143,7 +143,8 @@ function CompareConfig { } } catch { - Write-Log -message "Attempt $($attempt + 1): Failed to fetch YAML - $_" -severity 'WARN' + + Write-Log -message "Attempt $($attempt + 1): Failed to fetch YAML - $yaml_url" -severity 'WARN' Start-Sleep -Seconds $retryDelay $attempt++ } @@ -280,4 +281,10 @@ function CompareConfig { } } -CompareConfig +$bootstrap_stage = (Get-ItemProperty -path "HKLM:\SOFTWARE\Mozilla\ronin_puppet").bootstrap_stage +If ($bootstrap_stage -eq 'complete') { + CompareConfig +else { + Write-Log -message ('{0} :: Bootstrap has not completed. EXITING!' -f $($MyInvocation.MyCommand.Name)) -severity 'DEBUG' + Exit-PSSession +} From c74b22fac3b8f568a96e8257911f91830c777b29 Mon Sep 17 00:00:00 2001 From: Mark Cornmesser Date: Wed, 10 Dec 2025 12:38:21 -0800 Subject: [PATCH 016/105] troubleshooting --- modules/win_scheduled_tasks/files/self_redeploy_check.ps1 | 2 +- .../win_scheduled_tasks/manifests/self_redeploy_check.pp | 6 +++--- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/modules/win_scheduled_tasks/files/self_redeploy_check.ps1 b/modules/win_scheduled_tasks/files/self_redeploy_check.ps1 index 4285cf88f..71d140376 100644 --- a/modules/win_scheduled_tasks/files/self_redeploy_check.ps1 +++ b/modules/win_scheduled_tasks/files/self_redeploy_check.ps1 @@ -284,7 +284,7 @@ function CompareConfig { $bootstrap_stage = (Get-ItemProperty -path "HKLM:\SOFTWARE\Mozilla\ronin_puppet").bootstrap_stage If ($bootstrap_stage -eq 'complete') { CompareConfig -else { +} else { Write-Log -message ('{0} :: Bootstrap has not completed. EXITING!' -f $($MyInvocation.MyCommand.Name)) -severity 'DEBUG' Exit-PSSession } diff --git a/modules/win_scheduled_tasks/manifests/self_redeploy_check.pp b/modules/win_scheduled_tasks/manifests/self_redeploy_check.pp index 909bcc2ed..dd9681a0e 100644 --- a/modules/win_scheduled_tasks/manifests/self_redeploy_check.pp +++ b/modules/win_scheduled_tasks/manifests/self_redeploy_check.pp @@ -5,16 +5,16 @@ class win_scheduled_tasks::self_redeploy_check ( ) { - $gw_exe_check_ps1 = "${facts['custom_win_roninprogramdata']}\\self_redeploy_check.ps1" + $script = "${facts['custom_win_roninprogramdata']}\\self_redeploy_check.ps1" - file { $gw_exe_check_ps1: + file { $script: content => file('win_scheduled_tasks/self_redeploy_check.ps1'), } scheduled_task { 'self_redeploy_check': ensure => 'present', command => "${facts['custom_win_system32']}\\WindowsPowerShell\\v1.0\\powershell.exe", - arguments => "-executionpolicy bypass -File ${gw_exe_check_ps1}", + arguments => "-executionpolicy bypass -File ${script}", enabled => true, trigger => [{ schedule => 'daily', From 780e6665b49d2134042e298fb9a45a8e922e3138 Mon Sep 17 00:00:00 2001 From: Mark Cornmesser Date: Thu, 11 Dec 2025 09:48:02 -0800 Subject: [PATCH 017/105] troubleshooting --- modules/win_scheduled_tasks/files/self_redeploy_check.ps1 | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/modules/win_scheduled_tasks/files/self_redeploy_check.ps1 b/modules/win_scheduled_tasks/files/self_redeploy_check.ps1 index 71d140376..ee83235e2 100644 --- a/modules/win_scheduled_tasks/files/self_redeploy_check.ps1 +++ b/modules/win_scheduled_tasks/files/self_redeploy_check.ps1 @@ -144,7 +144,7 @@ function CompareConfig { } catch { - Write-Log -message "Attempt $($attempt + 1): Failed to fetch YAML - $yaml_url" -severity 'WARN' + Write-Log -message "Attempt $($attempt + 1): Failed to fetch YAML - $_ - $yaml_url" -severity 'WARN' Start-Sleep -Seconds $retryDelay $attempt++ } From 22e77d6125aeb1076133b616f61eba11e59f7482 Mon Sep 17 00:00:00 2001 From: Mark Cornmesser Date: Thu, 11 Dec 2025 10:51:02 -0800 Subject: [PATCH 018/105] troubleshooting --- .../files/BAKself_redeploy_check.ps1 | 290 ++++++++++++++++++ .../files/self_redeploy_check.ps1 | 118 +++++-- 2 files changed, 387 insertions(+), 21 deletions(-) create mode 100644 modules/win_scheduled_tasks/files/BAKself_redeploy_check.ps1 diff --git a/modules/win_scheduled_tasks/files/BAKself_redeploy_check.ps1 b/modules/win_scheduled_tasks/files/BAKself_redeploy_check.ps1 new file mode 100644 index 000000000..ee83235e2 --- /dev/null +++ b/modules/win_scheduled_tasks/files/BAKself_redeploy_check.ps1 @@ -0,0 +1,290 @@ +<# +This Source Code Form is subject to the terms of the Mozilla Public +License, v. 2.0. If a copy of the MPL was not distributed with this +file, You can obtain one at http://mozilla.org/MPL/2.0/. +#> + +function Write-Log { + param ( + [string] $message, + [string] $severity = 'INFO', + [string] $source = 'MaintainSystem', + [string] $logName = 'Application' + ) + if (!([Diagnostics.EventLog]::Exists($logName)) -or !([Diagnostics.EventLog]::SourceExists($source))) { + New-EventLog -LogName $logName -Source $source + } + switch ($severity) { + 'DEBUG' { + $entryType = 'SuccessAudit' + $eventId = 2 + break + } + 'WARN' { + $entryType = 'Warning' + $eventId = 3 + break + } + 'ERROR' { + $entryType = 'Error' + $eventId = 4 + break + } + default { + $entryType = 'Information' + $eventId = 1 + break + } + } + Write-EventLog -LogName $logName -Source $source -EntryType $entryType -Category 0 -EventID $eventId -Message $message + if ([Environment]::UserInteractive) { + $fc = @{ 'Information' = 'White'; 'Error' = 'Red'; 'Warning' = 'DarkYellow'; 'SuccessAudit' = 'DarkGray' }[$entryType] + Write-Host -object $message -ForegroundColor $fc + } +} +function CompareConfig { + param ( + [string]$yaml_url = "https://raw.githubusercontent.com/mozilla-platform-ops/worker-images/refs/heads/main/provisioners/windows/MDC1Windows/pools.yml", + [string]$PAT + ) + + begin { + Write-Log -message ('{0} :: begin - {1:o}' -f $($MyInvocation.MyCommand.Name), (Get-Date).ToUniversalTime()) -severity 'DEBUG' + } + + process { + $yaml = $null + $SETPXE = $false + $yamlHash = $null + $IPAddress = $null + + # ------------------------------- + # Resolve IP + # ------------------------------- + $Ethernet = [System.Net.NetworkInformation.NetworkInterface]::GetAllNetworkInterfaces() | + Where-Object { $_.Name -match "ethernet" } + + try { + $IPAddress = ($Ethernet.GetIPProperties().UnicastAddresses | + Where-Object { $_.Address.AddressFamily -eq [System.Net.Sockets.AddressFamily]::InterNetwork -and $_.Address.IPAddressToString -ne "127.0.0.1" } | + Select-Object -First 1 -ExpandProperty Address).IPAddressToString + } + catch { + try { + $NetshOutput = netsh interface ip show addresses + $IPAddress = ($NetshOutput -match "IP Address" | ForEach-Object { + if ($_ -notmatch "127.0.0.1") { $_ -replace ".*?:\s*", "" } + })[0] + } + catch { + Write-Log -message "Failed to get IP address" -severity 'ERROR' + } + } + + if ($IPAddress) { + Write-Log -message "IP Address: $IPAddress" -severity 'INFO' + } + else { + Write-Log -message "No IP Address could be determined." -severity 'ERROR' + return + } + + # ------------------------------- + # Reverse DNS + # ------------------------------- + try { + $ResolvedName = (Resolve-DnsName -Name $IPAddress -Server "10.48.75.120").NameHost + } + catch { + Write-Log -message "DNS resolution failed." -severity 'ERROR' + return + } + + Write-Log -message "Resolved Name: $ResolvedName" -severity 'INFO' + + $index = $ResolvedName.IndexOf('.') + if ($index -lt 0) { + Write-Log -message "Invalid hostname format." -severity 'ERROR' + return + } + + $worker_node_name = $ResolvedName.Substring(0, $index) + Write-Log -message "Host name set to: $worker_node_name" -severity 'INFO' + + # ------------------------------- + # Registry Values + # ------------------------------- + $localHash = (Get-ItemProperty -Path HKLM:\SOFTWARE\Mozilla\ronin_puppet).GITHASH + $localPool = (Get-ItemProperty -Path HKLM:\SOFTWARE\Mozilla\ronin_puppet).worker_pool_id + + # ------------------------------- + # Load YAML with retry + # ------------------------------- + $maxRetries = 5 + $retryDelay = 10 + $attempt = 0 + $success = $false + + while ($attempt -lt $maxRetries -and -not $success) { + try { + $Headers = @{ + Accept = "application/vnd.github+json" + Authorization = "Bearer $($PAT)" + "X-GitHub-Api-Version" = "2022-11-28" + } + $response = Invoke-WebRequest -Uri $yaml_url -UseBasicParsing -TimeoutSec 10 -ErrorAction Stop -Headers $Headers + $yaml = $response.Content | ConvertFrom-Yaml + + if ($yaml) { + $success = $true + } + else { + throw "YAML content is empty" + } + } + catch { + + Write-Log -message "Attempt $($attempt + 1): Failed to fetch YAML - $_ - $yaml_url" -severity 'WARN' + Start-Sleep -Seconds $retryDelay + $attempt++ + } + } + + if (-not $success) { + Write-Log -message "YAML could not be loaded after $maxRetries attempts." -severity 'ERROR' + $SETPXE = $true + } + + # ------------------------------- + # Find pool entry + # ------------------------------- + $found = $false + if ($yaml) { + foreach ($pool in $yaml.pools) { + foreach ($node in $pool.nodes) { + if ($node -eq $worker_node_name) { + $WorkerPool = $pool.name + $yamlHash = $pool.hash + $yamlImageName = $pool.image + $yamlImageDir = "D:\" + $yamlImageName + $found = $true + break + } + } + if ($found) { break } + } + } + + if (-not $found) { + Write-Log -message "Node name not found in YAML!!" -severity 'ERROR' + $SETPXE = $true + } + + Write-Log -message "=== Configuration Comparison ===" -severity 'INFO' + + # ------------------------------- + # Compare Worker Pool + # ------------------------------- + if ($localPool -eq $WorkerPool) { + Write-Log -message "Worker Pool Match: $WorkerPool" -severity 'INFO' + } + else { + Write-Log -message "Worker Pool MISMATCH!" -severity 'ERROR' + $SETPXE = $true + } + + # ------------------------------- + # Compare Git Hash, including empty or null yamlHash + # ------------------------------- + if ([string]::IsNullOrWhiteSpace($yamlHash)) { + Write-Log -message "YAML hash is missing or invalid. Treating as mismatch." -severity 'ERROR' + $SETPXE = $true + } + elseif ($localHash -ne $yamlHash) { + Write-Log -message "Git Hash MISMATCH!" -severity 'ERROR' + Write-Log -message "Local: $localHash" -severity 'WARN' + Write-Log -message "YAML : $yamlHash" -severity 'WARN' + $SETPXE = $true + } + else { + Write-Log -message "Git Hash Match: $yamlHash" -severity 'INFO' + } + + # ------------------------------- + # Check Image Directory + # ------------------------------- + if (!(Test-Path $yamlImageDir)) { + Write-Log -message "Image Directory MISMATCH! YAML: $yamlImageDir NOT FOUND" -severity 'ERROR' + $SETPXE = $true + } + + # ==================================================================================== + # NEW LOGIC: Evaluate worker-status.json BEFORE reboot or PXE trigger + # ==================================================================================== + if ($SETPXE) { + Write-Log -message "Configuration mismatch detected. Evaluating worker-status.json..." -severity 'WARN' + + $searchPaths = @( + "C:\WINDOWS\SystemTemp", + $env:TMP, + $env:TEMP, + $env:USERPROFILE + ) + + $workerStatus = $null + foreach ($path in $searchPaths) { + if ($null -ne $path) { + $candidate = Join-Path $path "worker-status.json" + if (Test-Path $candidate) { + $workerStatus = $candidate + break + } + } + } + + if (-not $workerStatus) { + Write-Log -message "worker-status.json not found. Rebooting now!" -severity 'ERROR' + Restart-Computer -Force + return + } + + # ------------------------------- + # Parse worker-status.json + # ------------------------------- + try { + $json = Get-Content $workerStatus -Raw | ConvertFrom-Json + } + catch { + Write-Log -message "worker-status.json is unreadable. Rebooting now!" -severity 'ERROR' + Restart-Computer -Force + return + } + + if (($json.currentTaskIds).Count -eq 0) { + Write-Log -message "No active tasks. Rebooting now!" -severity 'WARN' + Restart-Computer -Force + return + } + else { + $task = $json.currentTaskIds[0] + Write-Log -message "Task $task is active. Reboot will occur on next boot." -severity 'INFO' + Set-PXE + return + } + } + + Write-Log -message "SETPXE set to: $SETPXE" -severity 'DEBUG' + } + + end { + Write-Log -message ('{0} :: end - {1:o}' -f $($MyInvocation.MyCommand.Name), (Get-Date).ToUniversalTime()) -severity 'DEBUG' + } +} + +$bootstrap_stage = (Get-ItemProperty -path "HKLM:\SOFTWARE\Mozilla\ronin_puppet").bootstrap_stage +If ($bootstrap_stage -eq 'complete') { + CompareConfig +} else { + Write-Log -message ('{0} :: Bootstrap has not completed. EXITING!' -f $($MyInvocation.MyCommand.Name)) -severity 'DEBUG' + Exit-PSSession +} diff --git a/modules/win_scheduled_tasks/files/self_redeploy_check.ps1 b/modules/win_scheduled_tasks/files/self_redeploy_check.ps1 index ee83235e2..b12354a2f 100644 --- a/modules/win_scheduled_tasks/files/self_redeploy_check.ps1 +++ b/modules/win_scheduled_tasks/files/self_redeploy_check.ps1 @@ -42,6 +42,7 @@ function Write-Log { Write-Host -object $message -ForegroundColor $fc } } + function CompareConfig { param ( [string]$yaml_url = "https://raw.githubusercontent.com/mozilla-platform-ops/worker-images/refs/heads/main/provisioners/windows/MDC1Windows/pools.yml", @@ -114,12 +115,67 @@ function CompareConfig { # ------------------------------- # Registry Values # ------------------------------- - $localHash = (Get-ItemProperty -Path HKLM:\SOFTWARE\Mozilla\ronin_puppet).GITHASH + $localHash = (Get-ItemProperty -Path HKLM:\SOFTWARE\Mozilla\ronin_puppet).GGITHASH $localPool = (Get-ItemProperty -Path HKLM:\SOFTWARE\Mozilla\ronin_puppet).worker_pool_id - # ------------------------------- - # Load YAML with retry - # ------------------------------- + # ====================================================================== + # GitHub Connectivity Diagnostics + # ====================================================================== + try { + $uri = [uri]$yaml_url + $host = $uri.Host + Write-Log -message "GitHub diagnostics for $yaml_url" -severity 'INFO' + Write-Log -message "Parsed host: $host" -severity 'DEBUG' + + # DNS Check + try { + $dns = Resolve-DnsName -Name $host -ErrorAction Stop + $ips = ($dns | Where-Object { $_.IPAddress } | Select-Object -ExpandProperty IPAddress) -join ', ' + Write-Log -message "DNS OK: $host -> $ips" -severity 'INFO' + } + catch { + Write-Log -message "DNS resolution FAILED for $host: $($_.Exception.Message)" -severity 'ERROR' + } + + # ICMP Ping + try { + $pingOk = Test-Connection -ComputerName $host -Count 2 -Quiet -ErrorAction Stop + if ($pingOk) { + Write-Log -message "Ping to $host succeeded." -severity 'INFO' + } + else { + Write-Log -message "Ping to $host FAILED." -severity 'WARN' + } + } + catch { + Write-Log -message "Ping threw exception: $($_.Exception.Message)" -severity 'WARN' + } + + # HEAD Request + try { + $head = Invoke-WebRequest -Uri $yaml_url -Method Head -UseBasicParsing -TimeoutSec 10 -ErrorAction Stop + Write-Log -message "HEAD request OK: HTTP $($head.StatusCode) $($head.StatusDescription)" -severity 'INFO' + } + catch { + $webEx = $_.Exception + $status = $null + $desc = $null + if ($webEx.Response) { + try { + $status = [int]$webEx.Response.StatusCode + $desc = $webEx.Response.StatusDescription + } catch {} + } + Write-Log -message "HEAD request FAILED: HTTP $status $desc - $($webEx.Message)" -severity 'ERROR' + } + } + catch { + Write-Log -message "Diagnostics block failure: $($_.Exception.Message)" -severity 'ERROR' + } + + # ====================================================================== + # Load YAML with retry + detailed logging + # ====================================================================== $maxRetries = 5 $retryDelay = 10 $attempt = 0 @@ -127,24 +183,47 @@ function CompareConfig { while ($attempt -lt $maxRetries -and -not $success) { try { + Write-Log -message "Attempt $($attempt + 1): Fetching YAML from $yaml_url" -severity 'DEBUG' + $Headers = @{ Accept = "application/vnd.github+json" Authorization = "Bearer $($PAT)" "X-GitHub-Api-Version" = "2022-11-28" } - $response = Invoke-WebRequest -Uri $yaml_url -UseBasicParsing -TimeoutSec 10 -ErrorAction Stop -Headers $Headers + + $response = Invoke-WebRequest -Uri $yaml_url -UseBasicParsing -TimeoutSec 10 -Headers $Headers -ErrorAction Stop + + Write-Log -message ("Attempt {0}: HTTP {1} {2}" -f ($attempt + 1), $response.StatusCode, $response.StatusDescription) -severity 'DEBUG' + $yaml = $response.Content | ConvertFrom-Yaml if ($yaml) { $success = $true + Write-Log -message "YAML loaded successfully." -severity 'INFO' } else { - throw "YAML content is empty" + throw "YAML was empty" } } catch { + $webEx = $_.Exception + $status = $null + $desc = $null + if ($webEx.Response) { + try { + $status = [int]$webEx.Response.StatusCode + $desc = $webEx.Response.StatusDescription + } catch {} + } + + Write-Log -message ( + "Attempt {0}: YAML fetch FAILED. HTTP {1} {2}. {3}" -f + ($attempt + 1), + $status, + $desc, + $webEx.Message + ) -severity 'WARN' - Write-Log -message "Attempt $($attempt + 1): Failed to fetch YAML - $_ - $yaml_url" -severity 'WARN' Start-Sleep -Seconds $retryDelay $attempt++ } @@ -194,10 +273,10 @@ function CompareConfig { } # ------------------------------- - # Compare Git Hash, including empty or null yamlHash + # Compare Git Hash # ------------------------------- if ([string]::IsNullOrWhiteSpace($yamlHash)) { - Write-Log -message "YAML hash is missing or invalid. Treating as mismatch." -severity 'ERROR' + Write-Log -message "YAML hash missing → mismatch" -severity 'ERROR' $SETPXE = $true } elseif ($localHash -ne $yamlHash) { @@ -214,15 +293,15 @@ function CompareConfig { # Check Image Directory # ------------------------------- if (!(Test-Path $yamlImageDir)) { - Write-Log -message "Image Directory MISMATCH! YAML: $yamlImageDir NOT FOUND" -severity 'ERROR' + Write-Log -message "Image Directory MISSING: $yamlImageDir" -severity 'ERROR' $SETPXE = $true } - # ==================================================================================== - # NEW LOGIC: Evaluate worker-status.json BEFORE reboot or PXE trigger - # ==================================================================================== + # ====================================================================== + # Worker-status.json pre-reboot logic + # ====================================================================== if ($SETPXE) { - Write-Log -message "Configuration mismatch detected. Evaluating worker-status.json..." -severity 'WARN' + Write-Log -message "Configuration mismatch — evaluating worker-status.json..." -severity 'WARN' $searchPaths = @( "C:\WINDOWS\SystemTemp", @@ -243,31 +322,28 @@ function CompareConfig { } if (-not $workerStatus) { - Write-Log -message "worker-status.json not found. Rebooting now!" -severity 'ERROR' + Write-Log -message "worker-status.json NOT FOUND → immediate reboot" -severity 'ERROR' Restart-Computer -Force return } - # ------------------------------- - # Parse worker-status.json - # ------------------------------- try { $json = Get-Content $workerStatus -Raw | ConvertFrom-Json } catch { - Write-Log -message "worker-status.json is unreadable. Rebooting now!" -severity 'ERROR' + Write-Log -message "worker-status.json unreadable → reboot" -severity 'ERROR' Restart-Computer -Force return } if (($json.currentTaskIds).Count -eq 0) { - Write-Log -message "No active tasks. Rebooting now!" -severity 'WARN' + Write-Log -message "No active tasks → rebooting now." -severity 'WARN' Restart-Computer -Force return } else { $task = $json.currentTaskIds[0] - Write-Log -message "Task $task is active. Reboot will occur on next boot." -severity 'INFO' + Write-Log -message "Active task $task detected — scheduling PXE." -severity 'INFO' Set-PXE return } From b7b3416b4f7bb6f495a0a3d0d68b11a6c1497cc2 Mon Sep 17 00:00:00 2001 From: Mark Cornmesser Date: Thu, 11 Dec 2025 13:12:25 -0800 Subject: [PATCH 019/105] testing From 82d64bd49775253191d584f16ea92210b2d2046c Mon Sep 17 00:00:00 2001 From: Mark Cornmesser Date: Thu, 11 Dec 2025 13:18:03 -0800 Subject: [PATCH 020/105] troubleshooting --- .../files/BAKself_redeploy_check.ps1 | 290 ------------------ .../files/self_redeploy_check.ps1 | 118 ++----- 2 files changed, 21 insertions(+), 387 deletions(-) delete mode 100644 modules/win_scheduled_tasks/files/BAKself_redeploy_check.ps1 diff --git a/modules/win_scheduled_tasks/files/BAKself_redeploy_check.ps1 b/modules/win_scheduled_tasks/files/BAKself_redeploy_check.ps1 deleted file mode 100644 index ee83235e2..000000000 --- a/modules/win_scheduled_tasks/files/BAKself_redeploy_check.ps1 +++ /dev/null @@ -1,290 +0,0 @@ -<# -This Source Code Form is subject to the terms of the Mozilla Public -License, v. 2.0. If a copy of the MPL was not distributed with this -file, You can obtain one at http://mozilla.org/MPL/2.0/. -#> - -function Write-Log { - param ( - [string] $message, - [string] $severity = 'INFO', - [string] $source = 'MaintainSystem', - [string] $logName = 'Application' - ) - if (!([Diagnostics.EventLog]::Exists($logName)) -or !([Diagnostics.EventLog]::SourceExists($source))) { - New-EventLog -LogName $logName -Source $source - } - switch ($severity) { - 'DEBUG' { - $entryType = 'SuccessAudit' - $eventId = 2 - break - } - 'WARN' { - $entryType = 'Warning' - $eventId = 3 - break - } - 'ERROR' { - $entryType = 'Error' - $eventId = 4 - break - } - default { - $entryType = 'Information' - $eventId = 1 - break - } - } - Write-EventLog -LogName $logName -Source $source -EntryType $entryType -Category 0 -EventID $eventId -Message $message - if ([Environment]::UserInteractive) { - $fc = @{ 'Information' = 'White'; 'Error' = 'Red'; 'Warning' = 'DarkYellow'; 'SuccessAudit' = 'DarkGray' }[$entryType] - Write-Host -object $message -ForegroundColor $fc - } -} -function CompareConfig { - param ( - [string]$yaml_url = "https://raw.githubusercontent.com/mozilla-platform-ops/worker-images/refs/heads/main/provisioners/windows/MDC1Windows/pools.yml", - [string]$PAT - ) - - begin { - Write-Log -message ('{0} :: begin - {1:o}' -f $($MyInvocation.MyCommand.Name), (Get-Date).ToUniversalTime()) -severity 'DEBUG' - } - - process { - $yaml = $null - $SETPXE = $false - $yamlHash = $null - $IPAddress = $null - - # ------------------------------- - # Resolve IP - # ------------------------------- - $Ethernet = [System.Net.NetworkInformation.NetworkInterface]::GetAllNetworkInterfaces() | - Where-Object { $_.Name -match "ethernet" } - - try { - $IPAddress = ($Ethernet.GetIPProperties().UnicastAddresses | - Where-Object { $_.Address.AddressFamily -eq [System.Net.Sockets.AddressFamily]::InterNetwork -and $_.Address.IPAddressToString -ne "127.0.0.1" } | - Select-Object -First 1 -ExpandProperty Address).IPAddressToString - } - catch { - try { - $NetshOutput = netsh interface ip show addresses - $IPAddress = ($NetshOutput -match "IP Address" | ForEach-Object { - if ($_ -notmatch "127.0.0.1") { $_ -replace ".*?:\s*", "" } - })[0] - } - catch { - Write-Log -message "Failed to get IP address" -severity 'ERROR' - } - } - - if ($IPAddress) { - Write-Log -message "IP Address: $IPAddress" -severity 'INFO' - } - else { - Write-Log -message "No IP Address could be determined." -severity 'ERROR' - return - } - - # ------------------------------- - # Reverse DNS - # ------------------------------- - try { - $ResolvedName = (Resolve-DnsName -Name $IPAddress -Server "10.48.75.120").NameHost - } - catch { - Write-Log -message "DNS resolution failed." -severity 'ERROR' - return - } - - Write-Log -message "Resolved Name: $ResolvedName" -severity 'INFO' - - $index = $ResolvedName.IndexOf('.') - if ($index -lt 0) { - Write-Log -message "Invalid hostname format." -severity 'ERROR' - return - } - - $worker_node_name = $ResolvedName.Substring(0, $index) - Write-Log -message "Host name set to: $worker_node_name" -severity 'INFO' - - # ------------------------------- - # Registry Values - # ------------------------------- - $localHash = (Get-ItemProperty -Path HKLM:\SOFTWARE\Mozilla\ronin_puppet).GITHASH - $localPool = (Get-ItemProperty -Path HKLM:\SOFTWARE\Mozilla\ronin_puppet).worker_pool_id - - # ------------------------------- - # Load YAML with retry - # ------------------------------- - $maxRetries = 5 - $retryDelay = 10 - $attempt = 0 - $success = $false - - while ($attempt -lt $maxRetries -and -not $success) { - try { - $Headers = @{ - Accept = "application/vnd.github+json" - Authorization = "Bearer $($PAT)" - "X-GitHub-Api-Version" = "2022-11-28" - } - $response = Invoke-WebRequest -Uri $yaml_url -UseBasicParsing -TimeoutSec 10 -ErrorAction Stop -Headers $Headers - $yaml = $response.Content | ConvertFrom-Yaml - - if ($yaml) { - $success = $true - } - else { - throw "YAML content is empty" - } - } - catch { - - Write-Log -message "Attempt $($attempt + 1): Failed to fetch YAML - $_ - $yaml_url" -severity 'WARN' - Start-Sleep -Seconds $retryDelay - $attempt++ - } - } - - if (-not $success) { - Write-Log -message "YAML could not be loaded after $maxRetries attempts." -severity 'ERROR' - $SETPXE = $true - } - - # ------------------------------- - # Find pool entry - # ------------------------------- - $found = $false - if ($yaml) { - foreach ($pool in $yaml.pools) { - foreach ($node in $pool.nodes) { - if ($node -eq $worker_node_name) { - $WorkerPool = $pool.name - $yamlHash = $pool.hash - $yamlImageName = $pool.image - $yamlImageDir = "D:\" + $yamlImageName - $found = $true - break - } - } - if ($found) { break } - } - } - - if (-not $found) { - Write-Log -message "Node name not found in YAML!!" -severity 'ERROR' - $SETPXE = $true - } - - Write-Log -message "=== Configuration Comparison ===" -severity 'INFO' - - # ------------------------------- - # Compare Worker Pool - # ------------------------------- - if ($localPool -eq $WorkerPool) { - Write-Log -message "Worker Pool Match: $WorkerPool" -severity 'INFO' - } - else { - Write-Log -message "Worker Pool MISMATCH!" -severity 'ERROR' - $SETPXE = $true - } - - # ------------------------------- - # Compare Git Hash, including empty or null yamlHash - # ------------------------------- - if ([string]::IsNullOrWhiteSpace($yamlHash)) { - Write-Log -message "YAML hash is missing or invalid. Treating as mismatch." -severity 'ERROR' - $SETPXE = $true - } - elseif ($localHash -ne $yamlHash) { - Write-Log -message "Git Hash MISMATCH!" -severity 'ERROR' - Write-Log -message "Local: $localHash" -severity 'WARN' - Write-Log -message "YAML : $yamlHash" -severity 'WARN' - $SETPXE = $true - } - else { - Write-Log -message "Git Hash Match: $yamlHash" -severity 'INFO' - } - - # ------------------------------- - # Check Image Directory - # ------------------------------- - if (!(Test-Path $yamlImageDir)) { - Write-Log -message "Image Directory MISMATCH! YAML: $yamlImageDir NOT FOUND" -severity 'ERROR' - $SETPXE = $true - } - - # ==================================================================================== - # NEW LOGIC: Evaluate worker-status.json BEFORE reboot or PXE trigger - # ==================================================================================== - if ($SETPXE) { - Write-Log -message "Configuration mismatch detected. Evaluating worker-status.json..." -severity 'WARN' - - $searchPaths = @( - "C:\WINDOWS\SystemTemp", - $env:TMP, - $env:TEMP, - $env:USERPROFILE - ) - - $workerStatus = $null - foreach ($path in $searchPaths) { - if ($null -ne $path) { - $candidate = Join-Path $path "worker-status.json" - if (Test-Path $candidate) { - $workerStatus = $candidate - break - } - } - } - - if (-not $workerStatus) { - Write-Log -message "worker-status.json not found. Rebooting now!" -severity 'ERROR' - Restart-Computer -Force - return - } - - # ------------------------------- - # Parse worker-status.json - # ------------------------------- - try { - $json = Get-Content $workerStatus -Raw | ConvertFrom-Json - } - catch { - Write-Log -message "worker-status.json is unreadable. Rebooting now!" -severity 'ERROR' - Restart-Computer -Force - return - } - - if (($json.currentTaskIds).Count -eq 0) { - Write-Log -message "No active tasks. Rebooting now!" -severity 'WARN' - Restart-Computer -Force - return - } - else { - $task = $json.currentTaskIds[0] - Write-Log -message "Task $task is active. Reboot will occur on next boot." -severity 'INFO' - Set-PXE - return - } - } - - Write-Log -message "SETPXE set to: $SETPXE" -severity 'DEBUG' - } - - end { - Write-Log -message ('{0} :: end - {1:o}' -f $($MyInvocation.MyCommand.Name), (Get-Date).ToUniversalTime()) -severity 'DEBUG' - } -} - -$bootstrap_stage = (Get-ItemProperty -path "HKLM:\SOFTWARE\Mozilla\ronin_puppet").bootstrap_stage -If ($bootstrap_stage -eq 'complete') { - CompareConfig -} else { - Write-Log -message ('{0} :: Bootstrap has not completed. EXITING!' -f $($MyInvocation.MyCommand.Name)) -severity 'DEBUG' - Exit-PSSession -} diff --git a/modules/win_scheduled_tasks/files/self_redeploy_check.ps1 b/modules/win_scheduled_tasks/files/self_redeploy_check.ps1 index b12354a2f..ee83235e2 100644 --- a/modules/win_scheduled_tasks/files/self_redeploy_check.ps1 +++ b/modules/win_scheduled_tasks/files/self_redeploy_check.ps1 @@ -42,7 +42,6 @@ function Write-Log { Write-Host -object $message -ForegroundColor $fc } } - function CompareConfig { param ( [string]$yaml_url = "https://raw.githubusercontent.com/mozilla-platform-ops/worker-images/refs/heads/main/provisioners/windows/MDC1Windows/pools.yml", @@ -115,67 +114,12 @@ function CompareConfig { # ------------------------------- # Registry Values # ------------------------------- - $localHash = (Get-ItemProperty -Path HKLM:\SOFTWARE\Mozilla\ronin_puppet).GGITHASH + $localHash = (Get-ItemProperty -Path HKLM:\SOFTWARE\Mozilla\ronin_puppet).GITHASH $localPool = (Get-ItemProperty -Path HKLM:\SOFTWARE\Mozilla\ronin_puppet).worker_pool_id - # ====================================================================== - # GitHub Connectivity Diagnostics - # ====================================================================== - try { - $uri = [uri]$yaml_url - $host = $uri.Host - Write-Log -message "GitHub diagnostics for $yaml_url" -severity 'INFO' - Write-Log -message "Parsed host: $host" -severity 'DEBUG' - - # DNS Check - try { - $dns = Resolve-DnsName -Name $host -ErrorAction Stop - $ips = ($dns | Where-Object { $_.IPAddress } | Select-Object -ExpandProperty IPAddress) -join ', ' - Write-Log -message "DNS OK: $host -> $ips" -severity 'INFO' - } - catch { - Write-Log -message "DNS resolution FAILED for $host: $($_.Exception.Message)" -severity 'ERROR' - } - - # ICMP Ping - try { - $pingOk = Test-Connection -ComputerName $host -Count 2 -Quiet -ErrorAction Stop - if ($pingOk) { - Write-Log -message "Ping to $host succeeded." -severity 'INFO' - } - else { - Write-Log -message "Ping to $host FAILED." -severity 'WARN' - } - } - catch { - Write-Log -message "Ping threw exception: $($_.Exception.Message)" -severity 'WARN' - } - - # HEAD Request - try { - $head = Invoke-WebRequest -Uri $yaml_url -Method Head -UseBasicParsing -TimeoutSec 10 -ErrorAction Stop - Write-Log -message "HEAD request OK: HTTP $($head.StatusCode) $($head.StatusDescription)" -severity 'INFO' - } - catch { - $webEx = $_.Exception - $status = $null - $desc = $null - if ($webEx.Response) { - try { - $status = [int]$webEx.Response.StatusCode - $desc = $webEx.Response.StatusDescription - } catch {} - } - Write-Log -message "HEAD request FAILED: HTTP $status $desc - $($webEx.Message)" -severity 'ERROR' - } - } - catch { - Write-Log -message "Diagnostics block failure: $($_.Exception.Message)" -severity 'ERROR' - } - - # ====================================================================== - # Load YAML with retry + detailed logging - # ====================================================================== + # ------------------------------- + # Load YAML with retry + # ------------------------------- $maxRetries = 5 $retryDelay = 10 $attempt = 0 @@ -183,47 +127,24 @@ function CompareConfig { while ($attempt -lt $maxRetries -and -not $success) { try { - Write-Log -message "Attempt $($attempt + 1): Fetching YAML from $yaml_url" -severity 'DEBUG' - $Headers = @{ Accept = "application/vnd.github+json" Authorization = "Bearer $($PAT)" "X-GitHub-Api-Version" = "2022-11-28" } - - $response = Invoke-WebRequest -Uri $yaml_url -UseBasicParsing -TimeoutSec 10 -Headers $Headers -ErrorAction Stop - - Write-Log -message ("Attempt {0}: HTTP {1} {2}" -f ($attempt + 1), $response.StatusCode, $response.StatusDescription) -severity 'DEBUG' - + $response = Invoke-WebRequest -Uri $yaml_url -UseBasicParsing -TimeoutSec 10 -ErrorAction Stop -Headers $Headers $yaml = $response.Content | ConvertFrom-Yaml if ($yaml) { $success = $true - Write-Log -message "YAML loaded successfully." -severity 'INFO' } else { - throw "YAML was empty" + throw "YAML content is empty" } } catch { - $webEx = $_.Exception - $status = $null - $desc = $null - if ($webEx.Response) { - try { - $status = [int]$webEx.Response.StatusCode - $desc = $webEx.Response.StatusDescription - } catch {} - } - - Write-Log -message ( - "Attempt {0}: YAML fetch FAILED. HTTP {1} {2}. {3}" -f - ($attempt + 1), - $status, - $desc, - $webEx.Message - ) -severity 'WARN' + Write-Log -message "Attempt $($attempt + 1): Failed to fetch YAML - $_ - $yaml_url" -severity 'WARN' Start-Sleep -Seconds $retryDelay $attempt++ } @@ -273,10 +194,10 @@ function CompareConfig { } # ------------------------------- - # Compare Git Hash + # Compare Git Hash, including empty or null yamlHash # ------------------------------- if ([string]::IsNullOrWhiteSpace($yamlHash)) { - Write-Log -message "YAML hash missing → mismatch" -severity 'ERROR' + Write-Log -message "YAML hash is missing or invalid. Treating as mismatch." -severity 'ERROR' $SETPXE = $true } elseif ($localHash -ne $yamlHash) { @@ -293,15 +214,15 @@ function CompareConfig { # Check Image Directory # ------------------------------- if (!(Test-Path $yamlImageDir)) { - Write-Log -message "Image Directory MISSING: $yamlImageDir" -severity 'ERROR' + Write-Log -message "Image Directory MISMATCH! YAML: $yamlImageDir NOT FOUND" -severity 'ERROR' $SETPXE = $true } - # ====================================================================== - # Worker-status.json pre-reboot logic - # ====================================================================== + # ==================================================================================== + # NEW LOGIC: Evaluate worker-status.json BEFORE reboot or PXE trigger + # ==================================================================================== if ($SETPXE) { - Write-Log -message "Configuration mismatch — evaluating worker-status.json..." -severity 'WARN' + Write-Log -message "Configuration mismatch detected. Evaluating worker-status.json..." -severity 'WARN' $searchPaths = @( "C:\WINDOWS\SystemTemp", @@ -322,28 +243,31 @@ function CompareConfig { } if (-not $workerStatus) { - Write-Log -message "worker-status.json NOT FOUND → immediate reboot" -severity 'ERROR' + Write-Log -message "worker-status.json not found. Rebooting now!" -severity 'ERROR' Restart-Computer -Force return } + # ------------------------------- + # Parse worker-status.json + # ------------------------------- try { $json = Get-Content $workerStatus -Raw | ConvertFrom-Json } catch { - Write-Log -message "worker-status.json unreadable → reboot" -severity 'ERROR' + Write-Log -message "worker-status.json is unreadable. Rebooting now!" -severity 'ERROR' Restart-Computer -Force return } if (($json.currentTaskIds).Count -eq 0) { - Write-Log -message "No active tasks → rebooting now." -severity 'WARN' + Write-Log -message "No active tasks. Rebooting now!" -severity 'WARN' Restart-Computer -Force return } else { $task = $json.currentTaskIds[0] - Write-Log -message "Active task $task detected — scheduling PXE." -severity 'INFO' + Write-Log -message "Task $task is active. Reboot will occur on next boot." -severity 'INFO' Set-PXE return } From 0ed34e3cb457e288ada3aff56314549773ba99f4 Mon Sep 17 00:00:00 2001 From: Mark Cornmesser Date: Thu, 11 Dec 2025 15:02:43 -0800 Subject: [PATCH 021/105] troubleshooting --- .../files/self_redeploy_check.ps1 | 90 +++++++++++-------- 1 file changed, 54 insertions(+), 36 deletions(-) diff --git a/modules/win_scheduled_tasks/files/self_redeploy_check.ps1 b/modules/win_scheduled_tasks/files/self_redeploy_check.ps1 index ee83235e2..bcbb14fe3 100644 --- a/modules/win_scheduled_tasks/files/self_redeploy_check.ps1 +++ b/modules/win_scheduled_tasks/files/self_redeploy_check.ps1 @@ -42,6 +42,55 @@ function Write-Log { Write-Host -object $message -ForegroundColor $fc } } +function Invoke-DownloadWithRetryGithub { + Param( + [Parameter(Mandatory)] [string] $Url, + [Alias("Destination")] [string] $Path, + [string] $PAT + ) + if (-not $Path) { + $invalidChars = [IO.Path]::GetInvalidFileNameChars() -join '' + $re = "[{0}]" -f [RegEx]::Escape($invalidChars) + $fileName = [IO.Path]::GetFileName($Url) -replace $re + if ([String]::IsNullOrEmpty($fileName)) { $fileName = [System.IO.Path]::GetRandomFileName() } + $Path = Join-Path -Path "${env:Temp}" -ChildPath $fileName + } + Write-Host "Downloading package from $Url to $Path..." + $interval = 30 + $downloadStartTime = Get-Date + for ($retries = 20; $retries -gt 0; $retries--) { + try { + $attemptStartTime = Get-Date + $Headers = @{ + Accept = "application/vnd.github+json" + Authorization = "Bearer $($PAT)" + "X-GitHub-Api-Version" = "2022-11-28" + } + $response = Invoke-WebRequest -Uri $Url -Headers $Headers -OutFile $Path + $attemptSeconds = [math]::Round(($(Get-Date) - $attemptStartTime).TotalSeconds, 2) + Write-Host "Package downloaded in $attemptSeconds seconds" + Write-Host "Status: $($response.statuscode)" + break + } catch { + $attemptSeconds = [math]::Round(($(Get-Date) - $attemptStartTime).TotalSeconds, 2) + Write-Warning "Package download failed in $attemptSeconds seconds" + Write-Host "Status: $($response.statuscode)" + Write-Warning $_.Exception.Message + if ($_.Exception.InnerException.Response.StatusCode -eq [System.Net.HttpStatusCode]::NotFound) { + Write-Warning "Request returned 404 Not Found. Aborting download." + $retries = 0 + } + } + if ($retries -eq 0) { + $totalSeconds = [math]::Round(($(Get-Date) - $downloadStartTime).TotalSeconds, 2) + throw "Package download failed after $totalSeconds seconds" + } + Write-Warning "Waiting $interval seconds before retrying (retries left: $retries)..." + Start-Sleep -Seconds $interval + } + return $Path +} + function CompareConfig { param ( [string]$yaml_url = "https://raw.githubusercontent.com/mozilla-platform-ops/worker-images/refs/heads/main/provisioners/windows/MDC1Windows/pools.yml", @@ -117,42 +166,11 @@ function CompareConfig { $localHash = (Get-ItemProperty -Path HKLM:\SOFTWARE\Mozilla\ronin_puppet).GITHASH $localPool = (Get-ItemProperty -Path HKLM:\SOFTWARE\Mozilla\ronin_puppet).worker_pool_id - # ------------------------------- - # Load YAML with retry - # ------------------------------- - $maxRetries = 5 - $retryDelay = 10 - $attempt = 0 - $success = $false - - while ($attempt -lt $maxRetries -and -not $success) { - try { - $Headers = @{ - Accept = "application/vnd.github+json" - Authorization = "Bearer $($PAT)" - "X-GitHub-Api-Version" = "2022-11-28" - } - $response = Invoke-WebRequest -Uri $yaml_url -UseBasicParsing -TimeoutSec 10 -ErrorAction Stop -Headers $Headers - $yaml = $response.Content | ConvertFrom-Yaml - - if ($yaml) { - $success = $true - } - else { - throw "YAML content is empty" - } - } - catch { - - Write-Log -message "Attempt $($attempt + 1): Failed to fetch YAML - $_ - $yaml_url" -severity 'WARN' - Start-Sleep -Seconds $retryDelay - $attempt++ - } - } - - if (-not $success) { - Write-Log -message "YAML could not be loaded after $maxRetries attempts." -severity 'ERROR' - $SETPXE = $true + if (-not (Invoke-DownloadWithRetryGithub @splat)) { + Write-Log -message ('{0} :: YAML download failed after retries. PXE rebooting.' -f $MyInvocation.MyCommand.Name) -severity 'ERROR' + Set-PXE + Restart-Computer -Force + return } # ------------------------------- From 3371c846da07a546d912aad38327f78d45f137f1 Mon Sep 17 00:00:00 2001 From: Mark Cornmesser Date: Thu, 11 Dec 2025 15:51:44 -0800 Subject: [PATCH 022/105] troubleshooting --- modules/win_scheduled_tasks/files/self_redeploy_check.ps1 | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/modules/win_scheduled_tasks/files/self_redeploy_check.ps1 b/modules/win_scheduled_tasks/files/self_redeploy_check.ps1 index bcbb14fe3..2607401ca 100644 --- a/modules/win_scheduled_tasks/files/self_redeploy_check.ps1 +++ b/modules/win_scheduled_tasks/files/self_redeploy_check.ps1 @@ -195,7 +195,7 @@ function CompareConfig { if (-not $found) { Write-Log -message "Node name not found in YAML!!" -severity 'ERROR' - $SETPXE = $true + #$SETPXE = $true } Write-Log -message "=== Configuration Comparison ===" -severity 'INFO' @@ -208,7 +208,7 @@ function CompareConfig { } else { Write-Log -message "Worker Pool MISMATCH!" -severity 'ERROR' - $SETPXE = $true + #$SETPXE = $true } # ------------------------------- From c0b84235fc6daafae09b6d0ef742d2f8871eb261 Mon Sep 17 00:00:00 2001 From: Mark Cornmesser Date: Fri, 12 Dec 2025 11:08:01 -0800 Subject: [PATCH 023/105] troubleshooting --- .../files/self_redeploy_check.ps1 | 16 ++++++++++++++++ 1 file changed, 16 insertions(+) diff --git a/modules/win_scheduled_tasks/files/self_redeploy_check.ps1 b/modules/win_scheduled_tasks/files/self_redeploy_check.ps1 index 2607401ca..2ed562efe 100644 --- a/modules/win_scheduled_tasks/files/self_redeploy_check.ps1 +++ b/modules/win_scheduled_tasks/files/self_redeploy_check.ps1 @@ -166,6 +166,22 @@ function CompareConfig { $localHash = (Get-ItemProperty -Path HKLM:\SOFTWARE\Mozilla\ronin_puppet).GITHASH $localPool = (Get-ItemProperty -Path HKLM:\SOFTWARE\Mozilla\ronin_puppet).worker_pool_id + $patFile = "D:\Secrets\pat.txt" + if (-not (Test-Path $patFile)) { + Write-Log -message ('{0} :: PAT file missing: {1}' -f $MyInvocation.MyCommand.Name, $patFile) -severity 'ERROR' + Set-PXE + Restart-Computer -Force + return + } + + $PAT = Get-Content $patFile -ErrorAction Stop + + $splat = @{ + Url = $yaml_url + Path = $tempYamlPath + PAT = $PAT + } + if (-not (Invoke-DownloadWithRetryGithub @splat)) { Write-Log -message ('{0} :: YAML download failed after retries. PXE rebooting.' -f $MyInvocation.MyCommand.Name) -severity 'ERROR' Set-PXE From e5ca7220e1c3a66186929f94e09bf998170a84d4 Mon Sep 17 00:00:00 2001 From: Mark Cornmesser Date: Fri, 12 Dec 2025 13:02:34 -0800 Subject: [PATCH 024/105] troubleshooting --- .../win_scheduled_tasks/files/self_redeploy_check.ps1 | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/modules/win_scheduled_tasks/files/self_redeploy_check.ps1 b/modules/win_scheduled_tasks/files/self_redeploy_check.ps1 index 2ed562efe..55c5a06fd 100644 --- a/modules/win_scheduled_tasks/files/self_redeploy_check.ps1 +++ b/modules/win_scheduled_tasks/files/self_redeploy_check.ps1 @@ -174,6 +174,7 @@ function CompareConfig { return } + $tempYamlPath = "$env:TEMP\pools.yml" $PAT = Get-Content $patFile -ErrorAction Stop $splat = @{ @@ -189,6 +190,16 @@ function CompareConfig { return } + try { + $yaml = Get-Content $tempYamlPath -Raw | ConvertFrom-Yaml + } + catch { + Write-Log -message ('{0} :: YAML parsing failed: {1}' -f $MyInvocation.MyCommand.Name, $_) -severity 'ERROR' + Set-PXE + Restart-Computer -Force + return + } + # ------------------------------- # Find pool entry # ------------------------------- From 65cc25b10a50ab6e93e721822f56a38c2dd82af5 Mon Sep 17 00:00:00 2001 From: Mark Cornmesser Date: Fri, 12 Dec 2025 13:14:46 -0800 Subject: [PATCH 025/105] troubleshooting --- .../files/self_redeploy_check.ps1 | 61 ++++++++++++++++++- 1 file changed, 58 insertions(+), 3 deletions(-) diff --git a/modules/win_scheduled_tasks/files/self_redeploy_check.ps1 b/modules/win_scheduled_tasks/files/self_redeploy_check.ps1 index 55c5a06fd..2a7acc384 100644 --- a/modules/win_scheduled_tasks/files/self_redeploy_check.ps1 +++ b/modules/win_scheduled_tasks/files/self_redeploy_check.ps1 @@ -91,6 +91,41 @@ function Invoke-DownloadWithRetryGithub { return $Path } +# ------------------------------------------------------------------- +# Persistent PXE Pending Flag +# ------------------------------------------------------------------- +function Set-PXEPendingFlag { + param([switch]$Clear) + + $regPath = "HKLM:\SOFTWARE\Mozilla\PXE" + $name = "PendingPXE" + + if ($Clear) { + if (Test-Path $regPath) { + Remove-ItemProperty -Path $regPath -Name $name -ErrorAction SilentlyContinue + } + return + } + + if (-not (Test-Path $regPath)) { + New-Item -Path $regPath -Force | Out-Null + } + + New-ItemProperty -Path $regPath -Name $name -Value "1" -PropertyType String -Force | Out-Null +} + +function Get-PXEPendingFlag { + $regPath = "HKLM:\SOFTWARE\Mozilla\PXE" + $name = "PendingPXE" + + if (Test-Path "$regPath\$name") { return $true } + return $false +} + + +# ------------------------------------------------------------------- +# CompareConfig +# ------------------------------------------------------------------- function CompareConfig { param ( [string]$yaml_url = "https://raw.githubusercontent.com/mozilla-platform-ops/worker-images/refs/heads/main/provisioners/windows/MDC1Windows/pools.yml", @@ -99,6 +134,11 @@ function CompareConfig { begin { Write-Log -message ('{0} :: begin - {1:o}' -f $($MyInvocation.MyCommand.Name), (Get-Date).ToUniversalTime()) -severity 'DEBUG' + + # Detect previous deferral due to active task + if (Get-PXEPendingFlag) { + Write-Log -message "PXE/Reboot pending task completion from previous run." -severity 'INFO' + } } process { @@ -170,6 +210,7 @@ function CompareConfig { if (-not (Test-Path $patFile)) { Write-Log -message ('{0} :: PAT file missing: {1}' -f $MyInvocation.MyCommand.Name, $patFile) -severity 'ERROR' Set-PXE + Set-PXEPendingFlag -Clear Restart-Computer -Force return } @@ -186,6 +227,7 @@ function CompareConfig { if (-not (Invoke-DownloadWithRetryGithub @splat)) { Write-Log -message ('{0} :: YAML download failed after retries. PXE rebooting.' -f $MyInvocation.MyCommand.Name) -severity 'ERROR' Set-PXE + Set-PXEPendingFlag -Clear Restart-Computer -Force return } @@ -196,6 +238,7 @@ function CompareConfig { catch { Write-Log -message ('{0} :: YAML parsing failed: {1}' -f $MyInvocation.MyCommand.Name, $_) -severity 'ERROR' Set-PXE + Set-PXEPendingFlag -Clear Restart-Computer -Force return } @@ -222,7 +265,7 @@ function CompareConfig { if (-not $found) { Write-Log -message "Node name not found in YAML!!" -severity 'ERROR' - #$SETPXE = $true + # $SETPXE = $true } Write-Log -message "=== Configuration Comparison ===" -severity 'INFO' @@ -239,7 +282,7 @@ function CompareConfig { } # ------------------------------- - # Compare Git Hash, including empty or null yamlHash + # Compare Git Hash # ------------------------------- if ([string]::IsNullOrWhiteSpace($yamlHash)) { Write-Log -message "YAML hash is missing or invalid. Treating as mismatch." -severity 'ERROR' @@ -267,6 +310,7 @@ function CompareConfig { # NEW LOGIC: Evaluate worker-status.json BEFORE reboot or PXE trigger # ==================================================================================== if ($SETPXE) { + Write-Log -message "Configuration mismatch detected. Evaluating worker-status.json..." -severity 'WARN' $searchPaths = @( @@ -289,6 +333,7 @@ function CompareConfig { if (-not $workerStatus) { Write-Log -message "worker-status.json not found. Rebooting now!" -severity 'ERROR' + Set-PXEPendingFlag -Clear Restart-Computer -Force return } @@ -301,18 +346,28 @@ function CompareConfig { } catch { Write-Log -message "worker-status.json is unreadable. Rebooting now!" -severity 'ERROR' + Set-PXEPendingFlag -Clear Restart-Computer -Force return } + # ------------------------------- + # ACTIVE TASK HANDLING + FLAGGING + # ------------------------------- if (($json.currentTaskIds).Count -eq 0) { Write-Log -message "No active tasks. Rebooting now!" -severity 'WARN' + Set-PXEPendingFlag -Clear Restart-Computer -Force return } else { $task = $json.currentTaskIds[0] - Write-Log -message "Task $task is active. Reboot will occur on next boot." -severity 'INFO' + Write-Log -message "Task $task is active. PXE/Reboot deferred until task completion." -severity 'INFO' + + # Record pending reboot/PXE + Set-PXEPendingFlag + + # Prepare PXE boot Set-PXE return } From 96902ee90b6aa65ba1fc8a131a408220332f8ee1 Mon Sep 17 00:00:00 2001 From: Mark Cornmesser Date: Fri, 12 Dec 2025 14:37:53 -0800 Subject: [PATCH 026/105] testing From 1de72991504fafc0671ddc826069febcbcf8c178 Mon Sep 17 00:00:00 2001 From: Mark Cornmesser Date: Mon, 15 Dec 2025 10:32:06 -0800 Subject: [PATCH 027/105] test disabling appx packages --- .../roles_profiles/manifests/profiles/disable_services.pp | 2 +- .../manifests/roles/win116424h2hwrelops1213.pp | 6 ++++-- 2 files changed, 5 insertions(+), 3 deletions(-) diff --git a/modules/roles_profiles/manifests/profiles/disable_services.pp b/modules/roles_profiles/manifests/profiles/disable_services.pp index 29003d161..d75c8a231 100644 --- a/modules/roles_profiles/manifests/profiles/disable_services.pp +++ b/modules/roles_profiles/manifests/profiles/disable_services.pp @@ -42,7 +42,7 @@ ## Let's Uninstall Appx Packages ## Taken from https://github.com/The-Virtual-Desktop-Team/Virtual-Desktop-Optimization-Tool ## Bug 1913499 https://bugzilla.mozilla.org/show_bug.cgi?id=1913499 - #include win_disable_services::uninstall_appx_packages + include win_disable_services::uninstall_appx_packages if ($facts['custom_win_location'] == 'azure') { include win_scheduled_tasks::kill_local_clipboard } diff --git a/modules/roles_profiles/manifests/roles/win116424h2hwrelops1213.pp b/modules/roles_profiles/manifests/roles/win116424h2hwrelops1213.pp index c4c34b649..f153a6c6f 100644 --- a/modules/roles_profiles/manifests/roles/win116424h2hwrelops1213.pp +++ b/modules/roles_profiles/manifests/roles/win116424h2hwrelops1213.pp @@ -1,6 +1,6 @@ class roles_profiles::roles::win116424h2hwrelops1213 { include roles_profiles::profiles::chocolatey - # Install before Widnows Updates is disabled. + ## Install before Widnows Updates is disabled. include roles_profiles::profiles::microsoft_tools include roles_profiles::profiles::ssh # System @@ -21,6 +21,7 @@ # Adminstration include roles_profiles::profiles::logging + include roles_profiles::profiles::mercurial include roles_profiles::profiles::nuc_management #include roles_profiles::profiles::vnc @@ -28,7 +29,8 @@ include roles_profiles::profiles::git include roles_profiles::profiles::mozilla_build include roles_profiles::profiles::mozilla_maintenance_service - include roles_profiles::profiles::windows_generic_worker_standalone include roles_profiles::profiles::windows_datacenter_administrator include roles_profiles::profiles::google_chrome + #include roles_profiles::profiles::windows_generic_worker_standalone + include roles_profiles::profiles::windows_worker_runner } From 0df29623e16207eaaeb23c43cc024b359bd6e4df Mon Sep 17 00:00:00 2001 From: Mark Cornmesser Date: Mon, 15 Dec 2025 13:01:47 -0800 Subject: [PATCH 028/105] test disabling appx packages --- .../files/appxpackages/uninstall.ps1 | 557 ++++++++++-------- 1 file changed, 304 insertions(+), 253 deletions(-) diff --git a/modules/win_disable_services/files/appxpackages/uninstall.ps1 b/modules/win_disable_services/files/appxpackages/uninstall.ps1 index 8cdbf6742..4778d3e8e 100644 --- a/modules/win_disable_services/files/appxpackages/uninstall.ps1 +++ b/modules/win_disable_services/files/appxpackages/uninstall.ps1 @@ -1,269 +1,320 @@ $apps = @{ - "Bing Search" = @{ - "VDIState" = "Unchanged" - "URL" = "https://apps.microsoft.com/detail/9nzbf4gt040c" - "Description" = "Web Search from Microsoft Bing provides web results and answers in Windows Search" - } - "Clipchamp.Clipchamp" = @{ - "VDIState" = "Unchanged" - "URL" = "https://apps.microsoft.com/detail/9p1j8s7ccwwt?hl=en-us&gl=US" - "Description" = "Create videos with a few clicks" - } - "Microsoft.549981C3F5F10" = @{ - "VDIState" = "Unchanged" - "URL" = "https://apps.microsoft.com/detail/cortana/9NFFX4SZZ23L?hl=en-us&gl=US" - "Description" = "Cortana (could not update)" - } - "Microsoft.BingNews" = @{ - "VDIState" = "Unchanged" - "URL" = "https://www.microsoft.com/en-us/p/microsoft-news/9wzdncrfhvfw" - "Description" = "Microsoft News app" - } - "Microsoft.BingWeather" = @{ - "VDIState" = "Unchanged" - "URL" = "https://www.microsoft.com/en-us/p/msn-weather/9wzdncrfj3q2" - "Description" = "MSN Weather app" - } - "Microsoft.DesktopAppInstaller" = @{ - "VDIState" = "Unchanged" - "URL" = "https://apps.microsoft.com/detail/9NBLGGH4NNS1" - "Description" = "Microsoft App Installer for Windows 10 makes sideloading Windows apps easy" - } - "Microsoft.GetHelp" = @{ - "VDIState" = "Unchanged" - "URL" = "https://docs.microsoft.com/en-us/windows-hardware/customize/desktop/customize-get-help-app" - "Description" = "App that facilitates free support for Microsoft products" - } - "Microsoft.Getstarted" = @{ - "VDIState" = "Unchanged" - "URL" = "https://www.microsoft.com/en-us/p/microsoft-tips/9wzdncrdtbjj" - "Description" = "Windows 10 tips app" - } - "Microsoft.MicrosoftOfficeHub" = @{ - "VDIState" = "Unchanged" - "URL" = "https://www.microsoft.com/en-us/p/office/9wzdncrd29v9" - "Description" = "Office UWP app suite" - } - "Microsoft.Office.OneNote" = @{ - "VDIState" = "Unchanged" - "URL" = "https://www.microsoft.com/en-us/p/onenote-for-windows-10/9wzdncrfhvjl" - "Description" = "Office UWP OneNote app" + "Bing Search" = @{ + VDIState = "Unchanged" + URL = "https://apps.microsoft.com/detail/9nzbf4gt040c" + Description = "Web Search from Microsoft Bing provides web results and answers in Windows Search" } + + "Clipchamp.Clipchamp" = @{ + VDIState = "Unchanged" + URL = "https://apps.microsoft.com/detail/9p1j8s7ccwwt?hl=en-us&gl=US" + Description = "Create videos with a few clicks" + } + + "Microsoft.549981C3F5F10" = @{ + VDIState = "Unchanged" + URL = "https://apps.microsoft.com/detail/cortana/9NFFX4SZZ23L?hl=en-us&gl=US" + Description = "Cortana (could not update)" + } + + "Microsoft.BingNews" = @{ + VDIState = "Unchanged" + URL = "https://www.microsoft.com/en-us/p/microsoft-news/9wzdncrfhvfw" + Description = "Microsoft News app" + } + + "Microsoft.BingWeather" = @{ + VDIState = "Unchanged" + URL = "https://www.microsoft.com/en-us/p/msn-weather/9wzdncrfj3q2" + Description = "MSN Weather app" + } + + "Microsoft.DesktopAppInstaller" = @{ + VDIState = "Unchanged" + URL = "https://apps.microsoft.com/detail/9NBLGGH4NNS1" + Description = "Microsoft App Installer for Windows 10 makes sideloading Windows apps easy" + } + + "Microsoft.GetHelp" = @{ + VDIState = "Unchanged" + URL = "https://docs.microsoft.com/en-us/windows-hardware/customize/desktop/customize-get-help-app" + Description = "App that facilitates free support for Microsoft products" + } + + "Microsoft.Getstarted" = @{ + VDIState = "Unchanged" + URL = "https://www.microsoft.com/en-us/p/microsoft-tips/9wzdncrdtbjj" + Description = "Windows 10 tips app" + } + + "Microsoft.MicrosoftOfficeHub" = @{ + VDIState = "Unchanged" + URL = "https://www.microsoft.com/en-us/p/office/9wzdncrd29v9" + Description = "Office UWP app suite" + } + + "Microsoft.Office.OneNote" = @{ + VDIState = "Unchanged" + URL = "https://www.microsoft.com/en-us/p/onenote-for-windows-10/9wzdncrfhvjl" + Description = "Office UWP OneNote app" + } + "Microsoft.MicrosoftSolitaireCollection" = @{ - "VDIState" = "Unchanged" - "URL" = "https://www.microsoft.com/en-us/p/microsoft-solitaire-collection/9wzdncrfhwd2" - "Description" = "Solitaire suite of games" - } - "Microsoft.MicrosoftStickyNotes" = @{ - "VDIState" = "Unchanged" - "URL" = "https://www.microsoft.com/en-us/p/microsoft-sticky-notes/9nblggh4qghw" - "Description" = "Note-taking app" - } - "Microsoft.OutlookForWindows" = @{ - "VDIState" = "Unchanged" - "URL" = "https://apps.microsoft.com/detail/9NRX63209R7B?hl=en-us&gl=US" - "Description" = "a best-in-class email experience that is free for anyone with Windows" - } - "Microsoft.MSPaint" = @{ - "VDIState" = "Unchanged" - "URL" = "https://apps.microsoft.com/store/detail/paint-3d/9NBLGGH5FV99" - "Description" = "Paint 3D app (not Classic Paint app)" - } - "Microsoft.Paint" = @{ - "VDIState" = "Unchanged" - "URL" = "https://apps.microsoft.com/detail/9PCFS5B6T72H" - "Description" = "Classic Paint app" - } - "Microsoft.People" = @{ - "VDIState" = "Unchanged" - "URL" = "https://www.microsoft.com/en-us/p/microsoft-people/9nblggh10pg8" - "Description" = "Contact management app" - } - "Microsoft.PowerAutomateDesktop" = @{ - "VDIState" = "Unchanged" - "URL" = "https://flow.microsoft.com/en-us/desktop/" - "Description" = "Power Automate Desktop app. Record desktop and web actions in a single flow" - } - "Microsoft.ScreenSketch" = @{ - "VDIState" = "Unchanged" - "URL" = "https://www.microsoft.com/en-us/p/snip-sketch/9mz95kl8mr0l" - "Description" = "Snip and Sketch app" - } - "Microsoft.SkypeApp" = @{ - "VDIState" = "Unchanged" - "URL" = "https://www.microsoft.com/en-us/p/skype/9wzdncrfj364" - "Description" = "Instant message, voice or video call app" - } - "Microsoft.StorePurchaseApp" = @{ - "VDIState" = "Unchanged" - "URL" = "" - "Description" = "Store purchase app helper" - } - "Microsoft.Todos" = @{ - "VDIState" = "Unchanged" - "URL" = "https://www.microsoft.com/en-us/p/microsoft-to-do-lists-tasks-reminders/9nblggh5r558" - "Description" = "Microsoft To Do makes it easy to plan your day and manage your life" - } - "Microsoft.WinDbg.Fast" = @{ - "VDIState" = "Unchanged" - "URL" = "https://apps.microsoft.com/detail/9PGJGD53TN86?hl=en-us&gl=US" - "Description" = "Microsoft WinDbg" - } - "Microsoft.Windows.DevHome" = @{ - "VDIState" = "Unchanged" - "URL" = "https://learn.microsoft.com/en-us/windows/dev-home/" - "Description" = "A control center providing the ability to monitor projects in your dashboard using customizable widgets and more" - } - "Microsoft.Windows.Photos" = @{ - "VDIState" = "Unchanged" - "URL" = "https://www.microsoft.com/en-us/p/microsoft-photos/9wzdncrfjbh4" - "Description" = "Photo and video editor" - } - "Microsoft.WindowsAlarms" = @{ - "VDIState" = "Unchanged" - "URL" = "https://www.microsoft.com/en-us/p/windows-alarms-clock/9wzdncrfj3pr" - "Description" = "A combination app, of alarm clock, world clock, timer, and stopwatch." - } - "Microsoft.WindowsCalculator" = @{ - "VDIState" = "Unchanged" - "URL" = "https://www.microsoft.com/en-us/p/windows-calculator/9wzdncrfhvn5" - "Description" = "Microsoft Calculator app" - } - "Microsoft.WindowsCamera" = @{ - "VDIState" = "Unchanged" - "URL" = "https://www.microsoft.com/en-us/p/windows-camera/9wzdncrfjbbg" - "Description" = "Camera app to manage photos and video" - } - "microsoft.windowscommunicationsapps" = @{ - "VDIState" = "Unchanged" - "URL" = "https://www.microsoft.com/en-us/p/mail-and-calendar/9wzdncrfhvqm" - "Description" = "Mail & Calendar apps" - } - "Microsoft.WindowsFeedbackHub" = @{ - "VDIState" = "Unchanged" - "URL" = "https://www.microsoft.com/en-us/p/feedback-hub/9nblggh4r32n" - "Description" = "App to provide Feedback on Windows and apps to Microsoft" - } - "Microsoft.WindowsMaps" = @{ - "VDIState" = "Unchanged" - "URL" = "https://www.microsoft.com/en-us/p/windows-maps/9wzdncrdtbvb" - "Description" = "Microsoft Maps app" - } - "Microsoft.WindowsNotepad" = @{ - "VDIState" = "Unchanged" - "URL" = "https://www.microsoft.com/en-us/p/windows-notepad/9msmlrh6lzf3" - "Description" = "Fast, simple text editor for plain text documents and source code files." - } - "Microsoft.WindowsStore" = @{ - "VDIState" = "Unchanged" - "URL" = "https://blogs.windows.com/windowsexperience/2021/06/24/building-a-new-open-microsoft-store-on-windows-11/" - "Description" = "Windows Store app" - } - "Microsoft.WindowsSoundRecorder" = @{ - "VDIState" = "Unchanged" - "URL" = "https://www.microsoft.com/en-us/p/windows-voice-recorder/9wzdncrfhwkn" - "Description" = "(Voice recorder)" - } - "Microsoft.WindowsTerminal" = @{ - "VDIState" = "Unchanged" - "URL" = "https://www.microsoft.com/en-us/p/windows-terminal/9n0dx20hk701" - "Description" = "A terminal app featuring tabs, panes, Unicode, UTF-8 character support, and GPU text rendering engine." - } - "Microsoft.Winget.Platform.Source" = @{ - "VDIState" = "Unchanged" - "URL" = "https://learn.microsoft.com/en-us/windows/package-manager/winget/" - "Description" = "The Winget tool enables users to manage applications on Win10 and Win11 devices. This tool is the client interface to the Windows Package Manager service" - } - "Microsoft.Xbox.TCUI" = @{ - "VDIState" = "Unchanged" - "URL" = "https://docs.microsoft.com/en-us/gaming/xbox-live/features/general/tcui/live-tcui-overview" - "Description" = "XBox Title Callable UI (TCUI) enables your game code to call pre-defined user interface displays" - } - "Microsoft.XboxIdentityProvider" = @{ - "VDIState" = "Unchanged" - "URL" = "https://www.microsoft.com/en-us/p/xbox-identity-provider/9wzdncrd1hkw" - "Description" = "A system app that enables PC games to connect to Xbox Live." - } - "Microsoft.XboxSpeechToTextOverlay" = @{ - "VDIState" = "Unchanged" - "URL" = "https://support.xbox.com/help/account-profile/accessibility/use-game-chat-transcription" - "Description" = "Xbox game transcription overlay" - } - "Microsoft.YourPhone" = @{ - "VDIState" = "Unchanged" - "URL" = "https://www.microsoft.com/en-us/p/Your-phone/9nmpj99vjbwv" - "Description" = "Android phone to PC device interface app" - } - "Microsoft.ZuneMusic" = @{ - "VDIState" = "Unchanged" - "URL" = "https://www.microsoft.com/en-us/p/groove-music/9wzdncrfj3pt" - "Description" = "Groove Music app" - } - "Microsoft.ZuneVideo" = @{ - "VDIState" = "Unchanged" - "URL" = "https://www.microsoft.com/en-us/p/movies-tv/9wzdncrfj3p2" - "Description" = "Movies and TV app" - } - "MicrosoftCorporationII.QuickAssist" = @{ - "VDIState" = "Unchanged" - "URL" = "https://apps.microsoft.com/detail/9P7BP5VNWKX5?hl=en-us&gl=US" - "Description" = "Microsoft remote help app" - } - "MicrosoftWindows.Client.WebExperience" = @{ - "VDIState" = "Unchanged" - "URL" = "" - "Description" = "Windows 11 Internet information widget" - } - "Microsoft.XboxApp" = @{ - "VDIState" = "Unchanged" - "URL" = "https://www.microsoft.com/store/apps/9wzdncrfjbd8" - "Description" = "Xbox 'Console Companion' app (games, friends, etc.)" - } - "Microsoft.MixedReality.Portal" = @{ - "VDIState" = "Unchanged" - "URL" = "https://www.microsoft.com/en-us/p/mixed-reality-portal/9ng1h8b3zc7m" - "Description" = "The app that facilitates Windows Mixed Reality setup, and serves as the command center for mixed reality experiences" - } - "Microsoft.Microsoft3DViewer" = @{ - "VDIState" = "Unchanged" - "URL" = "https://www.microsoft.com/en-us/p/3d-viewer/9nblggh42ths" - "Description" = "App to view common 3D file types" - } - "MicrosoftTeams" = @{ - "VDIState" = "Unchanged" - "URL" = "https://apps.microsoft.com/detail/xp8bt8dw290mpq" - "Description" = "Microsoft communication platform" - } - "MSTeams" = @{ - "VDIState" = "Unchanged" - "URL" = "https://apps.microsoft.com/detail/xp8bt8dw290mpq" - "Description" = "Microsoft communication platform" - } - "Microsoft.OneDriveSync" = @{ - "VDIState" = "Unchanged" - "URL" = "https://docs.microsoft.com/en-us/onedrive/one-drive-sync" - "Description" = "Microsoft OneDrive sync app (included in Office 2016 or later)" - } - "Microsoft.Wallet" = @{ - "VDIState" = "Unchanged" - "URL" = "https://www.microsoft.com/en-us/payments" - "Description" = "(Microsoft Pay) for Edge browser on certain devices" + VDIState = "Unchanged" + URL = "https://www.microsoft.com/en-us/p/microsoft-solitaire-collection/9wzdncrfhwd2" + Description = "Solitaire suite of games" + } + + "Microsoft.MicrosoftStickyNotes" = @{ + VDIState = "Unchanged" + URL = "https://www.microsoft.com/en-us/p/microsoft-sticky-notes/9nblggh4qghw" + Description = "Note-taking app" + } + + "Microsoft.OutlookForWindows" = @{ + VDIState = "Unchanged" + URL = "https://apps.microsoft.com/detail/9NRX63209R7B?hl=en-us&gl=US" + Description = "A best-in-class email experience that is free for anyone with Windows" + } + + "Microsoft.MSPaint" = @{ + VDIState = "Unchanged" + URL = "https://apps.microsoft.com/store/detail/paint-3d/9NBLGGH5FV99" + Description = "Paint 3D app (not Classic Paint app)" + } + + "Microsoft.Paint" = @{ + VDIState = "Unchanged" + URL = "https://apps.microsoft.com/detail/9PCFS5B6T72H" + Description = "Classic Paint app" + } + + "Microsoft.People" = @{ + VDIState = "Unchanged" + URL = "https://www.microsoft.com/en-us/p/microsoft-people/9nblggh10pg8" + Description = "Contact management app" + } + + "Microsoft.PowerAutomateDesktop" = @{ + VDIState = "Unchanged" + URL = "https://flow.microsoft.com/en-us/desktop/" + Description = "Power Automate Desktop app. Record desktop and web actions in a single flow" + } + + "Microsoft.ScreenSketch" = @{ + VDIState = "Unchanged" + URL = "https://www.microsoft.com/en-us/p/snip-sketch/9mz95kl8mr0l" + Description = "Snip and Sketch app" + } + + "Microsoft.SkypeApp" = @{ + VDIState = "Unchanged" + URL = "https://www.microsoft.com/en-us/p/skype/9wzdncrfj364" + Description = "Instant message, voice or video call app" + } + + "Microsoft.StorePurchaseApp" = @{ + VDIState = "Unchanged" + URL = "" + Description = "Store purchase app helper" + } + + "Microsoft.Todos" = @{ + VDIState = "Unchanged" + URL = "https://www.microsoft.com/en-us/p/microsoft-to-do-lists-tasks-reminders/9nblggh5r558" + Description = "Microsoft To Do makes it easy to plan your day and manage your life" + } + + "Microsoft.WinDbg.Fast" = @{ + VDIState = "Unchanged" + URL = "https://apps.microsoft.com/detail/9PGJGD53TN86?hl=en-us&gl=US" + Description = "Microsoft WinDbg" + } + + "Microsoft.Windows.DevHome" = @{ + VDIState = "Unchanged" + URL = "https://learn.microsoft.com/en-us/windows/dev-home/" + Description = "A control center providing the ability to monitor projects in your dashboard using customizable widgets and more" + } + + "Microsoft.Windows.Photos" = @{ + VDIState = "Unchanged" + URL = "https://www.microsoft.com/en-us/p/microsoft-photos/9wzdncrfjbh4" + Description = "Photo and video editor" + } + + "Microsoft.WindowsAlarms" = @{ + VDIState = "Unchanged" + URL = "https://www.microsoft.com/en-us/p/windows-alarms-clock/9wzdncrfj3pr" + Description = "A combination app of alarm clock, world clock, timer, and stopwatch." + } + + "Microsoft.WindowsCalculator" = @{ + VDIState = "Unchanged" + URL = "https://www.microsoft.com/en-us/p/windows-calculator/9wzdncrfhvn5" + Description = "Microsoft Calculator app" + } + + "Microsoft.WindowsCamera" = @{ + VDIState = "Unchanged" + URL = "https://www.microsoft.com/en-us/p/windows-camera/9wzdncrfjbbg" + Description = "Camera app to manage photos and video" + } + + "microsoft.windowscommunicationsapps" = @{ + VDIState = "Unchanged" + URL = "https://www.microsoft.com/en-us/p/mail-and-calendar/9wzdncrfhvqm" + Description = "Mail & Calendar apps" + } + + "Microsoft.WindowsFeedbackHub" = @{ + VDIState = "Unchanged" + URL = "https://www.microsoft.com/en-us/p/feedback-hub/9nblggh4r32n" + Description = "App to provide Feedback on Windows and apps to Microsoft" + } + + "Microsoft.WindowsMaps" = @{ + VDIState = "Unchanged" + URL = "https://www.microsoft.com/en-us/p/windows-maps/9wzdncrdtbvb" + Description = "Microsoft Maps app" + } + + "Microsoft.WindowsNotepad" = @{ + VDIState = "Unchanged" + URL = "https://www.microsoft.com/en-us/p/windows-notepad/9msmlrh6lzf3" + Description = "Fast, simple text editor for plain text documents and source code files." + } + + "Microsoft.WindowsStore" = @{ + VDIState = "Unchanged" + URL = "https://blogs.windows.com/windowsexperience/2021/06/24/building-a-new-open-microsoft-store-on-windows-11/" + Description = "Windows Store app" + } + + "Microsoft.WindowsSoundRecorder" = @{ + VDIState = "Unchanged" + URL = "https://www.microsoft.com/en-us/p/windows-voice-recorder/9wzdncrfhwkn" + Description = "(Voice recorder)" + } + + "Microsoft.WindowsTerminal" = @{ + VDIState = "Unchanged" + URL = "https://www.microsoft.com/en-us/p/windows-terminal/9n0dx20hk701" + Description = "A terminal app featuring tabs, panes, Unicode, UTF-8 character support, and a GPU text rendering engine." + } + + "Microsoft.Winget.Platform.Source" = @{ + VDIState = "Unchanged" + URL = "https://learn.microsoft.com/en-us/windows/package-manager/winget/" + Description = "The Winget tool enables users to manage applications on Win10 and Win11 devices. This tool is the client interface to the Windows Package Manager service" + } + + "Microsoft.Xbox.TCUI" = @{ + VDIState = "Unchanged" + URL = "https://docs.microsoft.com/en-us/gaming/xbox-live/features/general/tcui/live-tcui-overview" + Description = "XBox Title Callable UI (TCUI) enables your game code to call pre-defined user interface displays" + } + + "Microsoft.XboxIdentityProvider" = @{ + VDIState = "Unchanged" + URL = "https://www.microsoft.com/en-us/p/xbox-identity-provider/9wzdncrd1hkw" + Description = "A system app that enables PC games to connect to Xbox Live." + } + + "Microsoft.XboxSpeechToTextOverlay" = @{ + VDIState = "Unchanged" + URL = "https://support.xbox.com/help/account-profile/accessibility/use-game-chat-transcription" + Description = "Xbox game transcription overlay" + } + + "Microsoft.YourPhone" = @{ + VDIState = "Unchanged" + URL = "https://www.microsoft.com/en-us/p/Your-phone/9nmpj99vjbwv" + Description = "Android phone to PC device interface app" + } + + "Microsoft.ZuneMusic" = @{ + VDIState = "Unchanged" + URL = "https://www.microsoft.com/en-us/p/groove-music/9wzdncrfj3pt" + Description = "Groove Music app" + } + + "Microsoft.ZuneVideo" = @{ + VDIState = "Unchanged" + URL = "https://www.microsoft.com/en-us/p/movies-tv/9wzdncrfj3p2" + Description = "Movies and TV app" + } + + "MicrosoftCorporationII.QuickAssist" = @{ + VDIState = "Unchanged" + URL = "https://apps.microsoft.com/detail/9P7BP5VNWKX5?hl=en-us&gl=US" + Description = "Microsoft remote help app" + } + + "MicrosoftWindows.Client.WebExperience" = @{ + VDIState = "Unchanged" + URL = "" + Description = "Windows 11 Internet information widget" + } + + "Microsoft.XboxApp" = @{ + VDIState = "Unchanged" + URL = "https://www.microsoft.com/store/apps/9wzdncrfjbd8" + Description = "Xbox 'Console Companion' app (games, friends, etc.)" + } + + "Microsoft.MixedReality.Portal" = @{ + VDIState = "Unchanged" + URL = "https://www.microsoft.com/en-us/p/mixed-reality-portal/9ng1h8b3zc7m" + Description = "The app that facilitates Windows Mixed Reality setup, and serves as the command center for mixed reality experiences" + } + + "Microsoft.Microsoft3DViewer" = @{ + VDIState = "Unchanged" + URL = "https://www.microsoft.com/en-us/p/3d-viewer/9nblggh42ths" + Description = "App to view common 3D file types" + } + + "MicrosoftTeams" = @{ + VDIState = "Unchanged" + URL = "https://apps.microsoft.com/detail/xp8bt8dw290mpq" + Description = "Microsoft communication platform" + } + + "MSTeams" = @{ + VDIState = "Unchanged" + URL = "https://apps.microsoft.com/detail/xp8bt8dw290mpq" + Description = "Microsoft communication platform" + } + + "Microsoft.OneDriveSync" = @{ + VDIState = "Unchanged" + URL = "https://docs.microsoft.com/en-us/onedrive/one-drive-sync" + Description = "Microsoft OneDrive sync app (included in Office 2016 or later)" + } + + "Microsoft.Wallet" = @{ + VDIState = "Unchanged" + URL = "https://www.microsoft.com/en-us/payments" + Description = "(Microsoft Pay) for Edge browser on certain devices" } } -Foreach ($Key in $apps.Keys) { +foreach ($Key in $apps.Keys) { $Item = $apps[$Key] + Write-Host "Removing Provisioned Package $Key" Get-AppxProvisionedPackage -Online | - Where-Object { $_.PackageName -like ("*{0}*" -f $Key) } | - Remove-AppxProvisionedPackage -Online -ErrorAction SilentlyContinue | Out-Null + Where-Object { $_.PackageName -like ("*{0}*" -f $Key) } | + Remove-AppxProvisionedPackage -Online -ErrorAction SilentlyContinue | + Out-Null Write-Host "Attempting to remove [All Users] $Key - $($Item.Description)" Get-AppxPackage -AllUsers -Name ("*{0}*" -f $Key) | - Remove-AppxPackage -AllUsers -ErrorAction SilentlyContinue + Remove-AppxPackage -AllUsers -ErrorAction SilentlyContinue Write-Host "Attempting to remove $Key - $($Item.Description)" Get-AppxPackage -Name ("*{0}*" -f $Key) | - Remove-AppxPackage -ErrorAction SilentlyContinue | Out-Null - + Remove-AppxPackage -ErrorAction SilentlyContinue | + Out-Null } From 1cc2822d81bf47e80dd463ffe4107d40bdd4fa44 Mon Sep 17 00:00:00 2001 From: Mark Cornmesser Date: Tue, 16 Dec 2025 09:22:03 -0800 Subject: [PATCH 029/105] disable nonessential services --- .../manifests/profiles/disable_services.pp | 1 + .../manifests/disable_optional_services.pp | 62 +++++++++++++++++++ 2 files changed, 63 insertions(+) create mode 100644 modules/win_disable_services/manifests/disable_optional_services.pp diff --git a/modules/roles_profiles/manifests/profiles/disable_services.pp b/modules/roles_profiles/manifests/profiles/disable_services.pp index d75c8a231..2d6d641b7 100644 --- a/modules/roles_profiles/manifests/profiles/disable_services.pp +++ b/modules/roles_profiles/manifests/profiles/disable_services.pp @@ -43,6 +43,7 @@ ## Taken from https://github.com/The-Virtual-Desktop-Team/Virtual-Desktop-Optimization-Tool ## Bug 1913499 https://bugzilla.mozilla.org/show_bug.cgi?id=1913499 include win_disable_services::uninstall_appx_packages + include win_disable_services::disable_optional_services if ($facts['custom_win_location'] == 'azure') { include win_scheduled_tasks::kill_local_clipboard } diff --git a/modules/win_disable_services/manifests/disable_optional_services.pp b/modules/win_disable_services/manifests/disable_optional_services.pp new file mode 100644 index 000000000..c5eb49625 --- /dev/null +++ b/modules/win_disable_services/manifests/disable_optional_services.pp @@ -0,0 +1,62 @@ +# This Source Code Form is subject to the terms of the Mozilla Public +# License, v. 2.0. If a copy of the MPL was not distributed with this +# file, You can obtain one at http://mozilla.org/MPL/2.0/. + +class win_disable_services::disable_optional_services { + + $services = [ + + # --- Bluetooth --- + 'BTAGService', # Bluetooth Audio Gateway Service + 'bthserv', # Bluetooth Support Service + 'BthAvctpSvc', # AVCTP Service (Bluetooth audio) + + # --- Telemetry / diagnostics --- + 'DiagTrack', # Connected User Experiences and Telemetry + 'DPS', # Diagnostic Policy Service + 'DusmSvc', # Data Usage + 'WdiServiceHost', # Diagnostic System Host + + # --- Network discovery & publishing --- + 'FDResPub', # Function Discovery Resource Publication + 'FDResHost', # Function Discovery Provider Host + + # --- Print / themes / prefetch (optional) --- + 'Spooler', # Print Spooler (disable only if you never print) + 'Themes', # Themes (visual styles) + 'SysMain', # SysMain (SuperFetch / prefetcher) + + # --- Wi-Fi / MS account / notifications / web accounts --- + 'WlanSvc', # WLAN AutoConfig (Wi-Fi) + 'wlidsvc', # Microsoft Account Sign-in Assistant + 'WpnService', # Windows Push Notifications System Service + 'TokenBroker', # Web Account Manager + + # --- UWP / Microsoft Store ecosystem --- + 'AppReadiness', # App readiness + 'AppXSvc', # AppX Deployment Service + 'CDPSvc', # Connected Devices Platform Service + 'ClipSVC', # Client License Service (Store licensing) + 'CoreMessagingRegistrar', # CoreMessaging + 'StateRepository', # State Repository Service + 'SystemEventsBroker', # System Events Broker + 'TextInputManagementSvc', # Text Input Management + 'TimeBrokerSvc', # Time Broker (background tasks) + + # --- Indexing / contacts --- + 'TrkWks', # Distributed Link Tracking Client + + # --- Third-party / vendor helpers (excluding nxlog) --- + 'igccservice', # Intel Graphics Command Center Service + 'IntelAudioService', # Intel Audio Service + 'jhi_service', # Intel Dynamic Application Loader Host + 'RtkAudioUniversalService', # Realtek Audio Universal Service + 'webthreatdefsvc', # Web Threat Defense service + + # --- Others --- + 'RmSvc', # Radio Management Service (airplane mode / radios) + 'NgcCtnrSvc', # Microsoft Passport Container (Windows Hello / PIN) + ] + + win_disable_services::disable_service { $services: } +} From 1297aae02beaa0e7d5b48864f65b49d82ab44a3d Mon Sep 17 00:00:00 2001 From: Mark Cornmesser Date: Tue, 16 Dec 2025 10:31:21 -0800 Subject: [PATCH 030/105] disable nonessential services --- .../manifests/disable_optional_services.pp | 21 +++++++++++++++---- 1 file changed, 17 insertions(+), 4 deletions(-) diff --git a/modules/win_disable_services/manifests/disable_optional_services.pp b/modules/win_disable_services/manifests/disable_optional_services.pp index c5eb49625..b51ce8dcb 100644 --- a/modules/win_disable_services/manifests/disable_optional_services.pp +++ b/modules/win_disable_services/manifests/disable_optional_services.pp @@ -34,11 +34,11 @@ # --- UWP / Microsoft Store ecosystem --- 'AppReadiness', # App readiness - 'AppXSvc', # AppX Deployment Service +# 'AppXSvc', # AppX Deployment Service 'CDPSvc', # Connected Devices Platform Service - 'ClipSVC', # Client License Service (Store licensing) +# 'ClipSVC', # Client License Service (Store licensing) 'CoreMessagingRegistrar', # CoreMessaging - 'StateRepository', # State Repository Service +# 'StateRepository', # State Repository Service 'SystemEventsBroker', # System Events Broker 'TextInputManagementSvc', # Text Input Management 'TimeBrokerSvc', # Time Broker (background tasks) @@ -58,5 +58,18 @@ 'NgcCtnrSvc', # Microsoft Passport Container (Windows Hello / PIN) ] - win_disable_services::disable_service { $services: } + $services_disable_only = [ + 'SystemEventsBroker', + 'webthreatdefsvc', + 'RmSvc', + ] + + service { $services: + ensure => 'stopped', + enable => false, + } + + service { $services_disable_only: + enable => false, + } } From 376de891b3b502cd855559402be01991826192e7 Mon Sep 17 00:00:00 2001 From: Mark Cornmesser Date: Tue, 16 Dec 2025 11:02:02 -0800 Subject: [PATCH 031/105] disable nonessential services --- .../manifests/disable_optional_services.pp | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/modules/win_disable_services/manifests/disable_optional_services.pp b/modules/win_disable_services/manifests/disable_optional_services.pp index b51ce8dcb..b1f626847 100644 --- a/modules/win_disable_services/manifests/disable_optional_services.pp +++ b/modules/win_disable_services/manifests/disable_optional_services.pp @@ -39,7 +39,7 @@ # 'ClipSVC', # Client License Service (Store licensing) 'CoreMessagingRegistrar', # CoreMessaging # 'StateRepository', # State Repository Service - 'SystemEventsBroker', # System Events Broker +# 'SystemEventsBroker', # System Events Broker 'TextInputManagementSvc', # Text Input Management 'TimeBrokerSvc', # Time Broker (background tasks) @@ -51,10 +51,10 @@ 'IntelAudioService', # Intel Audio Service 'jhi_service', # Intel Dynamic Application Loader Host 'RtkAudioUniversalService', # Realtek Audio Universal Service - 'webthreatdefsvc', # Web Threat Defense service +# 'webthreatdefsvc', # Web Threat Defense service # --- Others --- - 'RmSvc', # Radio Management Service (airplane mode / radios) +# 'RmSvc', # Radio Management Service (airplane mode / radios) 'NgcCtnrSvc', # Microsoft Passport Container (Windows Hello / PIN) ] From 631a7037b8f9b285bde241d0fa99124d2773b040 Mon Sep 17 00:00:00 2001 From: Mark Cornmesser Date: Tue, 16 Dec 2025 11:44:56 -0800 Subject: [PATCH 032/105] disable nonessential services --- .../win_disable_services/manifests/disable_optional_services.pp | 1 - 1 file changed, 1 deletion(-) diff --git a/modules/win_disable_services/manifests/disable_optional_services.pp b/modules/win_disable_services/manifests/disable_optional_services.pp index b1f626847..8bdab784b 100644 --- a/modules/win_disable_services/manifests/disable_optional_services.pp +++ b/modules/win_disable_services/manifests/disable_optional_services.pp @@ -65,7 +65,6 @@ ] service { $services: - ensure => 'stopped', enable => false, } From b6e01bcf31621de34906b95d3b5c943fb4adafec Mon Sep 17 00:00:00 2001 From: Mark Cornmesser Date: Tue, 16 Dec 2025 12:28:11 -0800 Subject: [PATCH 033/105] disable nonessential services --- .../win_disable_services/manifests/disable_optional_services.pp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/modules/win_disable_services/manifests/disable_optional_services.pp b/modules/win_disable_services/manifests/disable_optional_services.pp index 8bdab784b..9fbf7a634 100644 --- a/modules/win_disable_services/manifests/disable_optional_services.pp +++ b/modules/win_disable_services/manifests/disable_optional_services.pp @@ -37,7 +37,7 @@ # 'AppXSvc', # AppX Deployment Service 'CDPSvc', # Connected Devices Platform Service # 'ClipSVC', # Client License Service (Store licensing) - 'CoreMessagingRegistrar', # CoreMessaging +#### 'CoreMessagingRegistrar', # CoreMessaging # 'StateRepository', # State Repository Service # 'SystemEventsBroker', # System Events Broker 'TextInputManagementSvc', # Text Input Management From 3cbb36d638716dfeac22cde2c9439d81956ff54c Mon Sep 17 00:00:00 2001 From: Mark Cornmesser Date: Tue, 16 Dec 2025 13:11:24 -0800 Subject: [PATCH 034/105] disable nonessential services --- .../manifests/disable_optional_services.pp | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/modules/win_disable_services/manifests/disable_optional_services.pp b/modules/win_disable_services/manifests/disable_optional_services.pp index 9fbf7a634..e4a79f857 100644 --- a/modules/win_disable_services/manifests/disable_optional_services.pp +++ b/modules/win_disable_services/manifests/disable_optional_services.pp @@ -37,9 +37,9 @@ # 'AppXSvc', # AppX Deployment Service 'CDPSvc', # Connected Devices Platform Service # 'ClipSVC', # Client License Service (Store licensing) -#### 'CoreMessagingRegistrar', # CoreMessaging +#### 'CoreMessagingRegistrar', # CoreMessaging - won't disable # 'StateRepository', # State Repository Service -# 'SystemEventsBroker', # System Events Broker +#### 'SystemEventsBroker', # System Events Broker - DON'T Disable. Sched tasks depends on this 'TextInputManagementSvc', # Text Input Management 'TimeBrokerSvc', # Time Broker (background tasks) @@ -59,7 +59,6 @@ ] $services_disable_only = [ - 'SystemEventsBroker', 'webthreatdefsvc', 'RmSvc', ] From 0dd8b6ddfd5f3cf03549b3873e733094e867362f Mon Sep 17 00:00:00 2001 From: Mark Cornmesser Date: Tue, 16 Dec 2025 15:08:15 -0800 Subject: [PATCH 035/105] disable nonessential services --- .../manifests/disable_optional_services.pp | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/modules/win_disable_services/manifests/disable_optional_services.pp b/modules/win_disable_services/manifests/disable_optional_services.pp index e4a79f857..55f77690c 100644 --- a/modules/win_disable_services/manifests/disable_optional_services.pp +++ b/modules/win_disable_services/manifests/disable_optional_services.pp @@ -35,13 +35,13 @@ # --- UWP / Microsoft Store ecosystem --- 'AppReadiness', # App readiness # 'AppXSvc', # AppX Deployment Service - 'CDPSvc', # Connected Devices Platform Service +#### 'CDPSvc', # Connected Devices Platform Service # 'ClipSVC', # Client License Service (Store licensing) #### 'CoreMessagingRegistrar', # CoreMessaging - won't disable # 'StateRepository', # State Repository Service #### 'SystemEventsBroker', # System Events Broker - DON'T Disable. Sched tasks depends on this - 'TextInputManagementSvc', # Text Input Management - 'TimeBrokerSvc', # Time Broker (background tasks) +#### 'TextInputManagementSvc', # Text Input Management +#### 'TimeBrokerSvc', # Time Broker (background tasks) # --- Indexing / contacts --- 'TrkWks', # Distributed Link Tracking Client From 79979a0b2d69dd9db2658fee7be14eb40074da02 Mon Sep 17 00:00:00 2001 From: Mark Cornmesser Date: Wed, 17 Dec 2025 08:37:20 -0800 Subject: [PATCH 036/105] disable per user services in start up script --- .../manifests/disable_optional_services.pp | 3 ++ .../files/maintainsystem-hw.ps1 | 47 +++++++++++++++++++ 2 files changed, 50 insertions(+) diff --git a/modules/win_disable_services/manifests/disable_optional_services.pp b/modules/win_disable_services/manifests/disable_optional_services.pp index 55f77690c..38be71c48 100644 --- a/modules/win_disable_services/manifests/disable_optional_services.pp +++ b/modules/win_disable_services/manifests/disable_optional_services.pp @@ -56,6 +56,9 @@ # --- Others --- # 'RmSvc', # Radio Management Service (airplane mode / radios) 'NgcCtnrSvc', # Microsoft Passport Container (Windows Hello / PIN) + 'lfsvc', # Geolocation Service + 'PcaSvc', # Program Compatibility Assistant Service + 'SSDPSRV', # SSDP Discovery/UPnP Discovery ] $services_disable_only = [ diff --git a/modules/win_scheduled_tasks/files/maintainsystem-hw.ps1 b/modules/win_scheduled_tasks/files/maintainsystem-hw.ps1 index 8d11732dc..cec507aa3 100644 --- a/modules/win_scheduled_tasks/files/maintainsystem-hw.ps1 +++ b/modules/win_scheduled_tasks/files/maintainsystem-hw.ps1 @@ -411,6 +411,52 @@ function Get-LatestGoogleChrome { } } +function Disable-PerUserUwpServices { + [CmdletBinding()] + param ( + [string[]] + $ServicePrefixes = @( + 'cbdhsvc_', # Clipboard User Service + 'OneSyncSvc_', # Sync Host + 'UdkUserSvc_', # Udk User Service + 'PimIndexMaintenanceSvc_', # Contact/People indexing + 'UnistoreSvc_', # User Data Storage + 'UserDataSvc_', # User Data Access + 'CDPUserSvc_', # Connected Devices Platform (user) + 'WpnUserService_', # Push Notifications (user) + 'webthreatdefusersvc_' # Web Threat Defense (user) + ) + ) + + foreach ($prefix in $ServicePrefixes) { + + $svcList = Get-Service -Name "$prefix*" -ErrorAction SilentlyContinue + + if (-not $svcList) { + Write-Log -message ('{0} :: No services found for prefix {1}' -f $($MyInvocation.MyCommand.Name), $prefix) -severity 'DEBUG' + continue + } + + foreach ($svc in $svcList) { + Write-Log -message ('{0} :: Disabling per-user service {1}' -f $($MyInvocation.MyCommand.Name), $svc.Name) -severity 'DEBUG' + try { + # Disable so it will not start next logon/boot + Set-Service -Name $svc.Name -StartupType Disabled -ErrorAction Stop + + # Try to stop it now if running + if ($svc.Status -eq 'Running') { + Write-Log -message ('{0} :: Stopping per-user service {1}' -f $($MyInvocation.MyCommand.Name), $svc.Name) -severity 'DEBUG' + Stop-Service -Name $svc.Name -Force -ErrorAction Stop + } + } + catch { + Write-Log -message ('{0} :: Failed to disable/stop service {1}: {2}' -f $($MyInvocation.MyCommand.Name), $svc.Name, $_.Exception.Message) -severity 'DEBUG' + } + } + } +} + + function Set-PXE { param ( ) @@ -505,6 +551,7 @@ If ($bootstrap_stage -eq 'complete') { break } } + Disable-PerUserUwpServices ## Let's make sure the machine is online before checking the internet Test-ConnectionUntilOnline From cb9b8fd9fc7f9fd6d6d0c8297d081946079a2bfd Mon Sep 17 00:00:00 2001 From: Mark Cornmesser Date: Wed, 17 Dec 2025 09:20:28 -0800 Subject: [PATCH 037/105] disable per user services in start up script --- .../files/maintainsystem-hw.ps1 | 29 ++++++++--------- .../files/self_redeploy_check.ps1 | 31 ------------------- 2 files changed, 13 insertions(+), 47 deletions(-) diff --git a/modules/win_scheduled_tasks/files/maintainsystem-hw.ps1 b/modules/win_scheduled_tasks/files/maintainsystem-hw.ps1 index cec507aa3..6d280fb8a 100644 --- a/modules/win_scheduled_tasks/files/maintainsystem-hw.ps1 +++ b/modules/win_scheduled_tasks/files/maintainsystem-hw.ps1 @@ -416,15 +416,15 @@ function Disable-PerUserUwpServices { param ( [string[]] $ServicePrefixes = @( - 'cbdhsvc_', # Clipboard User Service - 'OneSyncSvc_', # Sync Host - 'UdkUserSvc_', # Udk User Service - 'PimIndexMaintenanceSvc_', # Contact/People indexing - 'UnistoreSvc_', # User Data Storage - 'UserDataSvc_', # User Data Access - 'CDPUserSvc_', # Connected Devices Platform (user) - 'WpnUserService_', # Push Notifications (user) - 'webthreatdefusersvc_' # Web Threat Defense (user) + 'cbdhsvc_', # Clipboard User Service + 'OneSyncSvc_', # Sync Host + 'UdkUserSvc_', # Udk User Service + 'PimIndexMaintenanceSvc_', # Contact/People indexing + 'UnistoreSvc_', # User Data Storage + 'UserDataSvc_', # User Data Access + 'CDPUserSvc_', # Connected Devices Platform (user) + 'WpnUserService_', # Push Notifications (user) + 'webthreatdefusersvc_' # Web Threat Defense (user) ) ) @@ -438,25 +438,22 @@ function Disable-PerUserUwpServices { } foreach ($svc in $svcList) { - Write-Log -message ('{0} :: Disabling per-user service {1}' -f $($MyInvocation.MyCommand.Name), $svc.Name) -severity 'DEBUG' try { - # Disable so it will not start next logon/boot - Set-Service -Name $svc.Name -StartupType Disabled -ErrorAction Stop - - # Try to stop it now if running if ($svc.Status -eq 'Running') { Write-Log -message ('{0} :: Stopping per-user service {1}' -f $($MyInvocation.MyCommand.Name), $svc.Name) -severity 'DEBUG' Stop-Service -Name $svc.Name -Force -ErrorAction Stop } + else { + Write-Log -message ('{0} :: Service {1} is already {2}, no action needed' -f $($MyInvocation.MyCommand.Name), $svc.Name, $svc.Status) -severity 'DEBUG' + } } catch { - Write-Log -message ('{0} :: Failed to disable/stop service {1}: {2}' -f $($MyInvocation.MyCommand.Name), $svc.Name, $_.Exception.Message) -severity 'DEBUG' + Write-Log -message ('{0} :: Failed to stop service {1}: {2}' -f $($MyInvocation.MyCommand.Name), $svc.Name, $_.Exception.Message) -severity 'DEBUG' } } } } - function Set-PXE { param ( ) diff --git a/modules/win_scheduled_tasks/files/self_redeploy_check.ps1 b/modules/win_scheduled_tasks/files/self_redeploy_check.ps1 index 2a7acc384..cd7172719 100644 --- a/modules/win_scheduled_tasks/files/self_redeploy_check.ps1 +++ b/modules/win_scheduled_tasks/files/self_redeploy_check.ps1 @@ -122,10 +122,6 @@ function Get-PXEPendingFlag { return $false } - -# ------------------------------------------------------------------- -# CompareConfig -# ------------------------------------------------------------------- function CompareConfig { param ( [string]$yaml_url = "https://raw.githubusercontent.com/mozilla-platform-ops/worker-images/refs/heads/main/provisioners/windows/MDC1Windows/pools.yml", @@ -178,9 +174,6 @@ function CompareConfig { return } - # ------------------------------- - # Reverse DNS - # ------------------------------- try { $ResolvedName = (Resolve-DnsName -Name $IPAddress -Server "10.48.75.120").NameHost } @@ -200,9 +193,6 @@ function CompareConfig { $worker_node_name = $ResolvedName.Substring(0, $index) Write-Log -message "Host name set to: $worker_node_name" -severity 'INFO' - # ------------------------------- - # Registry Values - # ------------------------------- $localHash = (Get-ItemProperty -Path HKLM:\SOFTWARE\Mozilla\ronin_puppet).GITHASH $localPool = (Get-ItemProperty -Path HKLM:\SOFTWARE\Mozilla\ronin_puppet).worker_pool_id @@ -243,9 +233,6 @@ function CompareConfig { return } - # ------------------------------- - # Find pool entry - # ------------------------------- $found = $false if ($yaml) { foreach ($pool in $yaml.pools) { @@ -270,9 +257,6 @@ function CompareConfig { Write-Log -message "=== Configuration Comparison ===" -severity 'INFO' - # ------------------------------- - # Compare Worker Pool - # ------------------------------- if ($localPool -eq $WorkerPool) { Write-Log -message "Worker Pool Match: $WorkerPool" -severity 'INFO' } @@ -281,9 +265,6 @@ function CompareConfig { #$SETPXE = $true } - # ------------------------------- - # Compare Git Hash - # ------------------------------- if ([string]::IsNullOrWhiteSpace($yamlHash)) { Write-Log -message "YAML hash is missing or invalid. Treating as mismatch." -severity 'ERROR' $SETPXE = $true @@ -298,17 +279,11 @@ function CompareConfig { Write-Log -message "Git Hash Match: $yamlHash" -severity 'INFO' } - # ------------------------------- - # Check Image Directory - # ------------------------------- if (!(Test-Path $yamlImageDir)) { Write-Log -message "Image Directory MISMATCH! YAML: $yamlImageDir NOT FOUND" -severity 'ERROR' $SETPXE = $true } - # ==================================================================================== - # NEW LOGIC: Evaluate worker-status.json BEFORE reboot or PXE trigger - # ==================================================================================== if ($SETPXE) { Write-Log -message "Configuration mismatch detected. Evaluating worker-status.json..." -severity 'WARN' @@ -338,9 +313,6 @@ function CompareConfig { return } - # ------------------------------- - # Parse worker-status.json - # ------------------------------- try { $json = Get-Content $workerStatus -Raw | ConvertFrom-Json } @@ -351,9 +323,6 @@ function CompareConfig { return } - # ------------------------------- - # ACTIVE TASK HANDLING + FLAGGING - # ------------------------------- if (($json.currentTaskIds).Count -eq 0) { Write-Log -message "No active tasks. Rebooting now!" -severity 'WARN' Set-PXEPendingFlag -Clear From 90908aa37ab8f8889d32191f8331f54ad038bf16 Mon Sep 17 00:00:00 2001 From: Mark Cornmesser Date: Wed, 17 Dec 2025 12:50:12 -0800 Subject: [PATCH 038/105] disable per user services in start up script --- .../manifests/disable_optional_services.pp | 28 ++++++++++--------- 1 file changed, 15 insertions(+), 13 deletions(-) diff --git a/modules/win_disable_services/manifests/disable_optional_services.pp b/modules/win_disable_services/manifests/disable_optional_services.pp index 38be71c48..8009d0f44 100644 --- a/modules/win_disable_services/manifests/disable_optional_services.pp +++ b/modules/win_disable_services/manifests/disable_optional_services.pp @@ -2,6 +2,8 @@ # License, v. 2.0. If a copy of the MPL was not distributed with this # file, You can obtain one at http://mozilla.org/MPL/2.0/. +## "- DON'T Disable." = has adverse effects if disabled + class win_disable_services::disable_optional_services { $services = [ @@ -13,7 +15,7 @@ # --- Telemetry / diagnostics --- 'DiagTrack', # Connected User Experiences and Telemetry - 'DPS', # Diagnostic Policy Service + 'DPS', # Diagnostic Policy Service - Disabled in MaintainSytems script too 'DusmSvc', # Data Usage 'WdiServiceHost', # Diagnostic System Host @@ -29,32 +31,32 @@ # --- Wi-Fi / MS account / notifications / web accounts --- 'WlanSvc', # WLAN AutoConfig (Wi-Fi) 'wlidsvc', # Microsoft Account Sign-in Assistant - 'WpnService', # Windows Push Notifications System Service + 'WpnService', # Windows Push Notifications System Service - Disabled in MaintainSytems script too 'TokenBroker', # Web Account Manager # --- UWP / Microsoft Store ecosystem --- 'AppReadiness', # App readiness -# 'AppXSvc', # AppX Deployment Service -#### 'CDPSvc', # Connected Devices Platform Service -# 'ClipSVC', # Client License Service (Store licensing) -#### 'CoreMessagingRegistrar', # CoreMessaging - won't disable -# 'StateRepository', # State Repository Service -#### 'SystemEventsBroker', # System Events Broker - DON'T Disable. Sched tasks depends on this -#### 'TextInputManagementSvc', # Text Input Management -#### 'TimeBrokerSvc', # Time Broker (background tasks) +# 'AppXSvc', # AppX Deployment Service - DON'T Disable. +# 'CDPSvc', # Connected Devices Platform Service - DON'T Disable. +# 'ClipSVC', # Client License Service (Store licensing) - DON'T Disable. +# 'CoreMessagingRegistrar', # CoreMessaging - won't disable +# 'StateRepository', # State Repository Service - DON'T Disable. +# 'SystemEventsBroker', # System Events Broker - DON'T Disable. +# 'TextInputManagementSvc', # Text Input Management - DON'T Disable. +# 'TimeBrokerSvc', # Time Broker (background tasks) - DON'T Disable. # --- Indexing / contacts --- - 'TrkWks', # Distributed Link Tracking Client + 'TrkWks', # Distributed Link Tracking Client - Disabled in MaintainSytems script too # --- Third-party / vendor helpers (excluding nxlog) --- 'igccservice', # Intel Graphics Command Center Service 'IntelAudioService', # Intel Audio Service 'jhi_service', # Intel Dynamic Application Loader Host 'RtkAudioUniversalService', # Realtek Audio Universal Service -# 'webthreatdefsvc', # Web Threat Defense service +# 'webthreatdefsvc', # Web Threat Defense service - DON'T Disable. # --- Others --- -# 'RmSvc', # Radio Management Service (airplane mode / radios) +# 'RmSvc', # Radio Management Service (airplane mode / radios) - DON'T Disable. 'NgcCtnrSvc', # Microsoft Passport Container (Windows Hello / PIN) 'lfsvc', # Geolocation Service 'PcaSvc', # Program Compatibility Assistant Service From b37a98d7344e3fbc4be37521faf2189690e24b34 Mon Sep 17 00:00:00 2001 From: Mark Cornmesser Date: Fri, 19 Dec 2025 09:11:05 -0800 Subject: [PATCH 039/105] disable apx service --- .../win_disable_services/manifests/disable_optional_services.pp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/modules/win_disable_services/manifests/disable_optional_services.pp b/modules/win_disable_services/manifests/disable_optional_services.pp index 8009d0f44..cf667a56c 100644 --- a/modules/win_disable_services/manifests/disable_optional_services.pp +++ b/modules/win_disable_services/manifests/disable_optional_services.pp @@ -36,7 +36,7 @@ # --- UWP / Microsoft Store ecosystem --- 'AppReadiness', # App readiness -# 'AppXSvc', # AppX Deployment Service - DON'T Disable. + 'AppXSvc', # AppX Deployment Service # 'CDPSvc', # Connected Devices Platform Service - DON'T Disable. # 'ClipSVC', # Client License Service (Store licensing) - DON'T Disable. # 'CoreMessagingRegistrar', # CoreMessaging - won't disable From d683c097eb2e895e841693ab541ee09233665d88 Mon Sep 17 00:00:00 2001 From: Mark Cornmesser Date: Fri, 19 Dec 2025 11:14:32 -0800 Subject: [PATCH 040/105] disable apx service --- .../files/appxpackages/BAKuninstall.ps1 | 320 +++++++++ .../files/appxpackages/uninstall.ps1 | 656 ++++++++++-------- .../manifests/disable_optional_services.pp | 2 +- 3 files changed, 692 insertions(+), 286 deletions(-) create mode 100644 modules/win_disable_services/files/appxpackages/BAKuninstall.ps1 diff --git a/modules/win_disable_services/files/appxpackages/BAKuninstall.ps1 b/modules/win_disable_services/files/appxpackages/BAKuninstall.ps1 new file mode 100644 index 000000000..4778d3e8e --- /dev/null +++ b/modules/win_disable_services/files/appxpackages/BAKuninstall.ps1 @@ -0,0 +1,320 @@ +$apps = @{ + "Bing Search" = @{ + VDIState = "Unchanged" + URL = "https://apps.microsoft.com/detail/9nzbf4gt040c" + Description = "Web Search from Microsoft Bing provides web results and answers in Windows Search" + } + + "Clipchamp.Clipchamp" = @{ + VDIState = "Unchanged" + URL = "https://apps.microsoft.com/detail/9p1j8s7ccwwt?hl=en-us&gl=US" + Description = "Create videos with a few clicks" + } + + "Microsoft.549981C3F5F10" = @{ + VDIState = "Unchanged" + URL = "https://apps.microsoft.com/detail/cortana/9NFFX4SZZ23L?hl=en-us&gl=US" + Description = "Cortana (could not update)" + } + + "Microsoft.BingNews" = @{ + VDIState = "Unchanged" + URL = "https://www.microsoft.com/en-us/p/microsoft-news/9wzdncrfhvfw" + Description = "Microsoft News app" + } + + "Microsoft.BingWeather" = @{ + VDIState = "Unchanged" + URL = "https://www.microsoft.com/en-us/p/msn-weather/9wzdncrfj3q2" + Description = "MSN Weather app" + } + + "Microsoft.DesktopAppInstaller" = @{ + VDIState = "Unchanged" + URL = "https://apps.microsoft.com/detail/9NBLGGH4NNS1" + Description = "Microsoft App Installer for Windows 10 makes sideloading Windows apps easy" + } + + "Microsoft.GetHelp" = @{ + VDIState = "Unchanged" + URL = "https://docs.microsoft.com/en-us/windows-hardware/customize/desktop/customize-get-help-app" + Description = "App that facilitates free support for Microsoft products" + } + + "Microsoft.Getstarted" = @{ + VDIState = "Unchanged" + URL = "https://www.microsoft.com/en-us/p/microsoft-tips/9wzdncrdtbjj" + Description = "Windows 10 tips app" + } + + "Microsoft.MicrosoftOfficeHub" = @{ + VDIState = "Unchanged" + URL = "https://www.microsoft.com/en-us/p/office/9wzdncrd29v9" + Description = "Office UWP app suite" + } + + "Microsoft.Office.OneNote" = @{ + VDIState = "Unchanged" + URL = "https://www.microsoft.com/en-us/p/onenote-for-windows-10/9wzdncrfhvjl" + Description = "Office UWP OneNote app" + } + + "Microsoft.MicrosoftSolitaireCollection" = @{ + VDIState = "Unchanged" + URL = "https://www.microsoft.com/en-us/p/microsoft-solitaire-collection/9wzdncrfhwd2" + Description = "Solitaire suite of games" + } + + "Microsoft.MicrosoftStickyNotes" = @{ + VDIState = "Unchanged" + URL = "https://www.microsoft.com/en-us/p/microsoft-sticky-notes/9nblggh4qghw" + Description = "Note-taking app" + } + + "Microsoft.OutlookForWindows" = @{ + VDIState = "Unchanged" + URL = "https://apps.microsoft.com/detail/9NRX63209R7B?hl=en-us&gl=US" + Description = "A best-in-class email experience that is free for anyone with Windows" + } + + "Microsoft.MSPaint" = @{ + VDIState = "Unchanged" + URL = "https://apps.microsoft.com/store/detail/paint-3d/9NBLGGH5FV99" + Description = "Paint 3D app (not Classic Paint app)" + } + + "Microsoft.Paint" = @{ + VDIState = "Unchanged" + URL = "https://apps.microsoft.com/detail/9PCFS5B6T72H" + Description = "Classic Paint app" + } + + "Microsoft.People" = @{ + VDIState = "Unchanged" + URL = "https://www.microsoft.com/en-us/p/microsoft-people/9nblggh10pg8" + Description = "Contact management app" + } + + "Microsoft.PowerAutomateDesktop" = @{ + VDIState = "Unchanged" + URL = "https://flow.microsoft.com/en-us/desktop/" + Description = "Power Automate Desktop app. Record desktop and web actions in a single flow" + } + + "Microsoft.ScreenSketch" = @{ + VDIState = "Unchanged" + URL = "https://www.microsoft.com/en-us/p/snip-sketch/9mz95kl8mr0l" + Description = "Snip and Sketch app" + } + + "Microsoft.SkypeApp" = @{ + VDIState = "Unchanged" + URL = "https://www.microsoft.com/en-us/p/skype/9wzdncrfj364" + Description = "Instant message, voice or video call app" + } + + "Microsoft.StorePurchaseApp" = @{ + VDIState = "Unchanged" + URL = "" + Description = "Store purchase app helper" + } + + "Microsoft.Todos" = @{ + VDIState = "Unchanged" + URL = "https://www.microsoft.com/en-us/p/microsoft-to-do-lists-tasks-reminders/9nblggh5r558" + Description = "Microsoft To Do makes it easy to plan your day and manage your life" + } + + "Microsoft.WinDbg.Fast" = @{ + VDIState = "Unchanged" + URL = "https://apps.microsoft.com/detail/9PGJGD53TN86?hl=en-us&gl=US" + Description = "Microsoft WinDbg" + } + + "Microsoft.Windows.DevHome" = @{ + VDIState = "Unchanged" + URL = "https://learn.microsoft.com/en-us/windows/dev-home/" + Description = "A control center providing the ability to monitor projects in your dashboard using customizable widgets and more" + } + + "Microsoft.Windows.Photos" = @{ + VDIState = "Unchanged" + URL = "https://www.microsoft.com/en-us/p/microsoft-photos/9wzdncrfjbh4" + Description = "Photo and video editor" + } + + "Microsoft.WindowsAlarms" = @{ + VDIState = "Unchanged" + URL = "https://www.microsoft.com/en-us/p/windows-alarms-clock/9wzdncrfj3pr" + Description = "A combination app of alarm clock, world clock, timer, and stopwatch." + } + + "Microsoft.WindowsCalculator" = @{ + VDIState = "Unchanged" + URL = "https://www.microsoft.com/en-us/p/windows-calculator/9wzdncrfhvn5" + Description = "Microsoft Calculator app" + } + + "Microsoft.WindowsCamera" = @{ + VDIState = "Unchanged" + URL = "https://www.microsoft.com/en-us/p/windows-camera/9wzdncrfjbbg" + Description = "Camera app to manage photos and video" + } + + "microsoft.windowscommunicationsapps" = @{ + VDIState = "Unchanged" + URL = "https://www.microsoft.com/en-us/p/mail-and-calendar/9wzdncrfhvqm" + Description = "Mail & Calendar apps" + } + + "Microsoft.WindowsFeedbackHub" = @{ + VDIState = "Unchanged" + URL = "https://www.microsoft.com/en-us/p/feedback-hub/9nblggh4r32n" + Description = "App to provide Feedback on Windows and apps to Microsoft" + } + + "Microsoft.WindowsMaps" = @{ + VDIState = "Unchanged" + URL = "https://www.microsoft.com/en-us/p/windows-maps/9wzdncrdtbvb" + Description = "Microsoft Maps app" + } + + "Microsoft.WindowsNotepad" = @{ + VDIState = "Unchanged" + URL = "https://www.microsoft.com/en-us/p/windows-notepad/9msmlrh6lzf3" + Description = "Fast, simple text editor for plain text documents and source code files." + } + + "Microsoft.WindowsStore" = @{ + VDIState = "Unchanged" + URL = "https://blogs.windows.com/windowsexperience/2021/06/24/building-a-new-open-microsoft-store-on-windows-11/" + Description = "Windows Store app" + } + + "Microsoft.WindowsSoundRecorder" = @{ + VDIState = "Unchanged" + URL = "https://www.microsoft.com/en-us/p/windows-voice-recorder/9wzdncrfhwkn" + Description = "(Voice recorder)" + } + + "Microsoft.WindowsTerminal" = @{ + VDIState = "Unchanged" + URL = "https://www.microsoft.com/en-us/p/windows-terminal/9n0dx20hk701" + Description = "A terminal app featuring tabs, panes, Unicode, UTF-8 character support, and a GPU text rendering engine." + } + + "Microsoft.Winget.Platform.Source" = @{ + VDIState = "Unchanged" + URL = "https://learn.microsoft.com/en-us/windows/package-manager/winget/" + Description = "The Winget tool enables users to manage applications on Win10 and Win11 devices. This tool is the client interface to the Windows Package Manager service" + } + + "Microsoft.Xbox.TCUI" = @{ + VDIState = "Unchanged" + URL = "https://docs.microsoft.com/en-us/gaming/xbox-live/features/general/tcui/live-tcui-overview" + Description = "XBox Title Callable UI (TCUI) enables your game code to call pre-defined user interface displays" + } + + "Microsoft.XboxIdentityProvider" = @{ + VDIState = "Unchanged" + URL = "https://www.microsoft.com/en-us/p/xbox-identity-provider/9wzdncrd1hkw" + Description = "A system app that enables PC games to connect to Xbox Live." + } + + "Microsoft.XboxSpeechToTextOverlay" = @{ + VDIState = "Unchanged" + URL = "https://support.xbox.com/help/account-profile/accessibility/use-game-chat-transcription" + Description = "Xbox game transcription overlay" + } + + "Microsoft.YourPhone" = @{ + VDIState = "Unchanged" + URL = "https://www.microsoft.com/en-us/p/Your-phone/9nmpj99vjbwv" + Description = "Android phone to PC device interface app" + } + + "Microsoft.ZuneMusic" = @{ + VDIState = "Unchanged" + URL = "https://www.microsoft.com/en-us/p/groove-music/9wzdncrfj3pt" + Description = "Groove Music app" + } + + "Microsoft.ZuneVideo" = @{ + VDIState = "Unchanged" + URL = "https://www.microsoft.com/en-us/p/movies-tv/9wzdncrfj3p2" + Description = "Movies and TV app" + } + + "MicrosoftCorporationII.QuickAssist" = @{ + VDIState = "Unchanged" + URL = "https://apps.microsoft.com/detail/9P7BP5VNWKX5?hl=en-us&gl=US" + Description = "Microsoft remote help app" + } + + "MicrosoftWindows.Client.WebExperience" = @{ + VDIState = "Unchanged" + URL = "" + Description = "Windows 11 Internet information widget" + } + + "Microsoft.XboxApp" = @{ + VDIState = "Unchanged" + URL = "https://www.microsoft.com/store/apps/9wzdncrfjbd8" + Description = "Xbox 'Console Companion' app (games, friends, etc.)" + } + + "Microsoft.MixedReality.Portal" = @{ + VDIState = "Unchanged" + URL = "https://www.microsoft.com/en-us/p/mixed-reality-portal/9ng1h8b3zc7m" + Description = "The app that facilitates Windows Mixed Reality setup, and serves as the command center for mixed reality experiences" + } + + "Microsoft.Microsoft3DViewer" = @{ + VDIState = "Unchanged" + URL = "https://www.microsoft.com/en-us/p/3d-viewer/9nblggh42ths" + Description = "App to view common 3D file types" + } + + "MicrosoftTeams" = @{ + VDIState = "Unchanged" + URL = "https://apps.microsoft.com/detail/xp8bt8dw290mpq" + Description = "Microsoft communication platform" + } + + "MSTeams" = @{ + VDIState = "Unchanged" + URL = "https://apps.microsoft.com/detail/xp8bt8dw290mpq" + Description = "Microsoft communication platform" + } + + "Microsoft.OneDriveSync" = @{ + VDIState = "Unchanged" + URL = "https://docs.microsoft.com/en-us/onedrive/one-drive-sync" + Description = "Microsoft OneDrive sync app (included in Office 2016 or later)" + } + + "Microsoft.Wallet" = @{ + VDIState = "Unchanged" + URL = "https://www.microsoft.com/en-us/payments" + Description = "(Microsoft Pay) for Edge browser on certain devices" + } +} + +foreach ($Key in $apps.Keys) { + $Item = $apps[$Key] + + Write-Host "Removing Provisioned Package $Key" + Get-AppxProvisionedPackage -Online | + Where-Object { $_.PackageName -like ("*{0}*" -f $Key) } | + Remove-AppxProvisionedPackage -Online -ErrorAction SilentlyContinue | + Out-Null + + Write-Host "Attempting to remove [All Users] $Key - $($Item.Description)" + Get-AppxPackage -AllUsers -Name ("*{0}*" -f $Key) | + Remove-AppxPackage -AllUsers -ErrorAction SilentlyContinue + + Write-Host "Attempting to remove $Key - $($Item.Description)" + Get-AppxPackage -Name ("*{0}*" -f $Key) | + Remove-AppxPackage -ErrorAction SilentlyContinue | + Out-Null +} diff --git a/modules/win_disable_services/files/appxpackages/uninstall.ps1 b/modules/win_disable_services/files/appxpackages/uninstall.ps1 index 4778d3e8e..e57faebc0 100644 --- a/modules/win_disable_services/files/appxpackages/uninstall.ps1 +++ b/modules/win_disable_services/files/appxpackages/uninstall.ps1 @@ -1,320 +1,406 @@ -$apps = @{ - "Bing Search" = @{ - VDIState = "Unchanged" - URL = "https://apps.microsoft.com/detail/9nzbf4gt040c" - Description = "Web Search from Microsoft Bing provides web results and answers in Windows Search" - } - - "Clipchamp.Clipchamp" = @{ - VDIState = "Unchanged" - URL = "https://apps.microsoft.com/detail/9p1j8s7ccwwt?hl=en-us&gl=US" - Description = "Create videos with a few clicks" - } - - "Microsoft.549981C3F5F10" = @{ - VDIState = "Unchanged" - URL = "https://apps.microsoft.com/detail/cortana/9NFFX4SZZ23L?hl=en-us&gl=US" - Description = "Cortana (could not update)" - } - - "Microsoft.BingNews" = @{ - VDIState = "Unchanged" - URL = "https://www.microsoft.com/en-us/p/microsoft-news/9wzdncrfhvfw" - Description = "Microsoft News app" - } - - "Microsoft.BingWeather" = @{ - VDIState = "Unchanged" - URL = "https://www.microsoft.com/en-us/p/msn-weather/9wzdncrfj3q2" - Description = "MSN Weather app" - } - - "Microsoft.DesktopAppInstaller" = @{ - VDIState = "Unchanged" - URL = "https://apps.microsoft.com/detail/9NBLGGH4NNS1" - Description = "Microsoft App Installer for Windows 10 makes sideloading Windows apps easy" - } - - "Microsoft.GetHelp" = @{ - VDIState = "Unchanged" - URL = "https://docs.microsoft.com/en-us/windows-hardware/customize/desktop/customize-get-help-app" - Description = "App that facilitates free support for Microsoft products" - } - - "Microsoft.Getstarted" = @{ - VDIState = "Unchanged" - URL = "https://www.microsoft.com/en-us/p/microsoft-tips/9wzdncrdtbjj" - Description = "Windows 10 tips app" - } - - "Microsoft.MicrosoftOfficeHub" = @{ - VDIState = "Unchanged" - URL = "https://www.microsoft.com/en-us/p/office/9wzdncrd29v9" - Description = "Office UWP app suite" - } - - "Microsoft.Office.OneNote" = @{ - VDIState = "Unchanged" - URL = "https://www.microsoft.com/en-us/p/onenote-for-windows-10/9wzdncrfhvjl" - Description = "Office UWP OneNote app" - } - - "Microsoft.MicrosoftSolitaireCollection" = @{ - VDIState = "Unchanged" - URL = "https://www.microsoft.com/en-us/p/microsoft-solitaire-collection/9wzdncrfhwd2" - Description = "Solitaire suite of games" - } - - "Microsoft.MicrosoftStickyNotes" = @{ - VDIState = "Unchanged" - URL = "https://www.microsoft.com/en-us/p/microsoft-sticky-notes/9nblggh4qghw" - Description = "Note-taking app" - } - - "Microsoft.OutlookForWindows" = @{ - VDIState = "Unchanged" - URL = "https://apps.microsoft.com/detail/9NRX63209R7B?hl=en-us&gl=US" - Description = "A best-in-class email experience that is free for anyone with Windows" - } - - "Microsoft.MSPaint" = @{ - VDIState = "Unchanged" - URL = "https://apps.microsoft.com/store/detail/paint-3d/9NBLGGH5FV99" - Description = "Paint 3D app (not Classic Paint app)" - } - - "Microsoft.Paint" = @{ - VDIState = "Unchanged" - URL = "https://apps.microsoft.com/detail/9PCFS5B6T72H" - Description = "Classic Paint app" - } - - "Microsoft.People" = @{ - VDIState = "Unchanged" - URL = "https://www.microsoft.com/en-us/p/microsoft-people/9nblggh10pg8" - Description = "Contact management app" - } - - "Microsoft.PowerAutomateDesktop" = @{ - VDIState = "Unchanged" - URL = "https://flow.microsoft.com/en-us/desktop/" - Description = "Power Automate Desktop app. Record desktop and web actions in a single flow" - } - - "Microsoft.ScreenSketch" = @{ - VDIState = "Unchanged" - URL = "https://www.microsoft.com/en-us/p/snip-sketch/9mz95kl8mr0l" - Description = "Snip and Sketch app" - } - - "Microsoft.SkypeApp" = @{ - VDIState = "Unchanged" - URL = "https://www.microsoft.com/en-us/p/skype/9wzdncrfj364" - Description = "Instant message, voice or video call app" - } - - "Microsoft.StorePurchaseApp" = @{ - VDIState = "Unchanged" - URL = "" - Description = "Store purchase app helper" - } - - "Microsoft.Todos" = @{ - VDIState = "Unchanged" - URL = "https://www.microsoft.com/en-us/p/microsoft-to-do-lists-tasks-reminders/9nblggh5r558" - Description = "Microsoft To Do makes it easy to plan your day and manage your life" - } - - "Microsoft.WinDbg.Fast" = @{ - VDIState = "Unchanged" - URL = "https://apps.microsoft.com/detail/9PGJGD53TN86?hl=en-us&gl=US" - Description = "Microsoft WinDbg" - } - - "Microsoft.Windows.DevHome" = @{ - VDIState = "Unchanged" - URL = "https://learn.microsoft.com/en-us/windows/dev-home/" - Description = "A control center providing the ability to monitor projects in your dashboard using customizable widgets and more" - } - - "Microsoft.Windows.Photos" = @{ - VDIState = "Unchanged" - URL = "https://www.microsoft.com/en-us/p/microsoft-photos/9wzdncrfjbh4" - Description = "Photo and video editor" - } - - "Microsoft.WindowsAlarms" = @{ - VDIState = "Unchanged" - URL = "https://www.microsoft.com/en-us/p/windows-alarms-clock/9wzdncrfj3pr" - Description = "A combination app of alarm clock, world clock, timer, and stopwatch." - } - - "Microsoft.WindowsCalculator" = @{ - VDIState = "Unchanged" - URL = "https://www.microsoft.com/en-us/p/windows-calculator/9wzdncrfhvn5" - Description = "Microsoft Calculator app" - } - - "Microsoft.WindowsCamera" = @{ - VDIState = "Unchanged" - URL = "https://www.microsoft.com/en-us/p/windows-camera/9wzdncrfjbbg" - Description = "Camera app to manage photos and video" - } - - "microsoft.windowscommunicationsapps" = @{ - VDIState = "Unchanged" - URL = "https://www.microsoft.com/en-us/p/mail-and-calendar/9wzdncrfhvqm" - Description = "Mail & Calendar apps" +#requires -RunAsAdministrator +<# + Lab-only Windows 11 24H2 hardening: + + - Remove a predefined set of AppX packages (inlined from ronin uninstall.ps1) + - Disable AppXSvc (service + registry Start=4) + - Install startup scheduled task (SYSTEM) to re-enforce disable every boot + - Validate AppXSvc is disabled; exit 0 on success, 1 on failure +#> + +$ErrorActionPreference = 'Stop' + +$svcName = 'AppXSvc' +$svcKeyPath = 'HKLM:\SYSTEM\CurrentControlSet\Services\AppXSvc' + +function Remove-PreinstalledAppxPackages { + [CmdletBinding()] + param() + + # Inlined from ronin_puppet win_disable_services appxpackages/uninstall.ps1, + # with Write-Host converted to Write-Verbose to reduce noise. + $apps = @{ + "Bing Search" = @{ + VDIState = "Unchanged" + URL = "https://apps.microsoft.com/detail/9nzbf4gt040c" + Description = "Web Search from Microsoft Bing provides web results and answers in Windows Search" + } + "Clipchamp.Clipchamp" = @{ + VDIState = "Unchanged" + URL = "https://apps.microsoft.com/detail/9p1j8s7ccwwt?hl=en-us&gl=US" + Description = "Create videos with a few clicks" + } + "Microsoft.549981C3F5F10" = @{ + VDIState = "Unchanged" + URL = "https://apps.microsoft.com/detail/cortana/9NFFX4SZZ23L?hl=en-us&gl=US" + Description = "Cortana (could not update)" + } + "Microsoft.BingNews" = @{ + VDIState = "Unchanged" + URL = "https://www.microsoft.com/en-us/p/microsoft-news/9wzdncrfhvfw" + Description = "Microsoft News app" + } + "Microsoft.BingWeather" = @{ + VDIState = "Unchanged" + URL = "https://www.microsoft.com/en-us/p/msn-weather/9wzdncrfj3q2" + Description = "MSN Weather app" + } + "Microsoft.DesktopAppInstaller" = @{ + VDIState = "Unchanged" + URL = "https://apps.microsoft.com/detail/9NBLGGH4NNS1" + Description = "Microsoft App Installer for Windows 10 makes sideloading Windows apps easy" + } + "Microsoft.GetHelp" = @{ + VDIState = "Unchanged" + URL = "https://docs.microsoft.com/en-us/windows-hardware/customize/desktop/customize-get-help-app" + Description = "App that facilitates free support for Microsoft products" + } + "Microsoft.Getstarted" = @{ + VDIState = "Unchanged" + URL = "https://www.microsoft.com/en-us/p/microsoft-tips/9wzdncrdtbjj" + Description = "Windows 10 tips app" + } + "Microsoft.MicrosoftOfficeHub" = @{ + VDIState = "Unchanged" + URL = "https://www.microsoft.com/en-us/p/office/9wzdncrd29v9" + Description = "Office UWP app suite" + } + "Microsoft.Office.OneNote" = @{ + VDIState = "Unchanged" + URL = "https://www.microsoft.com/en-us/p/onenote-for-windows-10/9wzdncrfhvjl" + Description = "Office UWP OneNote app" + } + "Microsoft.MicrosoftSolitaireCollection" = @{ + VDIState = "Unchanged" + URL = "https://www.microsoft.com/en-us/p/microsoft-solitaire-collection/9wzdncrfhwd2" + Description = "Solitaire suite of games" + } + "Microsoft.MicrosoftStickyNotes" = @{ + VDIState = "Unchanged" + URL = "https://www.microsoft.com/en-us/p/microsoft-sticky-notes/9nblggh4qghw" + Description = "Note-taking app" + } + "Microsoft.OutlookForWindows" = @{ + VDIState = "Unchanged" + URL = "https://apps.microsoft.com/detail/9NRX63209R7B?hl=en-us&gl=US" + Description = "A best-in-class email experience that is free for anyone with Windows" + } + "Microsoft.MSPaint" = @{ + VDIState = "Unchanged" + URL = "https://apps.microsoft.com/store/detail/paint-3d/9NBLGGH5FV99" + Description = "Paint 3D app (not Classic Paint app)" + } + "Microsoft.Paint" = @{ + VDIState = "Unchanged" + URL = "https://apps.microsoft.com/detail/9PCFS5B6T72H" + Description = "Classic Paint app" + } + "Microsoft.People" = @{ + VDIState = "Unchanged" + URL = "https://www.microsoft.com/en-us/p/microsoft-people/9nblggh10pg8" + Description = "Contact management app" + } + "Microsoft.PowerAutomateDesktop" = @{ + VDIState = "Unchanged" + URL = "https://flow.microsoft.com/en-us/desktop/" + Description = "Power Automate Desktop app. Record desktop and web actions in a single flow" + } + "Microsoft.ScreenSketch" = @{ + VDIState = "Unchanged" + URL = "https://www.microsoft.com/en-us/p/snip-sketch/9mz95kl8mr0l" + Description = "Snip and Sketch app" + } + "Microsoft.SkypeApp" = @{ + VDIState = "Unchanged" + URL = "https://www.microsoft.com/en-us/p/skype/9wzdncrfj364" + Description = "Instant message, voice or video call app" + } + "Microsoft.StorePurchaseApp" = @{ + VDIState = "Unchanged" + URL = "" + Description = "Store purchase app helper" + } + "Microsoft.Todos" = @{ + VDIState = "Unchanged" + URL = "https://www.microsoft.com/en-us/p/microsoft-to-do-lists-tasks-reminders/9nblggh5r558" + Description = "Microsoft To Do makes it easy to plan your day and manage your life" + } + "Microsoft.WinDbg.Fast" = @{ + VDIState = "Unchanged" + URL = "https://apps.microsoft.com/detail/9PGJGD53TN86?hl=en-us&gl=US" + Description = "Microsoft WinDbg" + } + "Microsoft.Windows.DevHome" = @{ + VDIState = "Unchanged" + URL = "https://learn.microsoft.com/en-us/windows/dev-home/" + Description = "A control center providing the ability to monitor projects in your dashboard using customizable widgets and more" + } + "Microsoft.Windows.Photos" = @{ + VDIState = "Unchanged" + URL = "https://www.microsoft.com/en-us/p/microsoft-photos/9wzdncrfjbh4" + Description = "Photo and video editor" + } + "Microsoft.WindowsAlarms" = @{ + VDIState = "Unchanged" + URL = "https://www.microsoft.com/en-us/p/windows-alarms-clock/9wzdncrfj3pr" + Description = "A combination app of alarm clock, world clock, timer, and stopwatch." + } + "Microsoft.WindowsCalculator" = @{ + VDIState = "Unchanged" + URL = "https://www.microsoft.com/en-us/p/windows-calculator/9wzdncrfhvn5" + Description = "Microsoft Calculator app" + } + "Microsoft.WindowsCamera" = @{ + VDIState = "Unchanged" + URL = "https://www.microsoft.com/en-us/p/windows-camera/9wzdncrfjbbg" + Description = "Camera app to manage photos and video" + } + "microsoft.windowscommunicationsapps" = @{ + VDIState = "Unchanged" + URL = "https://www.microsoft.com/en-us/p/mail-and-calendar/9wzdncrfhvqm" + Description = "Mail & Calendar apps" + } + "Microsoft.WindowsFeedbackHub" = @{ + VDIState = "Unchanged" + URL = "https://www.microsoft.com/en-us/p/feedback-hub/9nblggh4r32n" + Description = "App to provide Feedback on Windows and apps to Microsoft" + } + "Microsoft.WindowsMaps" = @{ + VDIState = "Unchanged" + URL = "https://www.microsoft.com/en-us/p/windows-maps/9wzdncrdtbvb" + Description = "Microsoft Maps app" + } + "Microsoft.WindowsNotepad" = @{ + VDIState = "Unchanged" + URL = "https://www.microsoft.com/en-us/p/windows-notepad/9msmlrh6lzf3" + Description = "Fast, simple text editor for plain text documents and source code files." + } + "Microsoft.WindowsStore" = @{ + VDIState = "Unchanged" + URL = "https://blogs.windows.com/windowsexperience/2021/06/24/building-a-new-open-microsoft-store-on-windows-11/" + Description = "Windows Store app" + } + "Microsoft.WindowsSoundRecorder" = @{ + VDIState = "Unchanged" + URL = "https://www.microsoft.com/en-us/p/windows-voice-recorder/9wzdncrfhwkn" + Description = "(Voice recorder)" + } + "Microsoft.WindowsTerminal" = @{ + VDIState = "Unchanged" + URL = "https://www.microsoft.com/en-us/p/windows-terminal/9n0dx20hk701" + Description = "A terminal app featuring tabs, panes, Unicode, UTF-8 character support, and a GPU text rendering engine." + } + "Microsoft.Winget.Platform.Source" = @{ + VDIState = "Unchanged" + URL = "https://learn.microsoft.com/en-us/windows/package-manager/winget/" + Description = "The Winget tool enables users to manage applications on Win10 and Win11 devices. This tool is the client interface to the Windows Package Manager service" + } + "Microsoft.Xbox.TCUI" = @{ + VDIState = "Unchanged" + URL = "https://docs.microsoft.com/en-us/gaming/xbox-live/features/general/tcui/live-tcui-overview" + Description = "XBox Title Callable UI (TCUI) enables your game code to call pre-defined user interface displays" + } + "Microsoft.XboxIdentityProvider" = @{ + VDIState = "Unchanged" + URL = "https://www.microsoft.com/en-us/p/xbox-identity-provider/9wzdncrd1hkw" + Description = "A system app that enables PC games to connect to Xbox Live." + } + "Microsoft.XboxSpeechToTextOverlay" = @{ + VDIState = "Unchanged" + URL = "https://support.xbox.com/help/account-profile/accessibility/use-game-chat-transcription" + Description = "Xbox game transcription overlay" + } + "Microsoft.YourPhone" = @{ + VDIState = "Unchanged" + URL = "https://www.microsoft.com/en-us/p/Your-phone/9nmpj99vjbwv" + Description = "Android phone to PC device interface app" + } + "Microsoft.ZuneMusic" = @{ + VDIState = "Unchanged" + URL = "https://www.microsoft.com/en-us/p/groove-music/9wzdncrfj3pt" + Description = "Groove Music app" + } + "Microsoft.ZuneVideo" = @{ + VDIState = "Unchanged" + URL = "https://www.microsoft.com/en-us/p/movies-tv/9wzdncrfj3p2" + Description = "Movies and TV app" + } + "MicrosoftCorporationII.QuickAssist" = @{ + VDIState = "Unchanged" + URL = "https://apps.microsoft.com/detail/9P7BP5VNWKX5?hl=en-us&gl=US" + Description = "Microsoft remote help app" + } + "MicrosoftWindows.Client.WebExperience" = @{ + VDIState = "Unchanged" + URL = "" + Description = "Windows 11 Internet information widget" + } + "Microsoft.XboxApp" = @{ + VDIState = "Unchanged" + URL = "https://www.microsoft.com/store/apps/9wzdncrfjbd8" + Description = "Xbox 'Console Companion' app (games, friends, etc.)" + } + "Microsoft.MixedReality.Portal" = @{ + VDIState = "Unchanged" + URL = "https://www.microsoft.com/en-us/p/mixed-reality-portal/9ng1h8b3zc7m" + Description = "The app that facilitates Windows Mixed Reality setup, and serves as the command center for mixed reality experiences" + } + "Microsoft.Microsoft3DViewer" = @{ + VDIState = "Unchanged" + URL = "https://www.microsoft.com/en-us/p/3d-viewer/9nblggh42ths" + Description = "App to view common 3D file types" + } + "MicrosoftTeams" = @{ + VDIState = "Unchanged" + URL = "https://apps.microsoft.com/detail/xp8bt8dw290mpq" + Description = "Microsoft communication platform" + } + "MSTeams" = @{ + VDIState = "Unchanged" + URL = "https://apps.microsoft.com/detail/xp8bt8dw290mpq" + Description = "Microsoft communication platform" + } + "Microsoft.OneDriveSync" = @{ + VDIState = "Unchanged" + URL = "https://docs.microsoft.com/en-us/onedrive/one-drive-sync" + Description = "Microsoft OneDrive sync app (included in Office 2016 or later)" + } + "Microsoft.Wallet" = @{ + VDIState = "Unchanged" + URL = "https://www.microsoft.com/en-us/payments" + Description = "(Microsoft Pay) for Edge browser on certain devices" + } + } + + foreach ($Key in $apps.Keys) { + $Item = $apps[$Key] + + Write-Verbose "Removing Provisioned Package $Key" + Get-AppxProvisionedPackage -Online | + Where-Object { $_.PackageName -like ("*{0}*" -f $Key) } | + Remove-AppxProvisionedPackage -Online -ErrorAction SilentlyContinue | + Out-Null + + Write-Verbose "Attempting to remove [All Users] $Key - $($Item.Description)" + Get-AppxPackage -AllUsers -Name ("*{0}*" -f $Key) | + Remove-AppxPackage -AllUsers -ErrorAction SilentlyContinue + + Write-Verbose "Attempting to remove $Key - $($Item.Description)" + Get-AppxPackage -Name ("*{0}*" -f $Key) | + Remove-AppxPackage -ErrorAction SilentlyContinue | + Out-Null } +} - "Microsoft.WindowsFeedbackHub" = @{ - VDIState = "Unchanged" - URL = "https://www.microsoft.com/en-us/p/feedback-hub/9nblggh4r32n" - Description = "App to provide Feedback on Windows and apps to Microsoft" - } +function Disable-AppXSvcCore { + [CmdletBinding()] + param() - "Microsoft.WindowsMaps" = @{ - VDIState = "Unchanged" - URL = "https://www.microsoft.com/en-us/p/windows-maps/9wzdncrdtbvb" - Description = "Microsoft Maps app" + # Stop + disable via SCM + $svc = Get-Service -Name $svcName -ErrorAction SilentlyContinue + if ($null -ne $svc) { + if ($svc.Status -ne 'Stopped') { + Stop-Service -Name $svcName -Force -ErrorAction SilentlyContinue + } + Set-Service -Name $svcName -StartupType Disabled -ErrorAction SilentlyContinue } - "Microsoft.WindowsNotepad" = @{ - VDIState = "Unchanged" - URL = "https://www.microsoft.com/en-us/p/windows-notepad/9msmlrh6lzf3" - Description = "Fast, simple text editor for plain text documents and source code files." - } - - "Microsoft.WindowsStore" = @{ - VDIState = "Unchanged" - URL = "https://blogs.windows.com/windowsexperience/2021/06/24/building-a-new-open-microsoft-store-on-windows-11/" - Description = "Windows Store app" + # Registry Start=4 + if (Test-Path $svcKeyPath) { + New-ItemProperty -Path $svcKeyPath -Name Start -Value 4 -PropertyType DWord -Force | Out-Null } +} - "Microsoft.WindowsSoundRecorder" = @{ - VDIState = "Unchanged" - URL = "https://www.microsoft.com/en-us/p/windows-voice-recorder/9wzdncrfhwkn" - Description = "(Voice recorder)" - } +function Ensure-AppXSvcHardeningTask { + [CmdletBinding()] + param() - "Microsoft.WindowsTerminal" = @{ - VDIState = "Unchanged" - URL = "https://www.microsoft.com/en-us/p/windows-terminal/9n0dx20hk701" - Description = "A terminal app featuring tabs, panes, Unicode, UTF-8 character support, and a GPU text rendering engine." - } + $hardeningDir = 'C:\ProgramData\AppXLock' + $hardeningFile = Join-Path $hardeningDir 'Disable-AppXSvc.ps1' - "Microsoft.Winget.Platform.Source" = @{ - VDIState = "Unchanged" - URL = "https://learn.microsoft.com/en-us/windows/package-manager/winget/" - Description = "The Winget tool enables users to manage applications on Win10 and Win11 devices. This tool is the client interface to the Windows Package Manager service" + if (-not (Test-Path $hardeningDir)) { + New-Item -ItemType Directory -Path $hardeningDir -Force | Out-Null } - "Microsoft.Xbox.TCUI" = @{ - VDIState = "Unchanged" - URL = "https://docs.microsoft.com/en-us/gaming/xbox-live/features/general/tcui/live-tcui-overview" - Description = "XBox Title Callable UI (TCUI) enables your game code to call pre-defined user interface displays" - } + $hardeningScript = @' +param() - "Microsoft.XboxIdentityProvider" = @{ - VDIState = "Unchanged" - URL = "https://www.microsoft.com/en-us/p/xbox-identity-provider/9wzdncrd1hkw" - Description = "A system app that enables PC games to connect to Xbox Live." - } +$ErrorActionPreference = "SilentlyContinue" - "Microsoft.XboxSpeechToTextOverlay" = @{ - VDIState = "Unchanged" - URL = "https://support.xbox.com/help/account-profile/accessibility/use-game-chat-transcription" - Description = "Xbox game transcription overlay" - } +$svcName = "AppXSvc" +$svcKeyPath = "HKLM:\\SYSTEM\\CurrentControlSet\\Services\\AppXSvc" - "Microsoft.YourPhone" = @{ - VDIState = "Unchanged" - URL = "https://www.microsoft.com/en-us/p/Your-phone/9nmpj99vjbwv" - Description = "Android phone to PC device interface app" +try { + $svc = Get-Service -Name $svcName -ErrorAction SilentlyContinue + if ($null -ne $svc) { + if ($svc.Status -ne "Stopped") { + Stop-Service -Name $svcName -Force -ErrorAction SilentlyContinue + } + Set-Service -Name $svcName -StartupType Disabled -ErrorAction SilentlyContinue } - "Microsoft.ZuneMusic" = @{ - VDIState = "Unchanged" - URL = "https://www.microsoft.com/en-us/p/groove-music/9wzdncrfj3pt" - Description = "Groove Music app" + if (Test-Path $svcKeyPath) { + New-ItemProperty -Path $svcKeyPath -Name Start -Value 4 -PropertyType DWord -Force | Out-Null } +} catch { + # best-effort only +} +'@ - "Microsoft.ZuneVideo" = @{ - VDIState = "Unchanged" - URL = "https://www.microsoft.com/en-us/p/movies-tv/9wzdncrfj3p2" - Description = "Movies and TV app" - } + Set-Content -Path $hardeningFile -Value $hardeningScript -Encoding UTF8 -Force - "MicrosoftCorporationII.QuickAssist" = @{ - VDIState = "Unchanged" - URL = "https://apps.microsoft.com/detail/9P7BP5VNWKX5?hl=en-us&gl=US" - Description = "Microsoft remote help app" - } + $action = New-ScheduledTaskAction -Execute 'powershell.exe' ` + -Argument "-NoLogo -NonInteractive -WindowStyle Hidden -ExecutionPolicy Bypass -File `"$hardeningFile`"" + $trigger = New-ScheduledTaskTrigger -AtStartup - "MicrosoftWindows.Client.WebExperience" = @{ - VDIState = "Unchanged" - URL = "" - Description = "Windows 11 Internet information widget" - } + $taskName = 'Hard-Disable-AppXSvc' + $taskPath = '\Hardening\' - "Microsoft.XboxApp" = @{ - VDIState = "Unchanged" - URL = "https://www.microsoft.com/store/apps/9wzdncrfjbd8" - Description = "Xbox 'Console Companion' app (games, friends, etc.)" - } + Unregister-ScheduledTask -TaskName $taskName -TaskPath $taskPath -Confirm:$false -ErrorAction SilentlyContinue - "Microsoft.MixedReality.Portal" = @{ - VDIState = "Unchanged" - URL = "https://www.microsoft.com/en-us/p/mixed-reality-portal/9ng1h8b3zc7m" - Description = "The app that facilitates Windows Mixed Reality setup, and serves as the command center for mixed reality experiences" - } + Register-ScheduledTask -TaskName $taskName ` + -TaskPath $taskPath ` + -Action $action ` + -Trigger $trigger ` + -RunLevel Highest ` + -User 'SYSTEM' ` + -Force | Out-Null +} - "Microsoft.Microsoft3DViewer" = @{ - VDIState = "Unchanged" - URL = "https://www.microsoft.com/en-us/p/3d-viewer/9nblggh42ths" - Description = "App to view common 3D file types" - } +function Test-AppXSvcDisabled { + [CmdletBinding()] + param() - "MicrosoftTeams" = @{ - VDIState = "Unchanged" - URL = "https://apps.microsoft.com/detail/xp8bt8dw290mpq" - Description = "Microsoft communication platform" - } + # Returns $true if AppXSvc is either: + # - Not present (already gone) + # - Present, Stopped, and StartType Disabled + $svc = Get-Service -Name $svcName -ErrorAction SilentlyContinue - "MSTeams" = @{ - VDIState = "Unchanged" - URL = "https://apps.microsoft.com/detail/xp8bt8dw290mpq" - Description = "Microsoft communication platform" + if ($null -eq $svc) { + return $true } - "Microsoft.OneDriveSync" = @{ - VDIState = "Unchanged" - URL = "https://docs.microsoft.com/en-us/onedrive/one-drive-sync" - Description = "Microsoft OneDrive sync app (included in Office 2016 or later)" + $startType = $svc.StartType.ToString() + if ($svc.Status -eq 'Stopped' -and $startType -eq 'Disabled') { + return $true } - "Microsoft.Wallet" = @{ - VDIState = "Unchanged" - URL = "https://www.microsoft.com/en-us/payments" - Description = "(Microsoft Pay) for Edge browser on certain devices" - } + return $false } -foreach ($Key in $apps.Keys) { - $Item = $apps[$Key] +# --- Main flow --------------------------------------------------------------- - Write-Host "Removing Provisioned Package $Key" - Get-AppxProvisionedPackage -Online | - Where-Object { $_.PackageName -like ("*{0}*" -f $Key) } | - Remove-AppxProvisionedPackage -Online -ErrorAction SilentlyContinue | - Out-Null +Remove-PreinstalledAppxPackages # Inlined ronin uninstall logic +Disable-AppXSvcCore # Stop, disable, set Start=4 +Ensure-AppXSvcHardeningTask # Re-enforce on every boot - Write-Host "Attempting to remove [All Users] $Key - $($Item.Description)" - Get-AppxPackage -AllUsers -Name ("*{0}*" -f $Key) | - Remove-AppxPackage -AllUsers -ErrorAction SilentlyContinue +if (-not (Test-AppXSvcDisabled)) { + $svc = Get-Service -Name $svcName -ErrorAction SilentlyContinue + $status = if ($svc) { $svc.Status } else { 'Missing' } + $startType = if ($svc) { $svc.StartType } else { 'Missing' } - Write-Host "Attempting to remove $Key - $($Item.Description)" - Get-AppxPackage -Name ("*{0}*" -f $Key) | - Remove-AppxPackage -ErrorAction SilentlyContinue | - Out-Null + Write-Error "AppXSvc is NOT disabled. Status: $status, StartType: $startType" + exit 1 } + +exit 0 diff --git a/modules/win_disable_services/manifests/disable_optional_services.pp b/modules/win_disable_services/manifests/disable_optional_services.pp index cf667a56c..98b45c358 100644 --- a/modules/win_disable_services/manifests/disable_optional_services.pp +++ b/modules/win_disable_services/manifests/disable_optional_services.pp @@ -36,7 +36,7 @@ # --- UWP / Microsoft Store ecosystem --- 'AppReadiness', # App readiness - 'AppXSvc', # AppX Deployment Service +# 'AppXSvc', # AppX Deployment Service - won't disable # 'CDPSvc', # Connected Devices Platform Service - DON'T Disable. # 'ClipSVC', # Client License Service (Store licensing) - DON'T Disable. # 'CoreMessagingRegistrar', # CoreMessaging - won't disable From f1368305cb35283d4eb99cdd5f035a09ee191901 Mon Sep 17 00:00:00 2001 From: Mark Cornmesser Date: Fri, 19 Dec 2025 12:44:23 -0800 Subject: [PATCH 041/105] disable apx service --- .../files/appxpackages/uninstall.ps1 | 94 +++++++++---------- 1 file changed, 43 insertions(+), 51 deletions(-) diff --git a/modules/win_disable_services/files/appxpackages/uninstall.ps1 b/modules/win_disable_services/files/appxpackages/uninstall.ps1 index e57faebc0..67f1649ea 100644 --- a/modules/win_disable_services/files/appxpackages/uninstall.ps1 +++ b/modules/win_disable_services/files/appxpackages/uninstall.ps1 @@ -1,12 +1,10 @@ #requires -RunAsAdministrator -<# - Lab-only Windows 11 24H2 hardening: - - Remove a predefined set of AppX packages (inlined from ronin uninstall.ps1) - - Disable AppXSvc (service + registry Start=4) - - Install startup scheduled task (SYSTEM) to re-enforce disable every boot - - Validate AppXSvc is disabled; exit 0 on success, 1 on failure -#> +# Lab-only Windows 11 24H2 hardening: +# - Remove predefined AppX packages (inlined from ronin uninstall.ps1) +# - Disable AppXSvc (service + registry Start=4) +# - Install startup scheduled task (SYSTEM) to re-enforce disable every boot +# - Validate AppXSvc is disabled; exit 0 on success, 1 on failure $ErrorActionPreference = 'Stop' @@ -17,8 +15,6 @@ function Remove-PreinstalledAppxPackages { [CmdletBinding()] param() - # Inlined from ronin_puppet win_disable_services appxpackages/uninstall.ps1, - # with Write-Host converted to Write-Verbose to reduce noise. $apps = @{ "Bing Search" = @{ VDIState = "Unchanged" @@ -133,7 +129,7 @@ function Remove-PreinstalledAppxPackages { "Microsoft.Windows.DevHome" = @{ VDIState = "Unchanged" URL = "https://learn.microsoft.com/en-us/windows/dev-home/" - Description = "A control center providing the ability to monitor projects in your dashboard using customizable widgets and more" + Description = "Dev Home dashboard" } "Microsoft.Windows.Photos" = @{ VDIState = "Unchanged" @@ -143,7 +139,7 @@ function Remove-PreinstalledAppxPackages { "Microsoft.WindowsAlarms" = @{ VDIState = "Unchanged" URL = "https://www.microsoft.com/en-us/p/windows-alarms-clock/9wzdncrfj3pr" - Description = "A combination app of alarm clock, world clock, timer, and stopwatch." + Description = "Alarms, world clock, timer, stopwatch" } "Microsoft.WindowsCalculator" = @{ VDIState = "Unchanged" @@ -153,7 +149,7 @@ function Remove-PreinstalledAppxPackages { "Microsoft.WindowsCamera" = @{ VDIState = "Unchanged" URL = "https://www.microsoft.com/en-us/p/windows-camera/9wzdncrfjbbg" - Description = "Camera app to manage photos and video" + Description = "Camera app" } "microsoft.windowscommunicationsapps" = @{ VDIState = "Unchanged" @@ -163,7 +159,7 @@ function Remove-PreinstalledAppxPackages { "Microsoft.WindowsFeedbackHub" = @{ VDIState = "Unchanged" URL = "https://www.microsoft.com/en-us/p/feedback-hub/9nblggh4r32n" - Description = "App to provide Feedback on Windows and apps to Microsoft" + Description = "Feedback Hub" } "Microsoft.WindowsMaps" = @{ VDIState = "Unchanged" @@ -173,7 +169,7 @@ function Remove-PreinstalledAppxPackages { "Microsoft.WindowsNotepad" = @{ VDIState = "Unchanged" URL = "https://www.microsoft.com/en-us/p/windows-notepad/9msmlrh6lzf3" - Description = "Fast, simple text editor for plain text documents and source code files." + Description = "Notepad (Store version)" } "Microsoft.WindowsStore" = @{ VDIState = "Unchanged" @@ -183,109 +179,110 @@ function Remove-PreinstalledAppxPackages { "Microsoft.WindowsSoundRecorder" = @{ VDIState = "Unchanged" URL = "https://www.microsoft.com/en-us/p/windows-voice-recorder/9wzdncrfhwkn" - Description = "(Voice recorder)" + Description = "Voice recorder" } "Microsoft.WindowsTerminal" = @{ VDIState = "Unchanged" URL = "https://www.microsoft.com/en-us/p/windows-terminal/9n0dx20hk701" - Description = "A terminal app featuring tabs, panes, Unicode, UTF-8 character support, and a GPU text rendering engine." + Description = "Windows Terminal" } "Microsoft.Winget.Platform.Source" = @{ VDIState = "Unchanged" URL = "https://learn.microsoft.com/en-us/windows/package-manager/winget/" - Description = "The Winget tool enables users to manage applications on Win10 and Win11 devices. This tool is the client interface to the Windows Package Manager service" + Description = "Winget (Windows Package Manager) source" } "Microsoft.Xbox.TCUI" = @{ VDIState = "Unchanged" URL = "https://docs.microsoft.com/en-us/gaming/xbox-live/features/general/tcui/live-tcui-overview" - Description = "XBox Title Callable UI (TCUI) enables your game code to call pre-defined user interface displays" + Description = "Xbox Title Callable UI" } "Microsoft.XboxIdentityProvider" = @{ VDIState = "Unchanged" URL = "https://www.microsoft.com/en-us/p/xbox-identity-provider/9wzdncrd1hkw" - Description = "A system app that enables PC games to connect to Xbox Live." + Description = "Xbox Identity Provider" } "Microsoft.XboxSpeechToTextOverlay" = @{ VDIState = "Unchanged" URL = "https://support.xbox.com/help/account-profile/accessibility/use-game-chat-transcription" - Description = "Xbox game transcription overlay" + Description = "Xbox game chat transcription" } "Microsoft.YourPhone" = @{ VDIState = "Unchanged" URL = "https://www.microsoft.com/en-us/p/Your-phone/9nmpj99vjbwv" - Description = "Android phone to PC device interface app" + Description = "Phone Link" } "Microsoft.ZuneMusic" = @{ VDIState = "Unchanged" URL = "https://www.microsoft.com/en-us/p/groove-music/9wzdncrfj3pt" - Description = "Groove Music app" + Description = "Groove Music" } "Microsoft.ZuneVideo" = @{ VDIState = "Unchanged" URL = "https://www.microsoft.com/en-us/p/movies-tv/9wzdncrfj3p2" - Description = "Movies and TV app" + Description = "Movies & TV" } "MicrosoftCorporationII.QuickAssist" = @{ VDIState = "Unchanged" URL = "https://apps.microsoft.com/detail/9P7BP5VNWKX5?hl=en-us&gl=US" - Description = "Microsoft remote help app" + Description = "Quick Assist" } "MicrosoftWindows.Client.WebExperience" = @{ VDIState = "Unchanged" URL = "" - Description = "Windows 11 Internet information widget" + Description = "Windows 11 Widgets / Web Experience" } "Microsoft.XboxApp" = @{ VDIState = "Unchanged" URL = "https://www.microsoft.com/store/apps/9wzdncrfjbd8" - Description = "Xbox 'Console Companion' app (games, friends, etc.)" + Description = "Xbox Console Companion" } "Microsoft.MixedReality.Portal" = @{ VDIState = "Unchanged" URL = "https://www.microsoft.com/en-us/p/mixed-reality-portal/9ng1h8b3zc7m" - Description = "The app that facilitates Windows Mixed Reality setup, and serves as the command center for mixed reality experiences" + Description = "Mixed Reality Portal" } "Microsoft.Microsoft3DViewer" = @{ VDIState = "Unchanged" URL = "https://www.microsoft.com/en-us/p/3d-viewer/9nblggh42ths" - Description = "App to view common 3D file types" + Description = "3D Viewer" } "MicrosoftTeams" = @{ VDIState = "Unchanged" URL = "https://apps.microsoft.com/detail/xp8bt8dw290mpq" - Description = "Microsoft communication platform" + Description = "Microsoft Teams" } "MSTeams" = @{ VDIState = "Unchanged" URL = "https://apps.microsoft.com/detail/xp8bt8dw290mpq" - Description = "Microsoft communication platform" + Description = "Microsoft Teams (alt id)" } "Microsoft.OneDriveSync" = @{ VDIState = "Unchanged" URL = "https://docs.microsoft.com/en-us/onedrive/one-drive-sync" - Description = "Microsoft OneDrive sync app (included in Office 2016 or later)" + Description = "OneDrive sync app" } "Microsoft.Wallet" = @{ VDIState = "Unchanged" URL = "https://www.microsoft.com/en-us/payments" - Description = "(Microsoft Pay) for Edge browser on certain devices" + Description = "Microsoft Pay" } } foreach ($Key in $apps.Keys) { $Item = $apps[$Key] - Write-Verbose "Removing Provisioned Package $Key" + # Provisioned (for new users) Get-AppxProvisionedPackage -Online | Where-Object { $_.PackageName -like ("*{0}*" -f $Key) } | Remove-AppxProvisionedPackage -Online -ErrorAction SilentlyContinue | Out-Null - Write-Verbose "Attempting to remove [All Users] $Key - $($Item.Description)" + # All users Get-AppxPackage -AllUsers -Name ("*{0}*" -f $Key) | - Remove-AppxPackage -AllUsers -ErrorAction SilentlyContinue + Remove-AppxPackage -AllUsers -ErrorAction SilentlyContinue | + Out-Null - Write-Verbose "Attempting to remove $Key - $($Item.Description)" + # Current user Get-AppxPackage -Name ("*{0}*" -f $Key) | Remove-AppxPackage -ErrorAction SilentlyContinue | Out-Null @@ -296,7 +293,6 @@ function Disable-AppXSvcCore { [CmdletBinding()] param() - # Stop + disable via SCM $svc = Get-Service -Name $svcName -ErrorAction SilentlyContinue if ($null -ne $svc) { if ($svc.Status -ne 'Stopped') { @@ -305,7 +301,6 @@ function Disable-AppXSvcCore { Set-Service -Name $svcName -StartupType Disabled -ErrorAction SilentlyContinue } - # Registry Start=4 if (Test-Path $svcKeyPath) { New-ItemProperty -Path $svcKeyPath -Name Start -Value 4 -PropertyType DWord -Force | Out-Null } @@ -359,21 +354,18 @@ try { Unregister-ScheduledTask -TaskName $taskName -TaskPath $taskPath -Confirm:$false -ErrorAction SilentlyContinue Register-ScheduledTask -TaskName $taskName ` - -TaskPath $taskPath ` - -Action $action ` - -Trigger $trigger ` - -RunLevel Highest ` - -User 'SYSTEM' ` - -Force | Out-Null + -TaskPath $taskPath ` + -Action $action ` + -Trigger $trigger ` + -RunLevel Highest ` + -User 'SYSTEM' ` + -Force | Out-Null } function Test-AppXSvcDisabled { [CmdletBinding()] param() - # Returns $true if AppXSvc is either: - # - Not present (already gone) - # - Present, Stopped, and StartType Disabled $svc = Get-Service -Name $svcName -ErrorAction SilentlyContinue if ($null -eq $svc) { @@ -388,11 +380,11 @@ function Test-AppXSvcDisabled { return $false } -# --- Main flow --------------------------------------------------------------- +# --- Main flow --- -Remove-PreinstalledAppxPackages # Inlined ronin uninstall logic -Disable-AppXSvcCore # Stop, disable, set Start=4 -Ensure-AppXSvcHardeningTask # Re-enforce on every boot +Remove-PreinstalledAppxPackages +Disable-AppXSvcCore +Ensure-AppXSvcHardeningTask if (-not (Test-AppXSvcDisabled)) { $svc = Get-Service -Name $svcName -ErrorAction SilentlyContinue From b0aa75d9c271135f5a3394d13f8eef8eb4cd8aa0 Mon Sep 17 00:00:00 2001 From: Mark Cornmesser Date: Fri, 19 Dec 2025 14:59:13 -0800 Subject: [PATCH 042/105] disable apx service --- .../files/appxpackages/uninstall.ps1 | 327 ++++-------------- 1 file changed, 61 insertions(+), 266 deletions(-) diff --git a/modules/win_disable_services/files/appxpackages/uninstall.ps1 b/modules/win_disable_services/files/appxpackages/uninstall.ps1 index 67f1649ea..1ef637483 100644 --- a/modules/win_disable_services/files/appxpackages/uninstall.ps1 +++ b/modules/win_disable_services/files/appxpackages/uninstall.ps1 @@ -1,12 +1,5 @@ -#requires -RunAsAdministrator - -# Lab-only Windows 11 24H2 hardening: -# - Remove predefined AppX packages (inlined from ronin uninstall.ps1) -# - Disable AppXSvc (service + registry Start=4) -# - Install startup scheduled task (SYSTEM) to re-enforce disable every boot -# - Validate AppXSvc is disabled; exit 0 on success, 1 on failure - -$ErrorActionPreference = 'Stop' +# IMPORTANT: use 'Continue' so random AppX errors don't hard-fail Puppet +$ErrorActionPreference = 'Continue' $svcName = 'AppXSvc' $svcKeyPath = 'HKLM:\SYSTEM\CurrentControlSet\Services\AppXSvc' @@ -15,274 +8,76 @@ function Remove-PreinstalledAppxPackages { [CmdletBinding()] param() + # Inlined from ronin_puppet win_disable_services appxpackages/uninstall.ps1, + # with Write-Host converted to Write-Verbose to reduce noise. $apps = @{ - "Bing Search" = @{ - VDIState = "Unchanged" - URL = "https://apps.microsoft.com/detail/9nzbf4gt040c" - Description = "Web Search from Microsoft Bing provides web results and answers in Windows Search" - } - "Clipchamp.Clipchamp" = @{ - VDIState = "Unchanged" - URL = "https://apps.microsoft.com/detail/9p1j8s7ccwwt?hl=en-us&gl=US" - Description = "Create videos with a few clicks" - } - "Microsoft.549981C3F5F10" = @{ - VDIState = "Unchanged" - URL = "https://apps.microsoft.com/detail/cortana/9NFFX4SZZ23L?hl=en-us&gl=US" - Description = "Cortana (could not update)" - } - "Microsoft.BingNews" = @{ - VDIState = "Unchanged" - URL = "https://www.microsoft.com/en-us/p/microsoft-news/9wzdncrfhvfw" - Description = "Microsoft News app" - } - "Microsoft.BingWeather" = @{ - VDIState = "Unchanged" - URL = "https://www.microsoft.com/en-us/p/msn-weather/9wzdncrfj3q2" - Description = "MSN Weather app" - } - "Microsoft.DesktopAppInstaller" = @{ - VDIState = "Unchanged" - URL = "https://apps.microsoft.com/detail/9NBLGGH4NNS1" - Description = "Microsoft App Installer for Windows 10 makes sideloading Windows apps easy" - } - "Microsoft.GetHelp" = @{ - VDIState = "Unchanged" - URL = "https://docs.microsoft.com/en-us/windows-hardware/customize/desktop/customize-get-help-app" - Description = "App that facilitates free support for Microsoft products" - } - "Microsoft.Getstarted" = @{ - VDIState = "Unchanged" - URL = "https://www.microsoft.com/en-us/p/microsoft-tips/9wzdncrdtbjj" - Description = "Windows 10 tips app" - } - "Microsoft.MicrosoftOfficeHub" = @{ - VDIState = "Unchanged" - URL = "https://www.microsoft.com/en-us/p/office/9wzdncrd29v9" - Description = "Office UWP app suite" - } - "Microsoft.Office.OneNote" = @{ - VDIState = "Unchanged" - URL = "https://www.microsoft.com/en-us/p/onenote-for-windows-10/9wzdncrfhvjl" - Description = "Office UWP OneNote app" - } - "Microsoft.MicrosoftSolitaireCollection" = @{ - VDIState = "Unchanged" - URL = "https://www.microsoft.com/en-us/p/microsoft-solitaire-collection/9wzdncrfhwd2" - Description = "Solitaire suite of games" - } - "Microsoft.MicrosoftStickyNotes" = @{ - VDIState = "Unchanged" - URL = "https://www.microsoft.com/en-us/p/microsoft-sticky-notes/9nblggh4qghw" - Description = "Note-taking app" - } - "Microsoft.OutlookForWindows" = @{ - VDIState = "Unchanged" - URL = "https://apps.microsoft.com/detail/9NRX63209R7B?hl=en-us&gl=US" - Description = "A best-in-class email experience that is free for anyone with Windows" - } - "Microsoft.MSPaint" = @{ - VDIState = "Unchanged" - URL = "https://apps.microsoft.com/store/detail/paint-3d/9NBLGGH5FV99" - Description = "Paint 3D app (not Classic Paint app)" - } - "Microsoft.Paint" = @{ - VDIState = "Unchanged" - URL = "https://apps.microsoft.com/detail/9PCFS5B6T72H" - Description = "Classic Paint app" - } - "Microsoft.People" = @{ - VDIState = "Unchanged" - URL = "https://www.microsoft.com/en-us/p/microsoft-people/9nblggh10pg8" - Description = "Contact management app" - } - "Microsoft.PowerAutomateDesktop" = @{ - VDIState = "Unchanged" - URL = "https://flow.microsoft.com/en-us/desktop/" - Description = "Power Automate Desktop app. Record desktop and web actions in a single flow" - } - "Microsoft.ScreenSketch" = @{ - VDIState = "Unchanged" - URL = "https://www.microsoft.com/en-us/p/snip-sketch/9mz95kl8mr0l" - Description = "Snip and Sketch app" - } - "Microsoft.SkypeApp" = @{ - VDIState = "Unchanged" - URL = "https://www.microsoft.com/en-us/p/skype/9wzdncrfj364" - Description = "Instant message, voice or video call app" - } - "Microsoft.StorePurchaseApp" = @{ - VDIState = "Unchanged" - URL = "" - Description = "Store purchase app helper" - } - "Microsoft.Todos" = @{ - VDIState = "Unchanged" - URL = "https://www.microsoft.com/en-us/p/microsoft-to-do-lists-tasks-reminders/9nblggh5r558" - Description = "Microsoft To Do makes it easy to plan your day and manage your life" - } - "Microsoft.WinDbg.Fast" = @{ - VDIState = "Unchanged" - URL = "https://apps.microsoft.com/detail/9PGJGD53TN86?hl=en-us&gl=US" - Description = "Microsoft WinDbg" - } - "Microsoft.Windows.DevHome" = @{ - VDIState = "Unchanged" - URL = "https://learn.microsoft.com/en-us/windows/dev-home/" - Description = "Dev Home dashboard" - } - "Microsoft.Windows.Photos" = @{ - VDIState = "Unchanged" - URL = "https://www.microsoft.com/en-us/p/microsoft-photos/9wzdncrfjbh4" - Description = "Photo and video editor" - } - "Microsoft.WindowsAlarms" = @{ - VDIState = "Unchanged" - URL = "https://www.microsoft.com/en-us/p/windows-alarms-clock/9wzdncrfj3pr" - Description = "Alarms, world clock, timer, stopwatch" - } - "Microsoft.WindowsCalculator" = @{ - VDIState = "Unchanged" - URL = "https://www.microsoft.com/en-us/p/windows-calculator/9wzdncrfhvn5" - Description = "Microsoft Calculator app" - } - "Microsoft.WindowsCamera" = @{ - VDIState = "Unchanged" - URL = "https://www.microsoft.com/en-us/p/windows-camera/9wzdncrfjbbg" - Description = "Camera app" - } - "microsoft.windowscommunicationsapps" = @{ - VDIState = "Unchanged" - URL = "https://www.microsoft.com/en-us/p/mail-and-calendar/9wzdncrfhvqm" - Description = "Mail & Calendar apps" - } - "Microsoft.WindowsFeedbackHub" = @{ - VDIState = "Unchanged" - URL = "https://www.microsoft.com/en-us/p/feedback-hub/9nblggh4r32n" - Description = "Feedback Hub" - } - "Microsoft.WindowsMaps" = @{ - VDIState = "Unchanged" - URL = "https://www.microsoft.com/en-us/p/windows-maps/9wzdncrdtbvb" - Description = "Microsoft Maps app" - } - "Microsoft.WindowsNotepad" = @{ - VDIState = "Unchanged" - URL = "https://www.microsoft.com/en-us/p/windows-notepad/9msmlrh6lzf3" - Description = "Notepad (Store version)" - } - "Microsoft.WindowsStore" = @{ - VDIState = "Unchanged" - URL = "https://blogs.windows.com/windowsexperience/2021/06/24/building-a-new-open-microsoft-store-on-windows-11/" - Description = "Windows Store app" - } - "Microsoft.WindowsSoundRecorder" = @{ - VDIState = "Unchanged" - URL = "https://www.microsoft.com/en-us/p/windows-voice-recorder/9wzdncrfhwkn" - Description = "Voice recorder" - } - "Microsoft.WindowsTerminal" = @{ - VDIState = "Unchanged" - URL = "https://www.microsoft.com/en-us/p/windows-terminal/9n0dx20hk701" - Description = "Windows Terminal" - } - "Microsoft.Winget.Platform.Source" = @{ - VDIState = "Unchanged" - URL = "https://learn.microsoft.com/en-us/windows/package-manager/winget/" - Description = "Winget (Windows Package Manager) source" - } - "Microsoft.Xbox.TCUI" = @{ - VDIState = "Unchanged" - URL = "https://docs.microsoft.com/en-us/gaming/xbox-live/features/general/tcui/live-tcui-overview" - Description = "Xbox Title Callable UI" - } - "Microsoft.XboxIdentityProvider" = @{ - VDIState = "Unchanged" - URL = "https://www.microsoft.com/en-us/p/xbox-identity-provider/9wzdncrd1hkw" - Description = "Xbox Identity Provider" - } - "Microsoft.XboxSpeechToTextOverlay" = @{ - VDIState = "Unchanged" - URL = "https://support.xbox.com/help/account-profile/accessibility/use-game-chat-transcription" - Description = "Xbox game chat transcription" - } - "Microsoft.YourPhone" = @{ - VDIState = "Unchanged" - URL = "https://www.microsoft.com/en-us/p/Your-phone/9nmpj99vjbwv" - Description = "Phone Link" - } - "Microsoft.ZuneMusic" = @{ - VDIState = "Unchanged" - URL = "https://www.microsoft.com/en-us/p/groove-music/9wzdncrfj3pt" - Description = "Groove Music" - } - "Microsoft.ZuneVideo" = @{ - VDIState = "Unchanged" - URL = "https://www.microsoft.com/en-us/p/movies-tv/9wzdncrfj3p2" - Description = "Movies & TV" - } - "MicrosoftCorporationII.QuickAssist" = @{ - VDIState = "Unchanged" - URL = "https://apps.microsoft.com/detail/9P7BP5VNWKX5?hl=en-us&gl=US" - Description = "Quick Assist" - } - "MicrosoftWindows.Client.WebExperience" = @{ - VDIState = "Unchanged" - URL = "" - Description = "Windows 11 Widgets / Web Experience" - } - "Microsoft.XboxApp" = @{ - VDIState = "Unchanged" - URL = "https://www.microsoft.com/store/apps/9wzdncrfjbd8" - Description = "Xbox Console Companion" - } - "Microsoft.MixedReality.Portal" = @{ - VDIState = "Unchanged" - URL = "https://www.microsoft.com/en-us/p/mixed-reality-portal/9ng1h8b3zc7m" - Description = "Mixed Reality Portal" - } - "Microsoft.Microsoft3DViewer" = @{ - VDIState = "Unchanged" - URL = "https://www.microsoft.com/en-us/p/3d-viewer/9nblggh42ths" - Description = "3D Viewer" - } - "MicrosoftTeams" = @{ - VDIState = "Unchanged" - URL = "https://apps.microsoft.com/detail/xp8bt8dw290mpq" - Description = "Microsoft Teams" - } - "MSTeams" = @{ - VDIState = "Unchanged" - URL = "https://apps.microsoft.com/detail/xp8bt8dw290mpq" - Description = "Microsoft Teams (alt id)" - } - "Microsoft.OneDriveSync" = @{ - VDIState = "Unchanged" - URL = "https://docs.microsoft.com/en-us/onedrive/one-drive-sync" - Description = "OneDrive sync app" - } - "Microsoft.Wallet" = @{ - VDIState = "Unchanged" - URL = "https://www.microsoft.com/en-us/payments" - Description = "Microsoft Pay" - } + "Bing Search" = @{ VDIState="Unchanged"; URL="https://apps.microsoft.com/detail/9nzbf4gt040c"; Description="Web Search from Microsoft Bing provides web results and answers in Windows Search" } + "Clipchamp.Clipchamp" = @{ VDIState="Unchanged"; URL="https://apps.microsoft.com/detail/9p1j8s7ccwwt?hl=en-us&gl=US"; Description="Create videos with a few clicks" } + "Microsoft.549981C3F5F10" = @{ VDIState="Unchanged"; URL="https://apps.microsoft.com/detail/cortana/9NFFX4SZZ23L?hl=en-us&gl=US"; Description="Cortana (could not update)" } + "Microsoft.BingNews" = @{ VDIState="Unchanged"; URL="https://www.microsoft.com/en-us/p/microsoft-news/9wzdncrfhvfw"; Description="Microsoft News app" } + "Microsoft.BingWeather" = @{ VDIState="Unchanged"; URL="https://www.microsoft.com/en-us/p/msn-weather/9wzdncrfj3q2"; Description="MSN Weather app" } + "Microsoft.DesktopAppInstaller" = @{ VDIState="Unchanged"; URL="https://apps.microsoft.com/detail/9NBLGGH4NNS1"; Description="Microsoft App Installer for Windows 10 makes sideloading Windows apps easy" } + "Microsoft.GetHelp" = @{ VDIState="Unchanged"; URL="https://docs.microsoft.com/en-us/windows-hardware/customize/desktop/customize-get-help-app"; Description="App that facilitates free support for Microsoft products" } + "Microsoft.Getstarted" = @{ VDIState="Unchanged"; URL="https://www.microsoft.com/en-us/p/microsoft-tips/9wzdncrdtbjj"; Description="Windows 10 tips app" } + "Microsoft.MicrosoftOfficeHub" = @{ VDIState="Unchanged"; URL="https://www.microsoft.com/en-us/p/office/9wzdncrd29v9"; Description="Office UWP app suite" } + "Microsoft.Office.OneNote" = @{ VDIState="Unchanged"; URL="https://www.microsoft.com/en-us/p/onenote-for-windows-10/9wzdncrfhvjl"; Description="Office UWP OneNote app" } + "Microsoft.MicrosoftSolitaireCollection" = @{ VDIState="Unchanged"; URL="https://www.microsoft.com/en-us/p/microsoft-solitaire-collection/9wzdncrfhwd2"; Description="Solitaire suite of games" } + "Microsoft.MicrosoftStickyNotes" = @{ VDIState="Unchanged"; URL="https://www.microsoft.com/en-us/p/microsoft-sticky-notes/9nblggh4qghw"; Description="Note-taking app" } + "Microsoft.OutlookForWindows" = @{ VDIState="Unchanged"; URL="https://apps.microsoft.com/detail/9NRX63209R7B?hl=en-us&gl=US"; Description="A best-in-class email experience that is free for anyone with Windows" } + "Microsoft.MSPaint" = @{ VDIState="Unchanged"; URL="https://apps.microsoft.com/store/detail/paint-3d/9NBLGGH5FV99"; Description="Paint 3D app (not Classic Paint app)" } + "Microsoft.Paint" = @{ VDIState="Unchanged"; URL="https://apps.microsoft.com/detail/9PCFS5B6T72H"; Description="Classic Paint app" } + "Microsoft.People" = @{ VDIState="Unchanged"; URL="https://www.microsoft.com/en-us/p/microsoft-people/9nblggh10pg8"; Description="Contact management app" } + "Microsoft.PowerAutomateDesktop" = @{ VDIState="Unchanged"; URL="https://flow.microsoft.com/en-us/desktop/"; Description="Power Automate Desktop app. Record desktop and web actions in a single flow" } + "Microsoft.ScreenSketch" = @{ VDIState="Unchanged"; URL="https://www.microsoft.com/en-us/p/snip-sketch/9mz95kl8mr0l"; Description="Snip and Sketch app" } + "Microsoft.SkypeApp" = @{ VDIState="Unchanged"; URL="https://www.microsoft.com/en-us/p/skype/9wzdncrfj364"; Description="Instant message, voice or video call app" } + "Microsoft.StorePurchaseApp" = @{ VDIState="Unchanged"; URL=""; Description="Store purchase app helper" } + "Microsoft.Todos" = @{ VDIState="Unchanged"; URL="https://www.microsoft.com/en-us/p/microsoft-to-do-lists-tasks-reminders/9nblggh5r558"; Description="Microsoft To Do makes it easy to plan your day and manage your life" } + "Microsoft.WinDbg.Fast" = @{ VDIState="Unchanged"; URL="https://apps.microsoft.com/detail/9PGJGD53TN86?hl=en-us&gl=US"; Description="Microsoft WinDbg" } + "Microsoft.Windows.DevHome" = @{ VDIState="Unchanged"; URL="https://learn.microsoft.com/en-us/windows/dev-home/"; Description="Dev Home dashboard" } + "Microsoft.Windows.Photos" = @{ VDIState="Unchanged"; URL="https://www.microsoft.com/en-us/p/microsoft-photos/9wzdncrfjbh4"; Description="Photo and video editor" } + "Microsoft.WindowsAlarms" = @{ VDIState="Unchanged"; URL="https://www.microsoft.com/en-us/p/windows-alarms-clock/9wzdncrfj3pr"; Description="Alarms, world clock, timer, stopwatch" } + "Microsoft.WindowsCalculator" = @{ VDIState="Unchanged"; URL="https://www.microsoft.com/en-us/p/windows-calculator/9wzdncrfhvn5"; Description="Microsoft Calculator app" } + "Microsoft.WindowsCamera" = @{ VDIState="Unchanged"; URL="https://www.microsoft.com/en-us/p/windows-camera/9wzdncrfjbbg"; Description="Camera app" } + "microsoft.windowscommunicationsapps" = @{ VDIState="Unchanged"; URL="https://www.microsoft.com/en-us/p/mail-and-calendar/9wzdncrfhvqm"; Description="Mail & Calendar apps" } + "Microsoft.WindowsFeedbackHub" = @{ VDIState="Unchanged"; URL="https://www.microsoft.com/en-us/p/feedback-hub/9nblggh4r32n"; Description="Feedback Hub" } + "Microsoft.WindowsMaps" = @{ VDIState="Unchanged"; URL="https://www.microsoft.com/en-us/p/windows-maps/9wzdncrdtbvb"; Description="Microsoft Maps app" } + "Microsoft.WindowsNotepad" = @{ VDIState="Unchanged"; URL="https://www.microsoft.com/en-us/p/windows-notepad/9msmlrh6lzf3"; Description="Notepad (Store version)" } + "Microsoft.WindowsStore" = @{ VDIState="Unchanged"; URL="https://blogs.windows.com/windowsexperience/2021/06/24/building-a-new-open-microsoft-store-on-windows-11/"; Description="Windows Store app" } + "Microsoft.WindowsSoundRecorder" = @{ VDIState="Unchanged"; URL="https://www.microsoft.com/en-us/p/windows-voice-recorder/9wzdncrfhwkn"; Description="Voice recorder" } + "Microsoft.WindowsTerminal" = @{ VDIState="Unchanged"; URL="https://www.microsoft.com/en-us/p/windows-terminal/9n0dx20hk701"; Description="Windows Terminal" } + "Microsoft.Winget.Platform.Source"= @{ VDIState="Unchanged"; URL="https://learn.microsoft.com/en-us/windows/package-manager/winget/"; Description="Winget (Windows Package Manager) source" } + "Microsoft.Xbox.TCUI" = @{ VDIState="Unchanged"; URL="https://docs.microsoft.com/en-us/gaming/xbox-live/features/general/tcui/live-tcui-overview"; Description="Xbox Title Callable UI" } + "Microsoft.XboxIdentityProvider" = @{ VDIState="Unchanged"; URL="https://www.microsoft.com/en-us/p/xbox-identity-provider/9wzdncrd1hkw"; Description="Xbox Identity Provider" } + "Microsoft.XboxSpeechToTextOverlay" = @{ VDIState="Unchanged"; URL="https://support.xbox.com/help/account-profile/accessibility/use-game-chat-transcription"; Description="Xbox game chat transcription" } + "Microsoft.YourPhone" = @{ VDIState="Unchanged"; URL="https://www.microsoft.com/en-us/p/Your-phone/9nmpj99vjbwv"; Description="Phone Link" } + "Microsoft.ZuneMusic" = @{ VDIState="Unchanged"; URL="https://www.microsoft.com/en-us/p/groove-music/9wzdncrfj3pt"; Description="Groove Music" } + "Microsoft.ZuneVideo" = @{ VDIState="Unchanged"; URL="https://www.microsoft.com/en-us/p/movies-tv/9wzdncrfj3p2"; Description="Movies and TV app" } + "MicrosoftCorporationII.QuickAssist" = @{ VDIState="Unchanged"; URL="https://apps.microsoft.com/detail/9P7BP5VNWKX5?hl=en-us&gl=US"; Description="Quick Assist" } + "MicrosoftWindows.Client.WebExperience" = @{ VDIState="Unchanged"; URL=""; Description="Windows 11 Widgets / Web Experience" } + "Microsoft.XboxApp" = @{ VDIState="Unchanged"; URL="https://www.microsoft.com/store/apps/9wzdncrfjbd8"; Description="Xbox Console Companion" } + "Microsoft.MixedReality.Portal" = @{ VDIState="Unchanged"; URL="https://www.microsoft.com/en-us/p/mixed-reality-portal/9ng1h8b3zc7m"; Description="Mixed Reality Portal" } + "Microsoft.Microsoft3DViewer" = @{ VDIState="Unchanged"; URL="https://www.microsoft.com/en-us/p/3d-viewer/9nblggh42ths"; Description="3D Viewer" } + "MicrosoftTeams" = @{ VDIState="Unchanged"; URL="https://apps.microsoft.com/detail/xp8bt8dw290mpq"; Description="Microsoft Teams" } + "MSTeams" = @{ VDIState="Unchanged"; URL="https://apps.microsoft.com/detail/xp8bt8dw290mpq"; Description="Microsoft Teams (alt id)" } + "Microsoft.OneDriveSync" = @{ VDIState="Unchanged"; URL="https://docs.microsoft.com/en-us/onedrive/one-drive-sync"; Description="OneDrive sync app" } + "Microsoft.Wallet" = @{ VDIState="Unchanged"; URL="https://www.microsoft.com/en-us/payments"; Description="Microsoft Pay" } } foreach ($Key in $apps.Keys) { $Item = $apps[$Key] - # Provisioned (for new users) + Write-Verbose "Removing provisioned package $Key" Get-AppxProvisionedPackage -Online | Where-Object { $_.PackageName -like ("*{0}*" -f $Key) } | Remove-AppxProvisionedPackage -Online -ErrorAction SilentlyContinue | Out-Null - # All users + Write-Verbose "Attempting to remove [All Users] $Key - $($Item.Description)" Get-AppxPackage -AllUsers -Name ("*{0}*" -f $Key) | Remove-AppxPackage -AllUsers -ErrorAction SilentlyContinue | Out-Null - # Current user + Write-Verbose "Attempting to remove $Key - $($Item.Description)" Get-AppxPackage -Name ("*{0}*" -f $Key) | Remove-AppxPackage -ErrorAction SilentlyContinue | Out-Null @@ -380,11 +175,11 @@ function Test-AppXSvcDisabled { return $false } -# --- Main flow --- +# --- Main flow --------------------------------------------------------------- -Remove-PreinstalledAppxPackages -Disable-AppXSvcCore -Ensure-AppXSvcHardeningTask +Remove-PreinstalledAppxPackages # Inlined ronin uninstall logic +Disable-AppXSvcCore # Stop, disable, set Start=4 +Ensure-AppXSvcHardeningTask # Re-enforce on every boot if (-not (Test-AppXSvcDisabled)) { $svc = Get-Service -Name $svcName -ErrorAction SilentlyContinue From 3547987069c091e164e6c32478b8b302dc34bb01 Mon Sep 17 00:00:00 2001 From: Mark Cornmesser Date: Fri, 19 Dec 2025 16:27:22 -0800 Subject: [PATCH 043/105] disable apx service --- .../files/appxpackages/uninstall.ps1 | 64 +++++++++---------- 1 file changed, 32 insertions(+), 32 deletions(-) diff --git a/modules/win_disable_services/files/appxpackages/uninstall.ps1 b/modules/win_disable_services/files/appxpackages/uninstall.ps1 index 1ef637483..ef2d2e2a1 100644 --- a/modules/win_disable_services/files/appxpackages/uninstall.ps1 +++ b/modules/win_disable_services/files/appxpackages/uninstall.ps1 @@ -1,4 +1,10 @@ -# IMPORTANT: use 'Continue' so random AppX errors don't hard-fail Puppet +# Lab-only Windows 11 24H2 hardening: +# - Remove a predefined set of AppX packages (inlined from ronin uninstall.ps1) +# - Disable AppXSvc (service + registry Start=4) +# - Install startup scheduled task (SYSTEM) to re-enforce disable every boot +# - Throw if AppXSvc is not disabled (Puppet will see non-zero) + +# IMPORTANT: use 'Continue' so normal AppX noise doesn't hard-fail Puppet $ErrorActionPreference = 'Continue' $svcName = 'AppXSvc' @@ -8,8 +14,6 @@ function Remove-PreinstalledAppxPackages { [CmdletBinding()] param() - # Inlined from ronin_puppet win_disable_services appxpackages/uninstall.ps1, - # with Write-Host converted to Write-Verbose to reduce noise. $apps = @{ "Bing Search" = @{ VDIState="Unchanged"; URL="https://apps.microsoft.com/detail/9nzbf4gt040c"; Description="Web Search from Microsoft Bing provides web results and answers in Windows Search" } "Clipchamp.Clipchamp" = @{ VDIState="Unchanged"; URL="https://apps.microsoft.com/detail/9p1j8s7ccwwt?hl=en-us&gl=US"; Description="Create videos with a few clicks" } @@ -23,37 +27,37 @@ function Remove-PreinstalledAppxPackages { "Microsoft.Office.OneNote" = @{ VDIState="Unchanged"; URL="https://www.microsoft.com/en-us/p/onenote-for-windows-10/9wzdncrfhvjl"; Description="Office UWP OneNote app" } "Microsoft.MicrosoftSolitaireCollection" = @{ VDIState="Unchanged"; URL="https://www.microsoft.com/en-us/p/microsoft-solitaire-collection/9wzdncrfhwd2"; Description="Solitaire suite of games" } "Microsoft.MicrosoftStickyNotes" = @{ VDIState="Unchanged"; URL="https://www.microsoft.com/en-us/p/microsoft-sticky-notes/9nblggh4qghw"; Description="Note-taking app" } - "Microsoft.OutlookForWindows" = @{ VDIState="Unchanged"; URL="https://apps.microsoft.com/detail/9NRX63209R7B?hl=en-us&gl=US"; Description="A best-in-class email experience that is free for anyone with Windows" } - "Microsoft.MSPaint" = @{ VDIState="Unchanged"; URL="https://apps.microsoft.com/store/detail/paint-3d/9NBLGGH5FV99"; Description="Paint 3D app (not Classic Paint app)" } + "Microsoft.OutlookForWindows" = @{ VDIState="Unchanged"; URL="https://apps.microsoft.com/detail/9NRX63209R7B?hl=en-us&gl=US"; Description="New Outlook app" } + "Microsoft.MSPaint" = @{ VDIState="Unchanged"; URL="https://apps.microsoft.com/store/detail/paint-3d/9NBLGGH5FV99"; Description="Paint 3D app" } "Microsoft.Paint" = @{ VDIState="Unchanged"; URL="https://apps.microsoft.com/detail/9PCFS5B6T72H"; Description="Classic Paint app" } "Microsoft.People" = @{ VDIState="Unchanged"; URL="https://www.microsoft.com/en-us/p/microsoft-people/9nblggh10pg8"; Description="Contact management app" } - "Microsoft.PowerAutomateDesktop" = @{ VDIState="Unchanged"; URL="https://flow.microsoft.com/en-us/desktop/"; Description="Power Automate Desktop app. Record desktop and web actions in a single flow" } + "Microsoft.PowerAutomateDesktop" = @{ VDIState="Unchanged"; URL="https://flow.microsoft.com/en-us/desktop/"; Description="Power Automate Desktop" } "Microsoft.ScreenSketch" = @{ VDIState="Unchanged"; URL="https://www.microsoft.com/en-us/p/snip-sketch/9mz95kl8mr0l"; Description="Snip and Sketch app" } - "Microsoft.SkypeApp" = @{ VDIState="Unchanged"; URL="https://www.microsoft.com/en-us/p/skype/9wzdncrfj364"; Description="Instant message, voice or video call app" } + "Microsoft.SkypeApp" = @{ VDIState="Unchanged"; URL="https://www.microsoft.com/en-us/p/skype/9wzdncrfj364"; Description="Skype app" } "Microsoft.StorePurchaseApp" = @{ VDIState="Unchanged"; URL=""; Description="Store purchase app helper" } - "Microsoft.Todos" = @{ VDIState="Unchanged"; URL="https://www.microsoft.com/en-us/p/microsoft-to-do-lists-tasks-reminders/9nblggh5r558"; Description="Microsoft To Do makes it easy to plan your day and manage your life" } - "Microsoft.WinDbg.Fast" = @{ VDIState="Unchanged"; URL="https://apps.microsoft.com/detail/9PGJGD53TN86?hl=en-us&gl=US"; Description="Microsoft WinDbg" } + "Microsoft.Todos" = @{ VDIState="Unchanged"; URL="https://www.microsoft.com/en-us/p/microsoft-to-do-lists-tasks-reminders/9nblggh5r558"; Description="Microsoft To Do" } + "Microsoft.WinDbg.Fast" = @{ VDIState="Unchanged"; URL="https://apps.microsoft.com/detail/9PGJGD53TN86?hl=en-us&gl=US"; Description="WinDbg" } "Microsoft.Windows.DevHome" = @{ VDIState="Unchanged"; URL="https://learn.microsoft.com/en-us/windows/dev-home/"; Description="Dev Home dashboard" } - "Microsoft.Windows.Photos" = @{ VDIState="Unchanged"; URL="https://www.microsoft.com/en-us/p/microsoft-photos/9wzdncrfjbh4"; Description="Photo and video editor" } - "Microsoft.WindowsAlarms" = @{ VDIState="Unchanged"; URL="https://www.microsoft.com/en-us/p/windows-alarms-clock/9wzdncrfj3pr"; Description="Alarms, world clock, timer, stopwatch" } - "Microsoft.WindowsCalculator" = @{ VDIState="Unchanged"; URL="https://www.microsoft.com/en-us/p/windows-calculator/9wzdncrfhvn5"; Description="Microsoft Calculator app" } - "Microsoft.WindowsCamera" = @{ VDIState="Unchanged"; URL="https://www.microsoft.com/en-us/p/windows-camera/9wzdncrfjbbg"; Description="Camera app" } - "microsoft.windowscommunicationsapps" = @{ VDIState="Unchanged"; URL="https://www.microsoft.com/en-us/p/mail-and-calendar/9wzdncrfhvqm"; Description="Mail & Calendar apps" } + "Microsoft.Windows.Photos" = @{ VDIState="Unchanged"; URL="https://www.microsoft.com/en-us/p/microsoft-photos/9wzdncrfjbh4"; Description="Photos app" } + "Microsoft.WindowsAlarms" = @{ VDIState="Unchanged"; URL="https://www.microsoft.com/en-us/p/windows-alarms-clock/9wzdncrfj3pr"; Description="Alarms & Clock" } + "Microsoft.WindowsCalculator" = @{ VDIState="Unchanged"; URL="https://www.microsoft.com/en-us/p/windows-calculator/9wzdncrfhvn5"; Description="Calculator" } + "Microsoft.WindowsCamera" = @{ VDIState="Unchanged"; URL="https://www.microsoft.com/en-us/p/windows-camera/9wzdncrfjbbg"; Description="Camera" } + "microsoft.windowscommunicationsapps" = @{ VDIState="Unchanged"; URL="https://www.microsoft.com/en-us/p/mail-and-calendar/9wzdncrfhvqm"; Description="Mail & Calendar" } "Microsoft.WindowsFeedbackHub" = @{ VDIState="Unchanged"; URL="https://www.microsoft.com/en-us/p/feedback-hub/9nblggh4r32n"; Description="Feedback Hub" } - "Microsoft.WindowsMaps" = @{ VDIState="Unchanged"; URL="https://www.microsoft.com/en-us/p/windows-maps/9wzdncrdtbvb"; Description="Microsoft Maps app" } - "Microsoft.WindowsNotepad" = @{ VDIState="Unchanged"; URL="https://www.microsoft.com/en-us/p/windows-notepad/9msmlrh6lzf3"; Description="Notepad (Store version)" } - "Microsoft.WindowsStore" = @{ VDIState="Unchanged"; URL="https://blogs.windows.com/windowsexperience/2021/06/24/building-a-new-open-microsoft-store-on-windows-11/"; Description="Windows Store app" } - "Microsoft.WindowsSoundRecorder" = @{ VDIState="Unchanged"; URL="https://www.microsoft.com/en-us/p/windows-voice-recorder/9wzdncrfhwkn"; Description="Voice recorder" } + "Microsoft.WindowsMaps" = @{ VDIState="Unchanged"; URL="https://www.microsoft.com/en-us/p/windows-maps/9wzdncrdtbvb"; Description="Maps" } + "Microsoft.WindowsNotepad" = @{ VDIState="Unchanged"; URL="https://www.microsoft.com/en-us/p/windows-notepad/9msmlrh6lzf3"; Description="Notepad (Store)" } + "Microsoft.WindowsStore" = @{ VDIState="Unchanged"; URL="https://blogs.windows.com/windowsexperience/2021/06/24/building-a-new-open-microsoft-store-on-windows-11/"; Description="Microsoft Store" } + "Microsoft.WindowsSoundRecorder" = @{ VDIState="Unchanged"; URL="https://www.microsoft.com/en-us/p/windows-voice-recorder/9wzdncrfhwkn"; Description="Voice Recorder" } "Microsoft.WindowsTerminal" = @{ VDIState="Unchanged"; URL="https://www.microsoft.com/en-us/p/windows-terminal/9n0dx20hk701"; Description="Windows Terminal" } - "Microsoft.Winget.Platform.Source"= @{ VDIState="Unchanged"; URL="https://learn.microsoft.com/en-us/windows/package-manager/winget/"; Description="Winget (Windows Package Manager) source" } - "Microsoft.Xbox.TCUI" = @{ VDIState="Unchanged"; URL="https://docs.microsoft.com/en-us/gaming/xbox-live/features/general/tcui/live-tcui-overview"; Description="Xbox Title Callable UI" } + "Microsoft.Winget.Platform.Source"= @{ VDIState="Unchanged"; URL="https://learn.microsoft.com/en-us/windows/package-manager/winget/"; Description="Winget source" } + "Microsoft.Xbox.TCUI" = @{ VDIState="Unchanged"; URL="https://docs.microsoft.com/en-us/gaming/xbox-live/features/general/tcui/live-tcui-overview"; Description="Xbox TCUI" } "Microsoft.XboxIdentityProvider" = @{ VDIState="Unchanged"; URL="https://www.microsoft.com/en-us/p/xbox-identity-provider/9wzdncrd1hkw"; Description="Xbox Identity Provider" } - "Microsoft.XboxSpeechToTextOverlay" = @{ VDIState="Unchanged"; URL="https://support.xbox.com/help/account-profile/accessibility/use-game-chat-transcription"; Description="Xbox game chat transcription" } + "Microsoft.XboxSpeechToTextOverlay" = @{ VDIState="Unchanged"; URL="https://support.xbox.com/help/account-profile/accessibility/use-game-chat-transcription"; Description="Xbox chat transcription" } "Microsoft.YourPhone" = @{ VDIState="Unchanged"; URL="https://www.microsoft.com/en-us/p/Your-phone/9nmpj99vjbwv"; Description="Phone Link" } "Microsoft.ZuneMusic" = @{ VDIState="Unchanged"; URL="https://www.microsoft.com/en-us/p/groove-music/9wzdncrfj3pt"; Description="Groove Music" } - "Microsoft.ZuneVideo" = @{ VDIState="Unchanged"; URL="https://www.microsoft.com/en-us/p/movies-tv/9wzdncrfj3p2"; Description="Movies and TV app" } + "Microsoft.ZuneVideo" = @{ VDIState="Unchanged"; URL="https://www.microsoft.com/en-us/p/movies-tv/9wzdncrfj3p2"; Description="Movies & TV" } "MicrosoftCorporationII.QuickAssist" = @{ VDIState="Unchanged"; URL="https://apps.microsoft.com/detail/9P7BP5VNWKX5?hl=en-us&gl=US"; Description="Quick Assist" } - "MicrosoftWindows.Client.WebExperience" = @{ VDIState="Unchanged"; URL=""; Description="Windows 11 Widgets / Web Experience" } + "MicrosoftWindows.Client.WebExperience" = @{ VDIState="Unchanged"; URL=""; Description="Windows 11 Web Experience" } "Microsoft.XboxApp" = @{ VDIState="Unchanged"; URL="https://www.microsoft.com/store/apps/9wzdncrfjbd8"; Description="Xbox Console Companion" } "Microsoft.MixedReality.Portal" = @{ VDIState="Unchanged"; URL="https://www.microsoft.com/en-us/p/mixed-reality-portal/9ng1h8b3zc7m"; Description="Mixed Reality Portal" } "Microsoft.Microsoft3DViewer" = @{ VDIState="Unchanged"; URL="https://www.microsoft.com/en-us/p/3d-viewer/9nblggh42ths"; Description="3D Viewer" } @@ -66,18 +70,15 @@ function Remove-PreinstalledAppxPackages { foreach ($Key in $apps.Keys) { $Item = $apps[$Key] - Write-Verbose "Removing provisioned package $Key" Get-AppxProvisionedPackage -Online | Where-Object { $_.PackageName -like ("*{0}*" -f $Key) } | Remove-AppxProvisionedPackage -Online -ErrorAction SilentlyContinue | Out-Null - Write-Verbose "Attempting to remove [All Users] $Key - $($Item.Description)" Get-AppxPackage -AllUsers -Name ("*{0}*" -f $Key) | Remove-AppxPackage -AllUsers -ErrorAction SilentlyContinue | Out-Null - Write-Verbose "Attempting to remove $Key - $($Item.Description)" Get-AppxPackage -Name ("*{0}*" -f $Key) | Remove-AppxPackage -ErrorAction SilentlyContinue | Out-Null @@ -177,17 +178,16 @@ function Test-AppXSvcDisabled { # --- Main flow --------------------------------------------------------------- -Remove-PreinstalledAppxPackages # Inlined ronin uninstall logic -Disable-AppXSvcCore # Stop, disable, set Start=4 -Ensure-AppXSvcHardeningTask # Re-enforce on every boot +Remove-PreinstalledAppxPackages +Disable-AppXSvcCore +Ensure-AppXSvcHardeningTask if (-not (Test-AppXSvcDisabled)) { $svc = Get-Service -Name $svcName -ErrorAction SilentlyContinue $status = if ($svc) { $svc.Status } else { 'Missing' } $startType = if ($svc) { $svc.StartType } else { 'Missing' } - Write-Error "AppXSvc is NOT disabled. Status: $status, StartType: $startType" - exit 1 + throw "AppXSvc is NOT disabled. Status: $status, StartType: $startType" } -exit 0 +# No 'exit 0' – let PowerShell exit cleanly for Puppet From 99ae1b8b0f10e26a27f9a80b076506953d9384a4 Mon Sep 17 00:00:00 2001 From: Mark Cornmesser Date: Mon, 22 Dec 2025 12:37:18 -0800 Subject: [PATCH 044/105] troubleshooting appx removal --- .../manifests/uninstall_appx_packages.pp | 21 ++++++++++++++++--- 1 file changed, 18 insertions(+), 3 deletions(-) diff --git a/modules/win_disable_services/manifests/uninstall_appx_packages.pp b/modules/win_disable_services/manifests/uninstall_appx_packages.pp index 8efc57186..37b9e59f8 100644 --- a/modules/win_disable_services/manifests/uninstall_appx_packages.pp +++ b/modules/win_disable_services/manifests/uninstall_appx_packages.pp @@ -1,8 +1,23 @@ # This class is responsible for disabling AppX packages on Windows. class win_disable_services::uninstall_appx_packages { + + # Use the fact directly as the base path + $ronin_base = $facts['custom_win_roninprogramdata'] + $script_path = "${ronin_base}\\win_uninstall_appx_packages.ps1" + + ## Run file locally so that it runs as a script + ## and not a single command + file { $script_path: + ensure => file, + content => file('win_disable_services/appxpackages/uninstall.ps1'), + } + exec { 'disable_appx_packages': - command => file('win_disable_services/appxpackages/uninstall.ps1'), - provider => powershell, - timeout => 300, + command => "powershell.exe -NoProfile -NonInteractive -ExecutionPolicy Bypass -File \"${script_path}\"", + provider => shell, + timeout => 300, + logoutput => true, + returns => [0], + require => File[$script_path], } } From 3f9b4d46bb62eaaf828d3dabf3cc946dcf6412cb Mon Sep 17 00:00:00 2001 From: Mark Cornmesser Date: Mon, 22 Dec 2025 14:51:53 -0800 Subject: [PATCH 045/105] troubleshooting appx removal --- .../files/appxpackages/uninstall.ps1 | 47 ++++++++++++++++++- .../manifests/uninstall_appx_packages.pp | 8 ++-- 2 files changed, 48 insertions(+), 7 deletions(-) diff --git a/modules/win_disable_services/files/appxpackages/uninstall.ps1 b/modules/win_disable_services/files/appxpackages/uninstall.ps1 index ef2d2e2a1..0bd68b3cd 100644 --- a/modules/win_disable_services/files/appxpackages/uninstall.ps1 +++ b/modules/win_disable_services/files/appxpackages/uninstall.ps1 @@ -1,9 +1,44 @@ # Lab-only Windows 11 24H2 hardening: -# - Remove a predefined set of AppX packages (inlined from ronin uninstall.ps1) +# - Remove a predefined set of AppX packages # - Disable AppXSvc (service + registry Start=4) # - Install startup scheduled task (SYSTEM) to re-enforce disable every boot # - Throw if AppXSvc is not disabled (Puppet will see non-zero) +function Write-Log { + param ( + [string] $message, + [string] $severity = 'INFO', + [string] $source = 'BootStrap', + [string] $logName = 'Application' + ) + + if (!([Diagnostics.EventLog]::Exists($logName)) -or + !([Diagnostics.EventLog]::SourceExists($source))) { + New-EventLog -LogName $logName -Source $source + } + + switch ($severity) { + 'DEBUG' { $entryType = 'SuccessAudit'; $eventId = 2; break } + 'WARN' { $entryType = 'Warning'; $eventId = 3; break } + 'ERROR' { $entryType = 'Error'; $eventId = 4; break } + default { $entryType = 'Information'; $eventId = 1; break } + } + + Write-EventLog -LogName $logName -Source $source ` + -EntryType $entryType -Category 0 -EventID $eventId ` + -Message $message + + if ([Environment]::UserInteractive) { + $fc = @{ + 'Information' = 'White' + 'Error' = 'Red' + 'Warning' = 'DarkYellow' + 'SuccessAudit'= 'DarkGray' + }[$entryType] + Write-Host $message -ForegroundColor $fc + } +} + # IMPORTANT: use 'Continue' so normal AppX noise doesn't hard-fail Puppet $ErrorActionPreference = 'Continue' @@ -178,8 +213,15 @@ function Test-AppXSvcDisabled { # --- Main flow --------------------------------------------------------------- +Write-Log -message 'uninstall_appx_packages :: begin' -severity 'DEBUG' + +Write-Log -message 'uninstall_appx_packages :: Remove-PreinstalledAppxPackages' -severity 'DEBUG' Remove-PreinstalledAppxPackages + +Write-Log -message 'uninstall_appx_packages :: Disable-AppXSvcCore' -severity 'DEBUG' Disable-AppXSvcCore + +Write-Log -message 'uninstall_appx_packages :: Ensure-AppXSvcHardeningTask' -severity 'DEBUG' Ensure-AppXSvcHardeningTask if (-not (Test-AppXSvcDisabled)) { @@ -187,7 +229,8 @@ if (-not (Test-AppXSvcDisabled)) { $status = if ($svc) { $svc.Status } else { 'Missing' } $startType = if ($svc) { $svc.StartType } else { 'Missing' } + Write-Log -message ("uninstall_appx_packages :: AppXSvc is NOT disabled. Status: {0}, StartType: {1}" -f $status, $startType) -severity 'ERROR' throw "AppXSvc is NOT disabled. Status: $status, StartType: $startType" } -# No 'exit 0' – let PowerShell exit cleanly for Puppet +Write-Log -message 'uninstall_appx_packages :: complete (AppXSvc disabled)' -severity 'DEBUG' diff --git a/modules/win_disable_services/manifests/uninstall_appx_packages.pp b/modules/win_disable_services/manifests/uninstall_appx_packages.pp index 37b9e59f8..e60acd759 100644 --- a/modules/win_disable_services/manifests/uninstall_appx_packages.pp +++ b/modules/win_disable_services/manifests/uninstall_appx_packages.pp @@ -1,20 +1,18 @@ # This class is responsible for disabling AppX packages on Windows. class win_disable_services::uninstall_appx_packages { - # Use the fact directly as the base path $ronin_base = $facts['custom_win_roninprogramdata'] $script_path = "${ronin_base}\\win_uninstall_appx_packages.ps1" - ## Run file locally so that it runs as a script - ## and not a single command file { $script_path: ensure => file, content => file('win_disable_services/appxpackages/uninstall.ps1'), } exec { 'disable_appx_packages': - command => "powershell.exe -NoProfile -NonInteractive -ExecutionPolicy Bypass -File \"${script_path}\"", - provider => shell, + # Call the script file from PowerShell provider + command => "& '${script_path}'", + provider => powershell, timeout => 300, logoutput => true, returns => [0], From 587c0e55edc676beb73e5a51110aa1c6b785c3f1 Mon Sep 17 00:00:00 2001 From: Mark Cornmesser Date: Tue, 23 Dec 2025 09:12:23 -0800 Subject: [PATCH 046/105] increase management interval --- modules/win_scheduled_tasks/manifests/gw_exe_check.pp | 2 +- modules/win_scheduled_tasks/manifests/self_redeploy_check.pp | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/modules/win_scheduled_tasks/manifests/gw_exe_check.pp b/modules/win_scheduled_tasks/manifests/gw_exe_check.pp index 305a635fc..1d74dac34 100644 --- a/modules/win_scheduled_tasks/manifests/gw_exe_check.pp +++ b/modules/win_scheduled_tasks/manifests/gw_exe_check.pp @@ -19,7 +19,7 @@ trigger => [{ schedule => 'daily', start_time => '00:00', - minutes_interval => 30, + minutes_interval => 60, minutes_duration => 1440, # 24 hours = repeat every 5 minutes all day }], user => 'SYSTEM', diff --git a/modules/win_scheduled_tasks/manifests/self_redeploy_check.pp b/modules/win_scheduled_tasks/manifests/self_redeploy_check.pp index dd9681a0e..6f8e8c906 100644 --- a/modules/win_scheduled_tasks/manifests/self_redeploy_check.pp +++ b/modules/win_scheduled_tasks/manifests/self_redeploy_check.pp @@ -19,8 +19,8 @@ trigger => [{ schedule => 'daily', start_time => '00:00', - #minutes_interval => 120, - minutes_interval => 5, + minutes_interval => 120, + #minutes_interval => 5, minutes_duration => 1440, # 24 hours = repeat every 2 hours all day }], user => 'SYSTEM', From 1eb5d1d114a4996974cb13bb5aa93daa00fbb3c6 Mon Sep 17 00:00:00 2001 From: Mark Cornmesser Date: Mon, 29 Dec 2025 10:30:26 -0800 Subject: [PATCH 047/105] testing --- modules/win_scheduled_tasks/manifests/gw_exe_check.pp | 2 +- modules/win_scheduled_tasks/manifests/self_redeploy_check.pp | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/modules/win_scheduled_tasks/manifests/gw_exe_check.pp b/modules/win_scheduled_tasks/manifests/gw_exe_check.pp index 1d74dac34..5aa5c994d 100644 --- a/modules/win_scheduled_tasks/manifests/gw_exe_check.pp +++ b/modules/win_scheduled_tasks/manifests/gw_exe_check.pp @@ -20,7 +20,7 @@ schedule => 'daily', start_time => '00:00', minutes_interval => 60, - minutes_duration => 1440, # 24 hours = repeat every 5 minutes all day + #minutes_duration => 1440, # 24 hours = repeat every 5 minutes all day }], user => 'SYSTEM', } diff --git a/modules/win_scheduled_tasks/manifests/self_redeploy_check.pp b/modules/win_scheduled_tasks/manifests/self_redeploy_check.pp index 6f8e8c906..271fb5885 100644 --- a/modules/win_scheduled_tasks/manifests/self_redeploy_check.pp +++ b/modules/win_scheduled_tasks/manifests/self_redeploy_check.pp @@ -21,7 +21,7 @@ start_time => '00:00', minutes_interval => 120, #minutes_interval => 5, - minutes_duration => 1440, # 24 hours = repeat every 2 hours all day + #minutes_duration => 1440, # 24 hours = repeat every 2 hours all day }], user => 'SYSTEM', } From 2284ee451c4761e5b0985c555794f45c5ffdf265 Mon Sep 17 00:00:00 2001 From: Mark Cornmesser Date: Mon, 29 Dec 2025 13:44:24 -0800 Subject: [PATCH 048/105] testing --- .../files/appxpackages/uninstall.ps1 | 10 ++++++++++ .../manifests/self_redeploy_check.pp | 4 ++-- 2 files changed, 12 insertions(+), 2 deletions(-) diff --git a/modules/win_disable_services/files/appxpackages/uninstall.ps1 b/modules/win_disable_services/files/appxpackages/uninstall.ps1 index 0bd68b3cd..7368349c5 100644 --- a/modules/win_disable_services/files/appxpackages/uninstall.ps1 +++ b/modules/win_disable_services/files/appxpackages/uninstall.ps1 @@ -118,6 +118,16 @@ function Remove-PreinstalledAppxPackages { Remove-AppxPackage -ErrorAction SilentlyContinue | Out-Null } + $paths = @( + "$env:SystemRoot\System32\OneDriveSetup.exe", + "$env:SystemRoot\SysWOW64\OneDriveSetup.exe" + ) + + foreach ($p in $paths) { + if (Test-Path $p) { + Start-Process $p -ArgumentList '/uninstall' -Wait -NoNewWindow + } + } } function Disable-AppXSvcCore { diff --git a/modules/win_scheduled_tasks/manifests/self_redeploy_check.pp b/modules/win_scheduled_tasks/manifests/self_redeploy_check.pp index 271fb5885..a4869a898 100644 --- a/modules/win_scheduled_tasks/manifests/self_redeploy_check.pp +++ b/modules/win_scheduled_tasks/manifests/self_redeploy_check.pp @@ -19,8 +19,8 @@ trigger => [{ schedule => 'daily', start_time => '00:00', - minutes_interval => 120, - #minutes_interval => 5, + #minutes_interval => 120, + minutes_interval => 5, #minutes_duration => 1440, # 24 hours = repeat every 2 hours all day }], user => 'SYSTEM', From 9a436d532bd09279b171ae15684320fe56507eb7 Mon Sep 17 00:00:00 2001 From: Mark Cornmesser Date: Mon, 29 Dec 2025 15:37:56 -0800 Subject: [PATCH 049/105] testing --- .../win_disable_services/files/appxpackages/uninstall.ps1 | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/modules/win_disable_services/files/appxpackages/uninstall.ps1 b/modules/win_disable_services/files/appxpackages/uninstall.ps1 index 7368349c5..32f5864e3 100644 --- a/modules/win_disable_services/files/appxpackages/uninstall.ps1 +++ b/modules/win_disable_services/files/appxpackages/uninstall.ps1 @@ -126,8 +126,11 @@ function Remove-PreinstalledAppxPackages { foreach ($p in $paths) { if (Test-Path $p) { Start-Process $p -ArgumentList '/uninstall' -Wait -NoNewWindow + } } - } + reg add "HKLM\SOFTWARE\Policies\Microsoft\Windows\OneDrive" /v DisableFileSyncNGSC /t REG_DWORD /d 1 /f + reg add "HKCR\CLSID\{018D5C66-4533-4307-9B53-224DE2ED1FE6}" /v System.IsPinnedToNameSpaceTree /t REG_DWORD /d 0 /f + reg add "HKCR\Wow6432Node\CLSID\{018D5C66-4533-4307-9B53-224DE2ED1FE6}" /v System.IsPinnedToNameSpaceTree /t REG_DWORD /d 0 /f } function Disable-AppXSvcCore { From f3d35cef353ee8a8c906c77cbab47d30318fab2c Mon Sep 17 00:00:00 2001 From: Mark Cornmesser Date: Tue, 30 Dec 2025 09:11:57 -0800 Subject: [PATCH 050/105] testing --- .../files/appxpackages/uninstall.ps1 | 184 +++++++++++++++++- 1 file changed, 175 insertions(+), 9 deletions(-) diff --git a/modules/win_disable_services/files/appxpackages/uninstall.ps1 b/modules/win_disable_services/files/appxpackages/uninstall.ps1 index 32f5864e3..c86d03533 100644 --- a/modules/win_disable_services/files/appxpackages/uninstall.ps1 +++ b/modules/win_disable_services/files/appxpackages/uninstall.ps1 @@ -1,9 +1,3 @@ -# Lab-only Windows 11 24H2 hardening: -# - Remove a predefined set of AppX packages -# - Disable AppXSvc (service + registry Start=4) -# - Install startup scheduled task (SYSTEM) to re-enforce disable every boot -# - Throw if AppXSvc is not disabled (Puppet will see non-zero) - function Write-Log { param ( [string] $message, @@ -39,6 +33,180 @@ function Write-Log { } } +function Remove-OneDriveAggressive { + [CmdletBinding(SupportsShouldProcess = $true, ConfirmImpact = 'High')] + param( + [switch]$PurgeUserData + ) + + function Try-Run([scriptblock]$sb, [string]$onError, [string]$severity = 'WARN') { + try { & $sb } catch { Write-Log -message "$onError $($_.Exception.Message)" -severity $severity -source 'BootStrap' -logName 'Application' } + } + + Write-Log -message "1) Stop OneDrive-related processes" -severity 'INFO' -source 'BootStrap' -logName 'Application' + + $procNames = @("OneDrive","OneDriveStandaloneUpdater","OneDriveSetup") + foreach ($p in $procNames) { + Get-Process -Name $p -ErrorAction SilentlyContinue | ForEach-Object { + $desc = "Process $($_.Name) (Id=$($_.Id))" + if ($PSCmdlet.ShouldProcess($desc, "Stop-Process -Force")) { + Try-Run { Stop-Process -Id $_.Id -Force -ErrorAction Stop } "Failed stopping $desc:" + } + } + } + + Write-Log -message "2) Disable and remove OneDrive scheduled tasks" -severity 'INFO' -source 'BootStrap' -logName 'Application' + + Try-Run { + $tasks = Get-ScheduledTask -ErrorAction Stop | Where-Object { + $_.TaskName -like "OneDrive*" -or $_.TaskPath -like "*OneDrive*" + } + + foreach ($t in $tasks) { + $fullName = "$($t.TaskPath)$($t.TaskName)" + if ($PSCmdlet.ShouldProcess("Scheduled Task $fullName", "Disable + Unregister")) { + Try-Run { Disable-ScheduledTask -TaskName $t.TaskName -TaskPath $t.TaskPath -ErrorAction SilentlyContinue | Out-Null } "Failed disabling task $fullName:" + Try-Run { Unregister-ScheduledTask -TaskName $t.TaskName -TaskPath $t.TaskPath -Confirm:$false -ErrorAction SilentlyContinue | Out-Null } "Failed unregistering task $fullName:" + } + } + + if (-not $tasks) { + Write-Log -message "No OneDrive scheduled tasks found." -severity 'INFO' -source 'BootStrap' -logName 'Application' + } + } "Could not enumerate scheduled tasks:" + + Write-Log -message "3) Uninstall OneDrive (winget if available, then built-in uninstallers)" -severity 'INFO' -source 'BootStrap' -logName 'Application' + + $winget = Get-Command winget -ErrorAction SilentlyContinue + if ($winget) { + if ($PSCmdlet.ShouldProcess("OneDrive via winget", "winget uninstall Microsoft.OneDrive")) { + Try-Run { + & winget uninstall --id Microsoft.OneDrive -e --accept-source-agreements --accept-package-agreements | Out-Null + } "winget uninstall failed:" + } + } else { + Write-Log -message "winget not found; skipping winget uninstall." -severity 'DEBUG' -source 'BootStrap' -logName 'Application' + } + + $setupPaths = @( + Join-Path $env:SystemRoot "System32\OneDriveSetup.exe", + Join-Path $env:SystemRoot "SysWOW64\OneDriveSetup.exe" + ) | Select-Object -Unique + + foreach ($path in $setupPaths) { + if (Test-Path $path) { + if ($PSCmdlet.ShouldProcess($path, "Run /uninstall")) { + Try-Run { Start-Process -FilePath $path -ArgumentList "/uninstall" -Wait -WindowStyle Hidden } "Failed running $path /uninstall:" + } + } else { + Write-Log -message "Not found: $path" -severity 'DEBUG' -source 'BootStrap' -logName 'Application' + } + } + + Write-Log -message "4) Remove OneDrive from startup/run hooks" -severity 'INFO' -source 'BootStrap' -logName 'Application' + + $runKeys = @( + "HKCU:\Software\Microsoft\Windows\CurrentVersion\Run", + "HKCU:\Software\Microsoft\Windows\CurrentVersion\RunOnce", + "HKLM:\Software\Microsoft\Windows\CurrentVersion\Run", + "HKLM:\Software\Microsoft\Windows\CurrentVersion\RunOnce" + ) + + foreach ($k in $runKeys) { + if (Test-Path $k) { + foreach ($name in @("OneDrive","OneDriveSetup","Microsoft OneDrive")) { + if ($PSCmdlet.ShouldProcess("$k\$name", "Remove-ItemProperty")) { + Try-Run { Remove-ItemProperty -Path $k -Name $name -ErrorAction SilentlyContinue } "Failed removing Run key value $k\$name:" + } + } + } + } + + $startupFolders = @( + Join-Path $env:APPDATA "Microsoft\Windows\Start Menu\Programs\Startup", + Join-Path $env:ProgramData "Microsoft\Windows\Start Menu\Programs\Startup" + ) + + foreach ($sf in $startupFolders) { + if (Test-Path $sf) { + Get-ChildItem -Path $sf -Filter "*OneDrive*.lnk" -ErrorAction SilentlyContinue | ForEach-Object { + if ($PSCmdlet.ShouldProcess($_.FullName, "Remove-Item")) { + Try-Run { Remove-Item -LiteralPath $_.FullName -Force -ErrorAction SilentlyContinue } "Failed removing startup shortcut $($_.FullName):" + } + } + } + } + + Write-Log -message "5) Disable OneDrive via policy (prevents sign-in/sync)" -severity 'INFO' -source 'BootStrap' -logName 'Application' + + $policyPath = "HKLM:\SOFTWARE\Policies\Microsoft\Windows\OneDrive" + if ($PSCmdlet.ShouldProcess($policyPath, "Set DisableFileSyncNGSC=1")) { + Try-Run { + New-Item -Path $policyPath -Force | Out-Null + New-ItemProperty -Path $policyPath -Name "DisableFileSyncNGSC" -PropertyType DWord -Value 1 -Force | Out-Null + } "Failed setting DisableFileSyncNGSC policy:" + } + + Write-Log -message "6) Remove File Explorer integration (sidebar pin + namespace entries)" -severity 'INFO' -source 'BootStrap' -logName 'Application' + + $clsid = "{018D5C66-4533-4307-9B53-224DE2ED1FE6}" + + foreach ($k in @("HKCR:\CLSID\$clsid","HKCR:\Wow6432Node\CLSID\$clsid")) { + if ($PSCmdlet.ShouldProcess($k, "Set System.IsPinnedToNameSpaceTree=0")) { + Try-Run { + New-Item -Path $k -Force | Out-Null + New-ItemProperty -Path $k -Name "System.IsPinnedToNameSpaceTree" -PropertyType DWord -Value 0 -Force | Out-Null + } "Failed setting nav pane pin value at $k:" + } + } + + foreach ($k in @( + "HKCU:\Software\Microsoft\Windows\CurrentVersion\Explorer\Desktop\NameSpace\$clsid", + "HKLM:\Software\Microsoft\Windows\CurrentVersion\Explorer\Desktop\NameSpace\$clsid", + "HKLM:\Software\Wow6432Node\Microsoft\Windows\CurrentVersion\Explorer\Desktop\NameSpace\$clsid" + )) { + if (Test-Path $k -PathType Container) { + if ($PSCmdlet.ShouldProcess($k, "Remove-Item -Recurse -Force")) { + Try-Run { Remove-Item -Path $k -Recurse -Force -ErrorAction SilentlyContinue } "Failed removing namespace key $k:" + } + } + } + + Write-Log -message "7) Remove leftover folders (optional purge of user data)" -severity 'INFO' -source 'BootStrap' -logName 'Application' + + $folders = @( + Join-Path $env:LOCALAPPDATA "Microsoft\OneDrive", + Join-Path $env:PROGRAMDATA "Microsoft OneDrive", + Join-Path $env:SystemDrive "OneDriveTemp" + ) + + if ($PurgeUserData) { + $folders += (Join-Path $env:USERPROFILE "OneDrive") + } + + foreach ($f in ($folders | Select-Object -Unique)) { + if (Test-Path $f) { + if ($PSCmdlet.ShouldProcess($f, "Remove-Item -Recurse -Force")) { + Try-Run { Remove-Item -LiteralPath $f -Recurse -Force -ErrorAction SilentlyContinue } "Failed removing folder $f:" + } + } + } + + Write-Log -message "8) Restart Explorer to apply UI changes" -severity 'INFO' -source 'BootStrap' -logName 'Application' + + if ($PSCmdlet.ShouldProcess("explorer.exe", "Restart Explorer")) { + Try-Run { + Get-Process explorer -ErrorAction SilentlyContinue | Stop-Process -Force -ErrorAction SilentlyContinue + Start-Process explorer.exe + } "Failed restarting Explorer:" + } + + Write-Log -message "OneDrive removal/disable steps completed. Recommend reboot to finalize." -severity 'INFO' -source 'BootStrap' -logName 'Application' + if (-not $PurgeUserData) { + Write-Log -message "NOTE: %UserProfile%\OneDrive was NOT deleted. Use -PurgeUserData to delete it." -severity 'WARN' -source 'BootStrap' -logName 'Application' + } +} + # IMPORTANT: use 'Continue' so normal AppX noise doesn't hard-fail Puppet $ErrorActionPreference = 'Continue' @@ -128,9 +296,7 @@ function Remove-PreinstalledAppxPackages { Start-Process $p -ArgumentList '/uninstall' -Wait -NoNewWindow } } - reg add "HKLM\SOFTWARE\Policies\Microsoft\Windows\OneDrive" /v DisableFileSyncNGSC /t REG_DWORD /d 1 /f - reg add "HKCR\CLSID\{018D5C66-4533-4307-9B53-224DE2ED1FE6}" /v System.IsPinnedToNameSpaceTree /t REG_DWORD /d 0 /f - reg add "HKCR\Wow6432Node\CLSID\{018D5C66-4533-4307-9B53-224DE2ED1FE6}" /v System.IsPinnedToNameSpaceTree /t REG_DWORD /d 0 /f + Remove-OneDriveAggressive } function Disable-AppXSvcCore { From 797c430257e6f417bbe529b789db1fb90d678283 Mon Sep 17 00:00:00 2001 From: Mark Cornmesser Date: Tue, 30 Dec 2025 13:21:46 -0800 Subject: [PATCH 051/105] testing --- .../files/appxpackages/uninstall.ps1 | 28 ++++++++++--------- 1 file changed, 15 insertions(+), 13 deletions(-) diff --git a/modules/win_disable_services/files/appxpackages/uninstall.ps1 b/modules/win_disable_services/files/appxpackages/uninstall.ps1 index c86d03533..fb2723021 100644 --- a/modules/win_disable_services/files/appxpackages/uninstall.ps1 +++ b/modules/win_disable_services/files/appxpackages/uninstall.ps1 @@ -50,7 +50,7 @@ function Remove-OneDriveAggressive { Get-Process -Name $p -ErrorAction SilentlyContinue | ForEach-Object { $desc = "Process $($_.Name) (Id=$($_.Id))" if ($PSCmdlet.ShouldProcess($desc, "Stop-Process -Force")) { - Try-Run { Stop-Process -Id $_.Id -Force -ErrorAction Stop } "Failed stopping $desc:" + Try-Run { Stop-Process -Id $_.Id -Force -ErrorAction Stop } "Failed stopping ${desc}:" } } } @@ -65,8 +65,8 @@ function Remove-OneDriveAggressive { foreach ($t in $tasks) { $fullName = "$($t.TaskPath)$($t.TaskName)" if ($PSCmdlet.ShouldProcess("Scheduled Task $fullName", "Disable + Unregister")) { - Try-Run { Disable-ScheduledTask -TaskName $t.TaskName -TaskPath $t.TaskPath -ErrorAction SilentlyContinue | Out-Null } "Failed disabling task $fullName:" - Try-Run { Unregister-ScheduledTask -TaskName $t.TaskName -TaskPath $t.TaskPath -Confirm:$false -ErrorAction SilentlyContinue | Out-Null } "Failed unregistering task $fullName:" + Try-Run { Disable-ScheduledTask -TaskName $t.TaskName -TaskPath $t.TaskPath -ErrorAction SilentlyContinue | Out-Null } "Failed disabling task ${fullName}:" + Try-Run { Unregister-ScheduledTask -TaskName $t.TaskName -TaskPath $t.TaskPath -Confirm:$false -ErrorAction SilentlyContinue | Out-Null } "Failed unregistering task ${fullName}:" } } @@ -116,7 +116,7 @@ function Remove-OneDriveAggressive { if (Test-Path $k) { foreach ($name in @("OneDrive","OneDriveSetup","Microsoft OneDrive")) { if ($PSCmdlet.ShouldProcess("$k\$name", "Remove-ItemProperty")) { - Try-Run { Remove-ItemProperty -Path $k -Name $name -ErrorAction SilentlyContinue } "Failed removing Run key value $k\$name:" + Try-Run { Remove-ItemProperty -Path $k -Name $name -ErrorAction SilentlyContinue } "Failed removing Run key value ${k}\${name}:" } } } @@ -156,7 +156,7 @@ function Remove-OneDriveAggressive { Try-Run { New-Item -Path $k -Force | Out-Null New-ItemProperty -Path $k -Name "System.IsPinnedToNameSpaceTree" -PropertyType DWord -Value 0 -Force | Out-Null - } "Failed setting nav pane pin value at $k:" + } "Failed setting nav pane pin value at ${k}:" } } @@ -167,7 +167,7 @@ function Remove-OneDriveAggressive { )) { if (Test-Path $k -PathType Container) { if ($PSCmdlet.ShouldProcess($k, "Remove-Item -Recurse -Force")) { - Try-Run { Remove-Item -Path $k -Recurse -Force -ErrorAction SilentlyContinue } "Failed removing namespace key $k:" + Try-Run { Remove-Item -Path $k -Recurse -Force -ErrorAction SilentlyContinue } "Failed removing namespace key ${k}:" } } } @@ -187,7 +187,7 @@ function Remove-OneDriveAggressive { foreach ($f in ($folders | Select-Object -Unique)) { if (Test-Path $f) { if ($PSCmdlet.ShouldProcess($f, "Remove-Item -Recurse -Force")) { - Try-Run { Remove-Item -LiteralPath $f -Recurse -Force -ErrorAction SilentlyContinue } "Failed removing folder $f:" + Try-Run { Remove-Item -LiteralPath $f -Recurse -Force -ErrorAction SilentlyContinue } "Failed removing folder ${f}:" } } } @@ -286,17 +286,19 @@ function Remove-PreinstalledAppxPackages { Remove-AppxPackage -ErrorAction SilentlyContinue | Out-Null } + $paths = @( "$env:SystemRoot\System32\OneDriveSetup.exe", "$env:SystemRoot\SysWOW64\OneDriveSetup.exe" - ) + ) - foreach ($p in $paths) { - if (Test-Path $p) { - Start-Process $p -ArgumentList '/uninstall' -Wait -NoNewWindow - } + foreach ($p in $paths) { + if (Test-Path $p) { + Start-Process $p -ArgumentList '/uninstall' -Wait -NoNewWindow } - Remove-OneDriveAggressive + } + + Remove-OneDriveAggressive } function Disable-AppXSvcCore { From 61ad59933e516e11f51bb231ba490c3515f2d31d Mon Sep 17 00:00:00 2001 From: Mark Cornmesser Date: Tue, 30 Dec 2025 14:22:34 -0800 Subject: [PATCH 052/105] testing --- .../files/appxpackages/uninstall.ps1 | 93 ++++++++----------- 1 file changed, 38 insertions(+), 55 deletions(-) diff --git a/modules/win_disable_services/files/appxpackages/uninstall.ps1 b/modules/win_disable_services/files/appxpackages/uninstall.ps1 index fb2723021..21ee16d1d 100644 --- a/modules/win_disable_services/files/appxpackages/uninstall.ps1 +++ b/modules/win_disable_services/files/appxpackages/uninstall.ps1 @@ -34,7 +34,7 @@ function Write-Log { } function Remove-OneDriveAggressive { - [CmdletBinding(SupportsShouldProcess = $true, ConfirmImpact = 'High')] + [CmdletBinding()] param( [switch]$PurgeUserData ) @@ -49,9 +49,7 @@ function Remove-OneDriveAggressive { foreach ($p in $procNames) { Get-Process -Name $p -ErrorAction SilentlyContinue | ForEach-Object { $desc = "Process $($_.Name) (Id=$($_.Id))" - if ($PSCmdlet.ShouldProcess($desc, "Stop-Process -Force")) { - Try-Run { Stop-Process -Id $_.Id -Force -ErrorAction Stop } "Failed stopping ${desc}:" - } + Try-Run { Stop-Process -Id $_.Id -Force -ErrorAction Stop } "Failed stopping ${desc}:" } } @@ -64,10 +62,8 @@ function Remove-OneDriveAggressive { foreach ($t in $tasks) { $fullName = "$($t.TaskPath)$($t.TaskName)" - if ($PSCmdlet.ShouldProcess("Scheduled Task $fullName", "Disable + Unregister")) { - Try-Run { Disable-ScheduledTask -TaskName $t.TaskName -TaskPath $t.TaskPath -ErrorAction SilentlyContinue | Out-Null } "Failed disabling task ${fullName}:" - Try-Run { Unregister-ScheduledTask -TaskName $t.TaskName -TaskPath $t.TaskPath -Confirm:$false -ErrorAction SilentlyContinue | Out-Null } "Failed unregistering task ${fullName}:" - } + Try-Run { Disable-ScheduledTask -TaskName $t.TaskName -TaskPath $t.TaskPath -ErrorAction SilentlyContinue | Out-Null } "Failed disabling task ${fullName}:" + Try-Run { Unregister-ScheduledTask -TaskName $t.TaskName -TaskPath $t.TaskPath -Confirm:$false -ErrorAction SilentlyContinue | Out-Null } "Failed unregistering task ${fullName}:" } if (-not $tasks) { @@ -79,11 +75,9 @@ function Remove-OneDriveAggressive { $winget = Get-Command winget -ErrorAction SilentlyContinue if ($winget) { - if ($PSCmdlet.ShouldProcess("OneDrive via winget", "winget uninstall Microsoft.OneDrive")) { - Try-Run { - & winget uninstall --id Microsoft.OneDrive -e --accept-source-agreements --accept-package-agreements | Out-Null - } "winget uninstall failed:" - } + Try-Run { + & winget uninstall --id Microsoft.OneDrive -e --accept-source-agreements --accept-package-agreements | Out-Null + } "winget uninstall failed:" } else { Write-Log -message "winget not found; skipping winget uninstall." -severity 'DEBUG' -source 'BootStrap' -logName 'Application' } @@ -95,9 +89,7 @@ function Remove-OneDriveAggressive { foreach ($path in $setupPaths) { if (Test-Path $path) { - if ($PSCmdlet.ShouldProcess($path, "Run /uninstall")) { - Try-Run { Start-Process -FilePath $path -ArgumentList "/uninstall" -Wait -WindowStyle Hidden } "Failed running $path /uninstall:" - } + Try-Run { Start-Process -FilePath $path -ArgumentList "/uninstall" -Wait -WindowStyle Hidden } "Failed running $path /uninstall:" } else { Write-Log -message "Not found: $path" -severity 'DEBUG' -source 'BootStrap' -logName 'Application' } @@ -115,9 +107,7 @@ function Remove-OneDriveAggressive { foreach ($k in $runKeys) { if (Test-Path $k) { foreach ($name in @("OneDrive","OneDriveSetup","Microsoft OneDrive")) { - if ($PSCmdlet.ShouldProcess("$k\$name", "Remove-ItemProperty")) { - Try-Run { Remove-ItemProperty -Path $k -Name $name -ErrorAction SilentlyContinue } "Failed removing Run key value ${k}\${name}:" - } + Try-Run { Remove-ItemProperty -Path $k -Name $name -ErrorAction SilentlyContinue } "Failed removing Run key value ${k}\${name}:" } } } @@ -130,9 +120,7 @@ function Remove-OneDriveAggressive { foreach ($sf in $startupFolders) { if (Test-Path $sf) { Get-ChildItem -Path $sf -Filter "*OneDrive*.lnk" -ErrorAction SilentlyContinue | ForEach-Object { - if ($PSCmdlet.ShouldProcess($_.FullName, "Remove-Item")) { - Try-Run { Remove-Item -LiteralPath $_.FullName -Force -ErrorAction SilentlyContinue } "Failed removing startup shortcut $($_.FullName):" - } + Try-Run { Remove-Item -LiteralPath $_.FullName -Force -ErrorAction SilentlyContinue } "Failed removing startup shortcut $($_.FullName):" } } } @@ -140,24 +128,20 @@ function Remove-OneDriveAggressive { Write-Log -message "5) Disable OneDrive via policy (prevents sign-in/sync)" -severity 'INFO' -source 'BootStrap' -logName 'Application' $policyPath = "HKLM:\SOFTWARE\Policies\Microsoft\Windows\OneDrive" - if ($PSCmdlet.ShouldProcess($policyPath, "Set DisableFileSyncNGSC=1")) { - Try-Run { - New-Item -Path $policyPath -Force | Out-Null - New-ItemProperty -Path $policyPath -Name "DisableFileSyncNGSC" -PropertyType DWord -Value 1 -Force | Out-Null - } "Failed setting DisableFileSyncNGSC policy:" - } + Try-Run { + New-Item -Path $policyPath -Force | Out-Null + New-ItemProperty -Path $policyPath -Name "DisableFileSyncNGSC" -PropertyType DWord -Value 1 -Force | Out-Null + } "Failed setting DisableFileSyncNGSC policy:" Write-Log -message "6) Remove File Explorer integration (sidebar pin + namespace entries)" -severity 'INFO' -source 'BootStrap' -logName 'Application' $clsid = "{018D5C66-4533-4307-9B53-224DE2ED1FE6}" foreach ($k in @("HKCR:\CLSID\$clsid","HKCR:\Wow6432Node\CLSID\$clsid")) { - if ($PSCmdlet.ShouldProcess($k, "Set System.IsPinnedToNameSpaceTree=0")) { - Try-Run { - New-Item -Path $k -Force | Out-Null - New-ItemProperty -Path $k -Name "System.IsPinnedToNameSpaceTree" -PropertyType DWord -Value 0 -Force | Out-Null - } "Failed setting nav pane pin value at ${k}:" - } + Try-Run { + New-Item -Path $k -Force | Out-Null + New-ItemProperty -Path $k -Name "System.IsPinnedToNameSpaceTree" -PropertyType DWord -Value 0 -Force | Out-Null + } "Failed setting nav pane pin value at ${k}:" } foreach ($k in @( @@ -166,9 +150,7 @@ function Remove-OneDriveAggressive { "HKLM:\Software\Wow6432Node\Microsoft\Windows\CurrentVersion\Explorer\Desktop\NameSpace\$clsid" )) { if (Test-Path $k -PathType Container) { - if ($PSCmdlet.ShouldProcess($k, "Remove-Item -Recurse -Force")) { - Try-Run { Remove-Item -Path $k -Recurse -Force -ErrorAction SilentlyContinue } "Failed removing namespace key ${k}:" - } + Try-Run { Remove-Item -Path $k -Recurse -Force -ErrorAction SilentlyContinue } "Failed removing namespace key ${k}:" } } @@ -186,20 +168,16 @@ function Remove-OneDriveAggressive { foreach ($f in ($folders | Select-Object -Unique)) { if (Test-Path $f) { - if ($PSCmdlet.ShouldProcess($f, "Remove-Item -Recurse -Force")) { - Try-Run { Remove-Item -LiteralPath $f -Recurse -Force -ErrorAction SilentlyContinue } "Failed removing folder ${f}:" - } + Try-Run { Remove-Item -LiteralPath $f -Recurse -Force -ErrorAction SilentlyContinue } "Failed removing folder ${f}:" } } Write-Log -message "8) Restart Explorer to apply UI changes" -severity 'INFO' -source 'BootStrap' -logName 'Application' - if ($PSCmdlet.ShouldProcess("explorer.exe", "Restart Explorer")) { - Try-Run { - Get-Process explorer -ErrorAction SilentlyContinue | Stop-Process -Force -ErrorAction SilentlyContinue - Start-Process explorer.exe - } "Failed restarting Explorer:" - } + Try-Run { + Get-Process explorer -ErrorAction SilentlyContinue | Stop-Process -Force -ErrorAction SilentlyContinue + Start-Process explorer.exe + } "Failed restarting Explorer:" Write-Log -message "OneDrive removal/disable steps completed. Recommend reboot to finalize." -severity 'INFO' -source 'BootStrap' -logName 'Application' if (-not $PurgeUserData) { @@ -271,7 +249,7 @@ function Remove-PreinstalledAppxPackages { } foreach ($Key in $apps.Keys) { - $Item = $apps[$Key] + $null = $apps[$Key] # keep, in case you add logging later Get-AppxProvisionedPackage -Online | Where-Object { $_.PackageName -like ("*{0}*" -f $Key) } | @@ -316,6 +294,13 @@ function Disable-AppXSvcCore { if (Test-Path $svcKeyPath) { New-ItemProperty -Path $svcKeyPath -Name Start -Value 4 -PropertyType DWord -Force | Out-Null } + + # Best-effort: give it a moment to stop (can be sticky during provisioning) + for ($i=0; $i -lt 10; $i++) { + $s = Get-Service -Name $svcName -ErrorAction SilentlyContinue + if ($null -eq $s -or $s.Status -eq 'Stopped') { break } + Start-Sleep -Seconds 1 + } } function Ensure-AppXSvcHardeningTask { @@ -379,21 +364,19 @@ function Test-AppXSvcDisabled { param() $svc = Get-Service -Name $svcName -ErrorAction SilentlyContinue + if ($null -eq $svc) { return $true } - if ($null -eq $svc) { - return $true - } - - $startType = $svc.StartType.ToString() - if ($svc.Status -eq 'Stopped' -and $startType -eq 'Disabled') { + # Success condition: Disabled. It may still be Running during early provisioning. + if ($svc.StartType.ToString() -eq 'Disabled') { + if ($svc.Status -ne 'Stopped') { + Write-Log -message ("uninstall_appx_packages :: AppXSvc is Disabled but currently {0}. Will be enforced at next boot." -f $svc.Status) -severity 'WARN' + } return $true } return $false } -# --- Main flow --------------------------------------------------------------- - Write-Log -message 'uninstall_appx_packages :: begin' -severity 'DEBUG' Write-Log -message 'uninstall_appx_packages :: Remove-PreinstalledAppxPackages' -severity 'DEBUG' From a243c8b9ea4ee1b18944113adc459412233643b6 Mon Sep 17 00:00:00 2001 From: Mark Cornmesser Date: Tue, 30 Dec 2025 15:13:39 -0800 Subject: [PATCH 053/105] testing --- .../files/maintainsystem-hw.ps1 | 51 +++++++++++++++++++ 1 file changed, 51 insertions(+) diff --git a/modules/win_scheduled_tasks/files/maintainsystem-hw.ps1 b/modules/win_scheduled_tasks/files/maintainsystem-hw.ps1 index 6d280fb8a..1a31e9fed 100644 --- a/modules/win_scheduled_tasks/files/maintainsystem-hw.ps1 +++ b/modules/win_scheduled_tasks/files/maintainsystem-hw.ps1 @@ -43,6 +43,56 @@ function Write-Log { } } +function Remove-OneDriveScheduledTasks { + [CmdletBinding()] + param() + + begin { + Write-Log -message ('{0} :: begin - {1:o}' -f $($MyInvocation.MyCommand.Name), (Get-Date).ToUniversalTime()) -severity 'DEBUG' + } + + process { + try { + # Grab tasks that look like OneDrive across the whole Task Scheduler library + $tasks = @(Get-ScheduledTask -ErrorAction Stop | Where-Object { + $_.TaskName -match '(?i)onedrive' -or $_.TaskPath -match '(?i)onedrive' + }) + + if (-not $tasks -or $tasks.Count -eq 0) { + Write-Log -message ('{0} :: No OneDrive scheduled tasks found' -f $($MyInvocation.MyCommand.Name)) -severity 'DEBUG' + return + } + + Write-Log -message ('{0} :: Found {1} OneDrive scheduled task(s)' -f $($MyInvocation.MyCommand.Name), $tasks.Count) -severity 'INFO' + + foreach ($t in $tasks) { + $fullName = '{0}{1}' -f $t.TaskPath, $t.TaskName + + try { + Disable-ScheduledTask -TaskName $t.TaskName -TaskPath $t.TaskPath -ErrorAction SilentlyContinue | Out-Null + } catch { + Write-Log -message ('{0} :: Failed to disable task {1}: {2}' -f $($MyInvocation.MyCommand.Name), $fullName, $_.Exception.Message) -severity 'WARN' + } + + try { + Unregister-ScheduledTask -TaskName $t.TaskName -TaskPath $t.TaskPath -Confirm:$false -ErrorAction SilentlyContinue | Out-Null + Write-Log -message ('{0} :: Removed task {1}' -f $($MyInvocation.MyCommand.Name), $fullName) -severity 'INFO' + } catch { + Write-Log -message ('{0} :: Failed to remove task {1}: {2}' -f $($MyInvocation.MyCommand.Name), $fullName, $_.Exception.Message) -severity 'WARN' + } + } + } + catch { + # If task scheduler bits aren't ready yet during very early bootstrap, don't hard-fail. + Write-Log -message ('{0} :: Could not enumerate scheduled tasks: {1}' -f $($MyInvocation.MyCommand.Name), $_.Exception.Message) -severity 'WARN' + } + } + + end { + Write-Log -message ('{0} :: end - {1:o}' -f $($MyInvocation.MyCommand.Name), (Get-Date).ToUniversalTime()) -severity 'DEBUG' + } +} + function Run-MaintainSystem { begin { Write-Log -message ('{0} :: begin - {1:o}' -f $($MyInvocation.MyCommand.Name), (Get-Date).ToUniversalTime()) -severity 'DEBUG' @@ -549,6 +599,7 @@ If ($bootstrap_stage -eq 'complete') { } } Disable-PerUserUwpServices + Remove-OneDriveScheduledTasks ## Let's make sure the machine is online before checking the internet Test-ConnectionUntilOnline From fc1a3fa1ce2d76a90102ab4d63f2417ff9b58549 Mon Sep 17 00:00:00 2001 From: Mark Cornmesser Date: Tue, 30 Dec 2025 16:25:03 -0800 Subject: [PATCH 054/105] testing --- .../files/appxpackages/uninstall.ps1 | 87 ++++++++++++++++++- 1 file changed, 86 insertions(+), 1 deletion(-) diff --git a/modules/win_disable_services/files/appxpackages/uninstall.ps1 b/modules/win_disable_services/files/appxpackages/uninstall.ps1 index 21ee16d1d..fa57758ac 100644 --- a/modules/win_disable_services/files/appxpackages/uninstall.ps1 +++ b/modules/win_disable_services/files/appxpackages/uninstall.ps1 @@ -33,6 +33,91 @@ function Write-Log { } } +function Ensure-OneDriveTaskCleanupHardeningTask { + [CmdletBinding()] + param() + + $dir = 'C:\ProgramData\Hardening' + $file = Join-Path $dir 'Remove-OneDriveScheduledTasks.ps1' + + Write-Log -message "OneDriveTasksHardening :: begin" -severity 'DEBUG' + + try { + if (-not (Test-Path $dir)) { New-Item -ItemType Directory -Path $dir -Force | Out-Null } + + # Minimal self-contained script: uses schtasks.exe only and writes to Event Log using your source/logName. + $payload = @' +function Write-Log { + param ( + [string] $message, + [string] $severity = 'INFO', + [string] $source = 'MaintainSystem', + [string] $logName = 'Application' + ) + try { + if (!([Diagnostics.EventLog]::Exists($logName)) -or !([Diagnostics.EventLog]::SourceExists($source))) { + New-EventLog -LogName $logName -Source $source + } + switch ($severity) { + 'DEBUG' { $entryType = 'SuccessAudit'; $eventId = 2; break } + 'WARN' { $entryType = 'Warning'; $eventId = 3; break } + 'ERROR' { $entryType = 'Error'; $eventId = 4; break } + default { $entryType = 'Information'; $eventId = 1; break } + } + Write-EventLog -LogName $logName -Source $source -EntryType $entryType -Category 0 -EventID $eventId -Message $message + } catch { } +} + +try { + $rows = @(schtasks.exe /Query /FO CSV /V 2>$null | ConvertFrom-Csv) + $targets = $rows | Where-Object { + ($_.TaskName -match '(?i)onedrive') -or + (($_.'Task To Run') -and (($_.'Task To Run') -match '(?i)onedrive(\\.exe)?')) -or + (($_.Actions) -and ($_.Actions -match '(?i)onedrive(\\.exe)?')) -or + (($_.'Task Run') -and (($_.'Task Run') -match '(?i)onedrive(\\.exe)?')) -or + (($_.Actions) -and ($_.Actions -match '(?i)OneDriveSetup\.exe|\\OneDrive\.exe')) -or + (($_.'Task To Run') -and (($_.'Task To Run') -match '(?i)OneDriveSetup\.exe|\\OneDrive\.exe')) + } | Select-Object -ExpandProperty TaskName -Unique + + foreach ($tn in $targets) { + schtasks.exe /Delete /TN "$tn" /F 2>$null | Out-Null + } + + Write-Log -message ("OneDriveTasksHardening :: removed {0} task(s)" -f ($targets.Count)) -severity 'INFO' +} catch { + Write-Log -message ("OneDriveTasksHardening :: failed: {0}" -f $_.Exception.Message) -severity 'WARN' +} +'@ + + Set-Content -Path $file -Value $payload -Encoding UTF8 -Force + + $taskName = 'Remove-OneDriveScheduledTasks' + $taskPath = '\Hardening\' + + schtasks.exe /Delete /TN "$taskPath$taskName" /F 2>$null | Out-Null + + # Create: AtStartup + schtasks.exe /Create /F /TN "$taskPath$taskName" ` + /SC ONSTART /RU SYSTEM /RL HIGHEST ` + /TR "powershell.exe -NoLogo -NonInteractive -WindowStyle Hidden -ExecutionPolicy Bypass -File `"$file`"" ` + 2>$null | Out-Null + + # Add a second trigger: AtLogOn (any user) + schtasks.exe /Create /F /TN "$taskPath$taskName-Logon" ` + /SC ONLOGON /RU SYSTEM /RL HIGHEST ` + /TR "powershell.exe -NoLogo -NonInteractive -WindowStyle Hidden -ExecutionPolicy Bypass -File `"$file`"" ` + 2>$null | Out-Null + + Write-Log -message "OneDriveTasksHardening :: installed (ONSTART + ONLOGON)" -severity 'INFO' + } + catch { + Write-Log -message ("OneDriveTasksHardening :: failed: {0}" -f $_.Exception.Message) -severity 'WARN' + } + finally { + Write-Log -message "OneDriveTasksHardening :: end" -severity 'DEBUG' + } +} + function Remove-OneDriveAggressive { [CmdletBinding()] param( @@ -276,7 +361,7 @@ function Remove-PreinstalledAppxPackages { } } - Remove-OneDriveAggressive + Ensure-OneDriveTaskCleanupHardeningTask } function Disable-AppXSvcCore { From 73871b92883e8109c0ee0e99e9c306fe2d775c04 Mon Sep 17 00:00:00 2001 From: Mark Cornmesser Date: Tue, 30 Dec 2025 17:04:36 -0800 Subject: [PATCH 055/105] testing --- .../files/appxpackages/uninstall.ps1 | 55 ++++++++++++++++++- 1 file changed, 54 insertions(+), 1 deletion(-) diff --git a/modules/win_disable_services/files/appxpackages/uninstall.ps1 b/modules/win_disable_services/files/appxpackages/uninstall.ps1 index fa57758ac..ad9fc3ab8 100644 --- a/modules/win_disable_services/files/appxpackages/uninstall.ps1 +++ b/modules/win_disable_services/files/appxpackages/uninstall.ps1 @@ -118,6 +118,59 @@ try { } } +function Remove-OneDriveScheduledTasks { + [CmdletBinding()] + param() + + Write-Log -message "OneDriveTasks :: begin" -severity 'DEBUG' + + try { + $rows = @(schtasks.exe /Query /FO CSV /V 2>$null | ConvertFrom-Csv) + + if (-not $rows -or $rows.Count -eq 0) { + Write-Log -message "OneDriveTasks :: schtasks returned no rows" -severity 'WARN' + return + } + + # Columns vary a bit across Windows builds, so check multiple possible fields. + $targets = $rows | Where-Object { + ($_.TaskName -match '(?i)onedrive') -or + (($_.'Task To Run') -and (($_.'Task To Run') -match '(?i)onedrive(\\.exe)?')) -or + (($_.Actions) -and ($_.Actions -match '(?i)onedrive(\\.exe)?')) -or + (($_.'Task Run') -and (($_.'Task Run') -match '(?i)onedrive(\\.exe)?')) -or + # extra-tight match on known binaries + (($_.Actions) -and ($_.Actions -match '(?i)OneDriveSetup\.exe|\\OneDrive\.exe')) -or + (($_.'Task To Run') -and (($_.'Task To Run') -match '(?i)OneDriveSetup\.exe|\\OneDrive\.exe')) + } | Select-Object -ExpandProperty TaskName -Unique + + if (-not $targets -or $targets.Count -eq 0) { + Write-Log -message "OneDriveTasks :: No matching tasks found" -severity 'DEBUG' + return + } + + Write-Log -message ("OneDriveTasks :: Found {0} task(s) to remove" -f $targets.Count) -severity 'INFO' + + foreach ($tn in $targets) { + try { + schtasks.exe /Delete /TN "$tn" /F 2>$null | Out-Null + if ($LASTEXITCODE -eq 0) { + Write-Log -message ("OneDriveTasks :: Deleted {0}" -f $tn) -severity 'INFO' + } else { + Write-Log -message ("OneDriveTasks :: Failed delete {0} (exit {1})" -f $tn, $LASTEXITCODE) -severity 'WARN' + } + } catch { + Write-Log -message ("OneDriveTasks :: Exception deleting {0}: {1}" -f $tn, $_.Exception.Message) -severity 'WARN' + } + } + } + catch { + Write-Log -message ("OneDriveTasks :: failed: {0}" -f $_.Exception.Message) -severity 'WARN' + } + finally { + Write-Log -message "OneDriveTasks :: end" -severity 'DEBUG' + } +} + function Remove-OneDriveAggressive { [CmdletBinding()] param( @@ -360,7 +413,7 @@ function Remove-PreinstalledAppxPackages { Start-Process $p -ArgumentList '/uninstall' -Wait -NoNewWindow } } - + Remove-OneDriveScheduledTasks Ensure-OneDriveTaskCleanupHardeningTask } From 471869c516bd07122061a0c11d10a439d29cd975 Mon Sep 17 00:00:00 2001 From: Mark Cornmesser Date: Wed, 31 Dec 2025 09:05:59 -0800 Subject: [PATCH 056/105] testing --- .../files/maintainsystem-hw.ps1 | 71 ++++++++++--------- 1 file changed, 37 insertions(+), 34 deletions(-) diff --git a/modules/win_scheduled_tasks/files/maintainsystem-hw.ps1 b/modules/win_scheduled_tasks/files/maintainsystem-hw.ps1 index 1a31e9fed..3a77c28ee 100644 --- a/modules/win_scheduled_tasks/files/maintainsystem-hw.ps1 +++ b/modules/win_scheduled_tasks/files/maintainsystem-hw.ps1 @@ -47,49 +47,52 @@ function Remove-OneDriveScheduledTasks { [CmdletBinding()] param() - begin { - Write-Log -message ('{0} :: begin - {1:o}' -f $($MyInvocation.MyCommand.Name), (Get-Date).ToUniversalTime()) -severity 'DEBUG' - } + Write-Log -message "OneDriveTasks :: begin" -severity 'DEBUG' - process { - try { - # Grab tasks that look like OneDrive across the whole Task Scheduler library - $tasks = @(Get-ScheduledTask -ErrorAction Stop | Where-Object { - $_.TaskName -match '(?i)onedrive' -or $_.TaskPath -match '(?i)onedrive' - }) - - if (-not $tasks -or $tasks.Count -eq 0) { - Write-Log -message ('{0} :: No OneDrive scheduled tasks found' -f $($MyInvocation.MyCommand.Name)) -severity 'DEBUG' - return - } + try { + $rows = @(schtasks.exe /Query /FO CSV /V 2>$null | ConvertFrom-Csv) - Write-Log -message ('{0} :: Found {1} OneDrive scheduled task(s)' -f $($MyInvocation.MyCommand.Name), $tasks.Count) -severity 'INFO' + if (-not $rows -or $rows.Count -eq 0) { + Write-Log -message "OneDriveTasks :: schtasks returned no rows" -severity 'WARN' + return + } - foreach ($t in $tasks) { - $fullName = '{0}{1}' -f $t.TaskPath, $t.TaskName + # Columns vary a bit across Windows builds, so check multiple possible fields. + $targets = $rows | Where-Object { + ($_.TaskName -match '(?i)onedrive') -or + (($_.'Task To Run') -and (($_.'Task To Run') -match '(?i)onedrive(\\.exe)?')) -or + (($_.Actions) -and ($_.Actions -match '(?i)onedrive(\\.exe)?')) -or + (($_.'Task Run') -and (($_.'Task Run') -match '(?i)onedrive(\\.exe)?')) -or + # extra-tight match on known binaries + (($_.Actions) -and ($_.Actions -match '(?i)OneDriveSetup\.exe|\\OneDrive\.exe')) -or + (($_.'Task To Run') -and (($_.'Task To Run') -match '(?i)OneDriveSetup\.exe|\\OneDrive\.exe')) + } | Select-Object -ExpandProperty TaskName -Unique - try { - Disable-ScheduledTask -TaskName $t.TaskName -TaskPath $t.TaskPath -ErrorAction SilentlyContinue | Out-Null - } catch { - Write-Log -message ('{0} :: Failed to disable task {1}: {2}' -f $($MyInvocation.MyCommand.Name), $fullName, $_.Exception.Message) -severity 'WARN' - } + if (-not $targets -or $targets.Count -eq 0) { + Write-Log -message "OneDriveTasks :: No matching tasks found" -severity 'DEBUG' + return + } + + Write-Log -message ("OneDriveTasks :: Found {0} task(s) to remove" -f $targets.Count) -severity 'INFO' - try { - Unregister-ScheduledTask -TaskName $t.TaskName -TaskPath $t.TaskPath -Confirm:$false -ErrorAction SilentlyContinue | Out-Null - Write-Log -message ('{0} :: Removed task {1}' -f $($MyInvocation.MyCommand.Name), $fullName) -severity 'INFO' - } catch { - Write-Log -message ('{0} :: Failed to remove task {1}: {2}' -f $($MyInvocation.MyCommand.Name), $fullName, $_.Exception.Message) -severity 'WARN' + foreach ($tn in $targets) { + try { + schtasks.exe /Delete /TN "$tn" /F 2>$null | Out-Null + if ($LASTEXITCODE -eq 0) { + Write-Log -message ("OneDriveTasks :: Deleted {0}" -f $tn) -severity 'INFO' + } else { + Write-Log -message ("OneDriveTasks :: Failed delete {0} (exit {1})" -f $tn, $LASTEXITCODE) -severity 'WARN' } + } catch { + Write-Log -message ("OneDriveTasks :: Exception deleting {0}: {1}" -f $tn, $_.Exception.Message) -severity 'WARN' } } - catch { - # If task scheduler bits aren't ready yet during very early bootstrap, don't hard-fail. - Write-Log -message ('{0} :: Could not enumerate scheduled tasks: {1}' -f $($MyInvocation.MyCommand.Name), $_.Exception.Message) -severity 'WARN' - } } - - end { - Write-Log -message ('{0} :: end - {1:o}' -f $($MyInvocation.MyCommand.Name), (Get-Date).ToUniversalTime()) -severity 'DEBUG' + catch { + Write-Log -message ("OneDriveTasks :: failed: {0}" -f $_.Exception.Message) -severity 'WARN' + } + finally { + Write-Log -message "OneDriveTasks :: end" -severity 'DEBUG' } } From 928c79532860ee13c968261b3a95f3f915a54ec1 Mon Sep 17 00:00:00 2001 From: Mark Cornmesser Date: Wed, 31 Dec 2025 09:53:08 -0800 Subject: [PATCH 057/105] testing --- modules/win_scheduled_tasks/files/maintainsystem-hw.ps1 | 1 + 1 file changed, 1 insertion(+) diff --git a/modules/win_scheduled_tasks/files/maintainsystem-hw.ps1 b/modules/win_scheduled_tasks/files/maintainsystem-hw.ps1 index 3a77c28ee..6674a46ee 100644 --- a/modules/win_scheduled_tasks/files/maintainsystem-hw.ps1 +++ b/modules/win_scheduled_tasks/files/maintainsystem-hw.ps1 @@ -603,6 +603,7 @@ If ($bootstrap_stage -eq 'complete') { } Disable-PerUserUwpServices Remove-OneDriveScheduledTasks + pause ## Let's make sure the machine is online before checking the internet Test-ConnectionUntilOnline From 34fb7a5acdb212f058e6b0fbb0bad1d80f48fbdd Mon Sep 17 00:00:00 2001 From: Mark Cornmesser Date: Wed, 31 Dec 2025 10:36:44 -0800 Subject: [PATCH 058/105] testing --- .../files/appxpackages/uninstall.ps1 | 2 +- .../files/maintainsystem-hw.ps1 | 89 ++++++++++++++++++- 2 files changed, 88 insertions(+), 3 deletions(-) diff --git a/modules/win_disable_services/files/appxpackages/uninstall.ps1 b/modules/win_disable_services/files/appxpackages/uninstall.ps1 index ad9fc3ab8..912cac8de 100644 --- a/modules/win_disable_services/files/appxpackages/uninstall.ps1 +++ b/modules/win_disable_services/files/appxpackages/uninstall.ps1 @@ -413,7 +413,7 @@ function Remove-PreinstalledAppxPackages { Start-Process $p -ArgumentList '/uninstall' -Wait -NoNewWindow } } - Remove-OneDriveScheduledTasks + #Remove-OneDriveScheduledTasks Ensure-OneDriveTaskCleanupHardeningTask } diff --git a/modules/win_scheduled_tasks/files/maintainsystem-hw.ps1 b/modules/win_scheduled_tasks/files/maintainsystem-hw.ps1 index 6674a46ee..1aef047af 100644 --- a/modules/win_scheduled_tasks/files/maintainsystem-hw.ps1 +++ b/modules/win_scheduled_tasks/files/maintainsystem-hw.ps1 @@ -96,6 +96,91 @@ function Remove-OneDriveScheduledTasks { } } +function Ensure-OneDriveTaskCleanupHardeningTask { + [CmdletBinding()] + param() + + $dir = 'C:\ProgramData\Hardening' + $file = Join-Path $dir 'Remove-OneDriveScheduledTasks.ps1' + + Write-Log -message "OneDriveTasksHardening :: begin" -severity 'DEBUG' + + try { + if (-not (Test-Path $dir)) { New-Item -ItemType Directory -Path $dir -Force | Out-Null } + + # Minimal self-contained script: uses schtasks.exe only and writes to Event Log using your source/logName. + $payload = @' +function Write-Log { + param ( + [string] $message, + [string] $severity = 'INFO', + [string] $source = 'MaintainSystem', + [string] $logName = 'Application' + ) + try { + if (!([Diagnostics.EventLog]::Exists($logName)) -or !([Diagnostics.EventLog]::SourceExists($source))) { + New-EventLog -LogName $logName -Source $source + } + switch ($severity) { + 'DEBUG' { $entryType = 'SuccessAudit'; $eventId = 2; break } + 'WARN' { $entryType = 'Warning'; $eventId = 3; break } + 'ERROR' { $entryType = 'Error'; $eventId = 4; break } + default { $entryType = 'Information'; $eventId = 1; break } + } + Write-EventLog -LogName $logName -Source $source -EntryType $entryType -Category 0 -EventID $eventId -Message $message + } catch { } +} + +try { + $rows = @(schtasks.exe /Query /FO CSV /V 2>$null | ConvertFrom-Csv) + $targets = $rows | Where-Object { + ($_.TaskName -match '(?i)onedrive') -or + (($_.'Task To Run') -and (($_.'Task To Run') -match '(?i)onedrive(\\.exe)?')) -or + (($_.Actions) -and ($_.Actions -match '(?i)onedrive(\\.exe)?')) -or + (($_.'Task Run') -and (($_.'Task Run') -match '(?i)onedrive(\\.exe)?')) -or + (($_.Actions) -and ($_.Actions -match '(?i)OneDriveSetup\.exe|\\OneDrive\.exe')) -or + (($_.'Task To Run') -and (($_.'Task To Run') -match '(?i)OneDriveSetup\.exe|\\OneDrive\.exe')) + } | Select-Object -ExpandProperty TaskName -Unique + + foreach ($tn in $targets) { + schtasks.exe /Delete /TN "$tn" /F 2>$null | Out-Null + } + + Write-Log -message ("OneDriveTasksHardening :: removed {0} task(s)" -f ($targets.Count)) -severity 'INFO' +} catch { + Write-Log -message ("OneDriveTasksHardening :: failed: {0}" -f $_.Exception.Message) -severity 'WARN' +} +'@ + + Set-Content -Path $file -Value $payload -Encoding UTF8 -Force + + $taskName = 'Remove-OneDriveScheduledTasks' + $taskPath = '\Hardening\' + + schtasks.exe /Delete /TN "$taskPath$taskName" /F 2>$null | Out-Null + + # Create: AtStartup + schtasks.exe /Create /F /TN "$taskPath$taskName" ` + /SC ONSTART /RU SYSTEM /RL HIGHEST ` + /TR "powershell.exe -NoLogo -NonInteractive -WindowStyle Hidden -ExecutionPolicy Bypass -File `"$file`"" ` + 2>$null | Out-Null + + # Add a second trigger: AtLogOn (any user) + schtasks.exe /Create /F /TN "$taskPath$taskName-Logon" ` + /SC ONLOGON /RU SYSTEM /RL HIGHEST ` + /TR "powershell.exe -NoLogo -NonInteractive -WindowStyle Hidden -ExecutionPolicy Bypass -File `"$file`"" ` + 2>$null | Out-Null + + Write-Log -message "OneDriveTasksHardening :: installed (ONSTART + ONLOGON)" -severity 'INFO' + } + catch { + Write-Log -message ("OneDriveTasksHardening :: failed: {0}" -f $_.Exception.Message) -severity 'WARN' + } + finally { + Write-Log -message "OneDriveTasksHardening :: end" -severity 'DEBUG' + } +} + function Run-MaintainSystem { begin { Write-Log -message ('{0} :: begin - {1:o}' -f $($MyInvocation.MyCommand.Name), (Get-Date).ToUniversalTime()) -severity 'DEBUG' @@ -602,8 +687,8 @@ If ($bootstrap_stage -eq 'complete') { } } Disable-PerUserUwpServices - Remove-OneDriveScheduledTasks - pause + #Remove-OneDriveScheduledTasks + Ensure-OneDriveTaskCleanupHardeningTask ## Let's make sure the machine is online before checking the internet Test-ConnectionUntilOnline From 9378eede7cdfd04248d45666953e65e273655893 Mon Sep 17 00:00:00 2001 From: Mark Cornmesser Date: Wed, 31 Dec 2025 12:53:35 -0800 Subject: [PATCH 059/105] testing --- .../files/appxpackages/uninstall.ps1 | 292 ------------------ .../files/at_task_user_logon.ps1 | 141 +++++++++ .../files/maintainsystem-hw.ps1 | 140 --------- 3 files changed, 141 insertions(+), 432 deletions(-) diff --git a/modules/win_disable_services/files/appxpackages/uninstall.ps1 b/modules/win_disable_services/files/appxpackages/uninstall.ps1 index 912cac8de..b5a3a405c 100644 --- a/modules/win_disable_services/files/appxpackages/uninstall.ps1 +++ b/modules/win_disable_services/files/appxpackages/uninstall.ps1 @@ -33,296 +33,6 @@ function Write-Log { } } -function Ensure-OneDriveTaskCleanupHardeningTask { - [CmdletBinding()] - param() - - $dir = 'C:\ProgramData\Hardening' - $file = Join-Path $dir 'Remove-OneDriveScheduledTasks.ps1' - - Write-Log -message "OneDriveTasksHardening :: begin" -severity 'DEBUG' - - try { - if (-not (Test-Path $dir)) { New-Item -ItemType Directory -Path $dir -Force | Out-Null } - - # Minimal self-contained script: uses schtasks.exe only and writes to Event Log using your source/logName. - $payload = @' -function Write-Log { - param ( - [string] $message, - [string] $severity = 'INFO', - [string] $source = 'MaintainSystem', - [string] $logName = 'Application' - ) - try { - if (!([Diagnostics.EventLog]::Exists($logName)) -or !([Diagnostics.EventLog]::SourceExists($source))) { - New-EventLog -LogName $logName -Source $source - } - switch ($severity) { - 'DEBUG' { $entryType = 'SuccessAudit'; $eventId = 2; break } - 'WARN' { $entryType = 'Warning'; $eventId = 3; break } - 'ERROR' { $entryType = 'Error'; $eventId = 4; break } - default { $entryType = 'Information'; $eventId = 1; break } - } - Write-EventLog -LogName $logName -Source $source -EntryType $entryType -Category 0 -EventID $eventId -Message $message - } catch { } -} - -try { - $rows = @(schtasks.exe /Query /FO CSV /V 2>$null | ConvertFrom-Csv) - $targets = $rows | Where-Object { - ($_.TaskName -match '(?i)onedrive') -or - (($_.'Task To Run') -and (($_.'Task To Run') -match '(?i)onedrive(\\.exe)?')) -or - (($_.Actions) -and ($_.Actions -match '(?i)onedrive(\\.exe)?')) -or - (($_.'Task Run') -and (($_.'Task Run') -match '(?i)onedrive(\\.exe)?')) -or - (($_.Actions) -and ($_.Actions -match '(?i)OneDriveSetup\.exe|\\OneDrive\.exe')) -or - (($_.'Task To Run') -and (($_.'Task To Run') -match '(?i)OneDriveSetup\.exe|\\OneDrive\.exe')) - } | Select-Object -ExpandProperty TaskName -Unique - - foreach ($tn in $targets) { - schtasks.exe /Delete /TN "$tn" /F 2>$null | Out-Null - } - - Write-Log -message ("OneDriveTasksHardening :: removed {0} task(s)" -f ($targets.Count)) -severity 'INFO' -} catch { - Write-Log -message ("OneDriveTasksHardening :: failed: {0}" -f $_.Exception.Message) -severity 'WARN' -} -'@ - - Set-Content -Path $file -Value $payload -Encoding UTF8 -Force - - $taskName = 'Remove-OneDriveScheduledTasks' - $taskPath = '\Hardening\' - - schtasks.exe /Delete /TN "$taskPath$taskName" /F 2>$null | Out-Null - - # Create: AtStartup - schtasks.exe /Create /F /TN "$taskPath$taskName" ` - /SC ONSTART /RU SYSTEM /RL HIGHEST ` - /TR "powershell.exe -NoLogo -NonInteractive -WindowStyle Hidden -ExecutionPolicy Bypass -File `"$file`"" ` - 2>$null | Out-Null - - # Add a second trigger: AtLogOn (any user) - schtasks.exe /Create /F /TN "$taskPath$taskName-Logon" ` - /SC ONLOGON /RU SYSTEM /RL HIGHEST ` - /TR "powershell.exe -NoLogo -NonInteractive -WindowStyle Hidden -ExecutionPolicy Bypass -File `"$file`"" ` - 2>$null | Out-Null - - Write-Log -message "OneDriveTasksHardening :: installed (ONSTART + ONLOGON)" -severity 'INFO' - } - catch { - Write-Log -message ("OneDriveTasksHardening :: failed: {0}" -f $_.Exception.Message) -severity 'WARN' - } - finally { - Write-Log -message "OneDriveTasksHardening :: end" -severity 'DEBUG' - } -} - -function Remove-OneDriveScheduledTasks { - [CmdletBinding()] - param() - - Write-Log -message "OneDriveTasks :: begin" -severity 'DEBUG' - - try { - $rows = @(schtasks.exe /Query /FO CSV /V 2>$null | ConvertFrom-Csv) - - if (-not $rows -or $rows.Count -eq 0) { - Write-Log -message "OneDriveTasks :: schtasks returned no rows" -severity 'WARN' - return - } - - # Columns vary a bit across Windows builds, so check multiple possible fields. - $targets = $rows | Where-Object { - ($_.TaskName -match '(?i)onedrive') -or - (($_.'Task To Run') -and (($_.'Task To Run') -match '(?i)onedrive(\\.exe)?')) -or - (($_.Actions) -and ($_.Actions -match '(?i)onedrive(\\.exe)?')) -or - (($_.'Task Run') -and (($_.'Task Run') -match '(?i)onedrive(\\.exe)?')) -or - # extra-tight match on known binaries - (($_.Actions) -and ($_.Actions -match '(?i)OneDriveSetup\.exe|\\OneDrive\.exe')) -or - (($_.'Task To Run') -and (($_.'Task To Run') -match '(?i)OneDriveSetup\.exe|\\OneDrive\.exe')) - } | Select-Object -ExpandProperty TaskName -Unique - - if (-not $targets -or $targets.Count -eq 0) { - Write-Log -message "OneDriveTasks :: No matching tasks found" -severity 'DEBUG' - return - } - - Write-Log -message ("OneDriveTasks :: Found {0} task(s) to remove" -f $targets.Count) -severity 'INFO' - - foreach ($tn in $targets) { - try { - schtasks.exe /Delete /TN "$tn" /F 2>$null | Out-Null - if ($LASTEXITCODE -eq 0) { - Write-Log -message ("OneDriveTasks :: Deleted {0}" -f $tn) -severity 'INFO' - } else { - Write-Log -message ("OneDriveTasks :: Failed delete {0} (exit {1})" -f $tn, $LASTEXITCODE) -severity 'WARN' - } - } catch { - Write-Log -message ("OneDriveTasks :: Exception deleting {0}: {1}" -f $tn, $_.Exception.Message) -severity 'WARN' - } - } - } - catch { - Write-Log -message ("OneDriveTasks :: failed: {0}" -f $_.Exception.Message) -severity 'WARN' - } - finally { - Write-Log -message "OneDriveTasks :: end" -severity 'DEBUG' - } -} - -function Remove-OneDriveAggressive { - [CmdletBinding()] - param( - [switch]$PurgeUserData - ) - - function Try-Run([scriptblock]$sb, [string]$onError, [string]$severity = 'WARN') { - try { & $sb } catch { Write-Log -message "$onError $($_.Exception.Message)" -severity $severity -source 'BootStrap' -logName 'Application' } - } - - Write-Log -message "1) Stop OneDrive-related processes" -severity 'INFO' -source 'BootStrap' -logName 'Application' - - $procNames = @("OneDrive","OneDriveStandaloneUpdater","OneDriveSetup") - foreach ($p in $procNames) { - Get-Process -Name $p -ErrorAction SilentlyContinue | ForEach-Object { - $desc = "Process $($_.Name) (Id=$($_.Id))" - Try-Run { Stop-Process -Id $_.Id -Force -ErrorAction Stop } "Failed stopping ${desc}:" - } - } - - Write-Log -message "2) Disable and remove OneDrive scheduled tasks" -severity 'INFO' -source 'BootStrap' -logName 'Application' - - Try-Run { - $tasks = Get-ScheduledTask -ErrorAction Stop | Where-Object { - $_.TaskName -like "OneDrive*" -or $_.TaskPath -like "*OneDrive*" - } - - foreach ($t in $tasks) { - $fullName = "$($t.TaskPath)$($t.TaskName)" - Try-Run { Disable-ScheduledTask -TaskName $t.TaskName -TaskPath $t.TaskPath -ErrorAction SilentlyContinue | Out-Null } "Failed disabling task ${fullName}:" - Try-Run { Unregister-ScheduledTask -TaskName $t.TaskName -TaskPath $t.TaskPath -Confirm:$false -ErrorAction SilentlyContinue | Out-Null } "Failed unregistering task ${fullName}:" - } - - if (-not $tasks) { - Write-Log -message "No OneDrive scheduled tasks found." -severity 'INFO' -source 'BootStrap' -logName 'Application' - } - } "Could not enumerate scheduled tasks:" - - Write-Log -message "3) Uninstall OneDrive (winget if available, then built-in uninstallers)" -severity 'INFO' -source 'BootStrap' -logName 'Application' - - $winget = Get-Command winget -ErrorAction SilentlyContinue - if ($winget) { - Try-Run { - & winget uninstall --id Microsoft.OneDrive -e --accept-source-agreements --accept-package-agreements | Out-Null - } "winget uninstall failed:" - } else { - Write-Log -message "winget not found; skipping winget uninstall." -severity 'DEBUG' -source 'BootStrap' -logName 'Application' - } - - $setupPaths = @( - Join-Path $env:SystemRoot "System32\OneDriveSetup.exe", - Join-Path $env:SystemRoot "SysWOW64\OneDriveSetup.exe" - ) | Select-Object -Unique - - foreach ($path in $setupPaths) { - if (Test-Path $path) { - Try-Run { Start-Process -FilePath $path -ArgumentList "/uninstall" -Wait -WindowStyle Hidden } "Failed running $path /uninstall:" - } else { - Write-Log -message "Not found: $path" -severity 'DEBUG' -source 'BootStrap' -logName 'Application' - } - } - - Write-Log -message "4) Remove OneDrive from startup/run hooks" -severity 'INFO' -source 'BootStrap' -logName 'Application' - - $runKeys = @( - "HKCU:\Software\Microsoft\Windows\CurrentVersion\Run", - "HKCU:\Software\Microsoft\Windows\CurrentVersion\RunOnce", - "HKLM:\Software\Microsoft\Windows\CurrentVersion\Run", - "HKLM:\Software\Microsoft\Windows\CurrentVersion\RunOnce" - ) - - foreach ($k in $runKeys) { - if (Test-Path $k) { - foreach ($name in @("OneDrive","OneDriveSetup","Microsoft OneDrive")) { - Try-Run { Remove-ItemProperty -Path $k -Name $name -ErrorAction SilentlyContinue } "Failed removing Run key value ${k}\${name}:" - } - } - } - - $startupFolders = @( - Join-Path $env:APPDATA "Microsoft\Windows\Start Menu\Programs\Startup", - Join-Path $env:ProgramData "Microsoft\Windows\Start Menu\Programs\Startup" - ) - - foreach ($sf in $startupFolders) { - if (Test-Path $sf) { - Get-ChildItem -Path $sf -Filter "*OneDrive*.lnk" -ErrorAction SilentlyContinue | ForEach-Object { - Try-Run { Remove-Item -LiteralPath $_.FullName -Force -ErrorAction SilentlyContinue } "Failed removing startup shortcut $($_.FullName):" - } - } - } - - Write-Log -message "5) Disable OneDrive via policy (prevents sign-in/sync)" -severity 'INFO' -source 'BootStrap' -logName 'Application' - - $policyPath = "HKLM:\SOFTWARE\Policies\Microsoft\Windows\OneDrive" - Try-Run { - New-Item -Path $policyPath -Force | Out-Null - New-ItemProperty -Path $policyPath -Name "DisableFileSyncNGSC" -PropertyType DWord -Value 1 -Force | Out-Null - } "Failed setting DisableFileSyncNGSC policy:" - - Write-Log -message "6) Remove File Explorer integration (sidebar pin + namespace entries)" -severity 'INFO' -source 'BootStrap' -logName 'Application' - - $clsid = "{018D5C66-4533-4307-9B53-224DE2ED1FE6}" - - foreach ($k in @("HKCR:\CLSID\$clsid","HKCR:\Wow6432Node\CLSID\$clsid")) { - Try-Run { - New-Item -Path $k -Force | Out-Null - New-ItemProperty -Path $k -Name "System.IsPinnedToNameSpaceTree" -PropertyType DWord -Value 0 -Force | Out-Null - } "Failed setting nav pane pin value at ${k}:" - } - - foreach ($k in @( - "HKCU:\Software\Microsoft\Windows\CurrentVersion\Explorer\Desktop\NameSpace\$clsid", - "HKLM:\Software\Microsoft\Windows\CurrentVersion\Explorer\Desktop\NameSpace\$clsid", - "HKLM:\Software\Wow6432Node\Microsoft\Windows\CurrentVersion\Explorer\Desktop\NameSpace\$clsid" - )) { - if (Test-Path $k -PathType Container) { - Try-Run { Remove-Item -Path $k -Recurse -Force -ErrorAction SilentlyContinue } "Failed removing namespace key ${k}:" - } - } - - Write-Log -message "7) Remove leftover folders (optional purge of user data)" -severity 'INFO' -source 'BootStrap' -logName 'Application' - - $folders = @( - Join-Path $env:LOCALAPPDATA "Microsoft\OneDrive", - Join-Path $env:PROGRAMDATA "Microsoft OneDrive", - Join-Path $env:SystemDrive "OneDriveTemp" - ) - - if ($PurgeUserData) { - $folders += (Join-Path $env:USERPROFILE "OneDrive") - } - - foreach ($f in ($folders | Select-Object -Unique)) { - if (Test-Path $f) { - Try-Run { Remove-Item -LiteralPath $f -Recurse -Force -ErrorAction SilentlyContinue } "Failed removing folder ${f}:" - } - } - - Write-Log -message "8) Restart Explorer to apply UI changes" -severity 'INFO' -source 'BootStrap' -logName 'Application' - - Try-Run { - Get-Process explorer -ErrorAction SilentlyContinue | Stop-Process -Force -ErrorAction SilentlyContinue - Start-Process explorer.exe - } "Failed restarting Explorer:" - - Write-Log -message "OneDrive removal/disable steps completed. Recommend reboot to finalize." -severity 'INFO' -source 'BootStrap' -logName 'Application' - if (-not $PurgeUserData) { - Write-Log -message "NOTE: %UserProfile%\OneDrive was NOT deleted. Use -PurgeUserData to delete it." -severity 'WARN' -source 'BootStrap' -logName 'Application' - } -} - # IMPORTANT: use 'Continue' so normal AppX noise doesn't hard-fail Puppet $ErrorActionPreference = 'Continue' @@ -413,8 +123,6 @@ function Remove-PreinstalledAppxPackages { Start-Process $p -ArgumentList '/uninstall' -Wait -NoNewWindow } } - #Remove-OneDriveScheduledTasks - Ensure-OneDriveTaskCleanupHardeningTask } function Disable-AppXSvcCore { diff --git a/modules/win_scheduled_tasks/files/at_task_user_logon.ps1 b/modules/win_scheduled_tasks/files/at_task_user_logon.ps1 index 114302967..52aeb83be 100644 --- a/modules/win_scheduled_tasks/files/at_task_user_logon.ps1 +++ b/modules/win_scheduled_tasks/files/at_task_user_logon.ps1 @@ -83,6 +83,145 @@ while ($true) { } } +function Ensure-OneDriveTaskCleanupHardeningTask { + [CmdletBinding()] + param() + + $dir = 'C:\ProgramData\Hardening' + $file = Join-Path $dir 'Remove-OneDriveScheduledTasks.ps1' + + Write-Log -message "OneDriveTasksHardening :: begin" -severity 'DEBUG' + + try { + if (-not (Test-Path $dir)) { New-Item -ItemType Directory -Path $dir -Force | Out-Null } + + # Minimal self-contained script: uses schtasks.exe only and writes to Event Log using your source/logName. + $payload = @' +function Write-Log { + param ( + [string] $message, + [string] $severity = 'INFO', + [string] $source = 'MaintainSystem', + [string] $logName = 'Application' + ) + try { + if (!([Diagnostics.EventLog]::Exists($logName)) -or !([Diagnostics.EventLog]::SourceExists($source))) { + New-EventLog -LogName $logName -Source $source + } + switch ($severity) { + 'DEBUG' { $entryType = 'SuccessAudit'; $eventId = 2; break } + 'WARN' { $entryType = 'Warning'; $eventId = 3; break } + 'ERROR' { $entryType = 'Error'; $eventId = 4; break } + default { $entryType = 'Information'; $eventId = 1; break } + } + Write-EventLog -LogName $logName -Source $source -EntryType $entryType -Category 0 -EventID $eventId -Message $message + } catch { } +} + +try { + $rows = @(schtasks.exe /Query /FO CSV /V 2>$null | ConvertFrom-Csv) + $targets = $rows | Where-Object { + ($_.TaskName -match '(?i)onedrive') -or + (($_.'Task To Run') -and (($_.'Task To Run') -match '(?i)onedrive(\\.exe)?')) -or + (($_.Actions) -and ($_.Actions -match '(?i)onedrive(\\.exe)?')) -or + (($_.'Task Run') -and (($_.'Task Run') -match '(?i)onedrive(\\.exe)?')) -or + (($_.Actions) -and ($_.Actions -match '(?i)OneDriveSetup\.exe|\\OneDrive\.exe')) -or + (($_.'Task To Run') -and (($_.'Task To Run') -match '(?i)OneDriveSetup\.exe|\\OneDrive\.exe')) + } | Select-Object -ExpandProperty TaskName -Unique + + foreach ($tn in $targets) { + schtasks.exe /Delete /TN "$tn" /F 2>$null | Out-Null + } + + Write-Log -message ("OneDriveTasksHardening :: removed {0} task(s)" -f ($targets.Count)) -severity 'INFO' +} catch { + Write-Log -message ("OneDriveTasksHardening :: failed: {0}" -f $_.Exception.Message) -severity 'WARN' +} +'@ + + Set-Content -Path $file -Value $payload -Encoding UTF8 -Force + + $taskName = 'Remove-OneDriveScheduledTasks' + $taskPath = '\Hardening\' + + schtasks.exe /Delete /TN "$taskPath$taskName" /F 2>$null | Out-Null + + # Create: AtStartup + schtasks.exe /Create /F /TN "$taskPath$taskName" ` + /SC ONSTART /RU SYSTEM /RL HIGHEST ` + /TR "powershell.exe -NoLogo -NonInteractive -WindowStyle Hidden -ExecutionPolicy Bypass -File `"$file`"" ` + 2>$null | Out-Null + + # Add a second trigger: AtLogOn (any user) + schtasks.exe /Create /F /TN "$taskPath$taskName-Logon" ` + /SC ONLOGON /RU SYSTEM /RL HIGHEST ` + /TR "powershell.exe -NoLogo -NonInteractive -WindowStyle Hidden -ExecutionPolicy Bypass -File `"$file`"" ` + 2>$null | Out-Null + + Write-Log -message "OneDriveTasksHardening :: installed (ONSTART + ONLOGON)" -severity 'INFO' + } + catch { + Write-Log -message ("OneDriveTasksHardening :: failed: {0}" -f $_.Exception.Message) -severity 'WARN' + } + finally { + Write-Log -message "OneDriveTasksHardening :: end" -severity 'DEBUG' + } +} + +function Remove-OneDriveScheduledTasks { + [CmdletBinding()] + param() + + Write-Log -message "OneDriveTasks :: begin" -severity 'DEBUG' + + try { + $rows = @(schtasks.exe /Query /FO CSV /V 2>$null | ConvertFrom-Csv) + + if (-not $rows -or $rows.Count -eq 0) { + Write-Log -message "OneDriveTasks :: schtasks returned no rows" -severity 'WARN' + return + } + + # Columns vary a bit across Windows builds, so check multiple possible fields. + $targets = $rows | Where-Object { + ($_.TaskName -match '(?i)onedrive') -or + (($_.'Task To Run') -and (($_.'Task To Run') -match '(?i)onedrive(\\.exe)?')) -or + (($_.Actions) -and ($_.Actions -match '(?i)onedrive(\\.exe)?')) -or + (($_.'Task Run') -and (($_.'Task Run') -match '(?i)onedrive(\\.exe)?')) -or + # extra-tight match on known binaries + (($_.Actions) -and ($_.Actions -match '(?i)OneDriveSetup\.exe|\\OneDrive\.exe')) -or + (($_.'Task To Run') -and (($_.'Task To Run') -match '(?i)OneDriveSetup\.exe|\\OneDrive\.exe')) + } | Select-Object -ExpandProperty TaskName -Unique + + if (-not $targets -or $targets.Count -eq 0) { + Write-Log -message "OneDriveTasks :: No matching tasks found" -severity 'DEBUG' + return + } + + Write-Log -message ("OneDriveTasks :: Found {0} task(s) to remove" -f $targets.Count) -severity 'INFO' + + foreach ($tn in $targets) { + try { + schtasks.exe /Delete /TN "$tn" /F 2>$null | Out-Null + if ($LASTEXITCODE -eq 0) { + Write-Log -message ("OneDriveTasks :: Deleted {0}" -f $tn) -severity 'INFO' + } else { + Write-Log -message ("OneDriveTasks :: Failed delete {0} (exit {1})" -f $tn, $LASTEXITCODE) -severity 'WARN' + } + } catch { + Write-Log -message ("OneDriveTasks :: Exception deleting {0}: {1}" -f $tn, $_.Exception.Message) -severity 'WARN' + } + } + } + catch { + Write-Log -message ("OneDriveTasks :: failed: {0}" -f $_.Exception.Message) -severity 'WARN' + } + finally { + Write-Log -message "OneDriveTasks :: end" -severity 'DEBUG' + } +} + + ## Accessibilty keys in HKCU $Accessibility = Get-ItemProperty -Path "HKCU:\Control Panel\Accessibility" @@ -95,6 +234,8 @@ switch ($os_version) { "win_11_2009" { Write-Log -Message ('{0} :: {1} - {2:o}' -f $($MyInvocation.MyCommand.Name), "Setting scrollbars to always show in task-user-init.ps1", (Get-Date).ToUniversalTime()) -severity 'DEBUG' New-ItemProperty -Path 'HKCU:\Control Panel\Accessibility' -Name 'DynamicScrollbars' -Value 0 -Force + Remove-OneDriveScheduledTasks + Ensure-OneDriveTaskCleanupHardeningTask } "win_2022" { ## Disable Server Manager Dashboard diff --git a/modules/win_scheduled_tasks/files/maintainsystem-hw.ps1 b/modules/win_scheduled_tasks/files/maintainsystem-hw.ps1 index 1aef047af..6d280fb8a 100644 --- a/modules/win_scheduled_tasks/files/maintainsystem-hw.ps1 +++ b/modules/win_scheduled_tasks/files/maintainsystem-hw.ps1 @@ -43,144 +43,6 @@ function Write-Log { } } -function Remove-OneDriveScheduledTasks { - [CmdletBinding()] - param() - - Write-Log -message "OneDriveTasks :: begin" -severity 'DEBUG' - - try { - $rows = @(schtasks.exe /Query /FO CSV /V 2>$null | ConvertFrom-Csv) - - if (-not $rows -or $rows.Count -eq 0) { - Write-Log -message "OneDriveTasks :: schtasks returned no rows" -severity 'WARN' - return - } - - # Columns vary a bit across Windows builds, so check multiple possible fields. - $targets = $rows | Where-Object { - ($_.TaskName -match '(?i)onedrive') -or - (($_.'Task To Run') -and (($_.'Task To Run') -match '(?i)onedrive(\\.exe)?')) -or - (($_.Actions) -and ($_.Actions -match '(?i)onedrive(\\.exe)?')) -or - (($_.'Task Run') -and (($_.'Task Run') -match '(?i)onedrive(\\.exe)?')) -or - # extra-tight match on known binaries - (($_.Actions) -and ($_.Actions -match '(?i)OneDriveSetup\.exe|\\OneDrive\.exe')) -or - (($_.'Task To Run') -and (($_.'Task To Run') -match '(?i)OneDriveSetup\.exe|\\OneDrive\.exe')) - } | Select-Object -ExpandProperty TaskName -Unique - - if (-not $targets -or $targets.Count -eq 0) { - Write-Log -message "OneDriveTasks :: No matching tasks found" -severity 'DEBUG' - return - } - - Write-Log -message ("OneDriveTasks :: Found {0} task(s) to remove" -f $targets.Count) -severity 'INFO' - - foreach ($tn in $targets) { - try { - schtasks.exe /Delete /TN "$tn" /F 2>$null | Out-Null - if ($LASTEXITCODE -eq 0) { - Write-Log -message ("OneDriveTasks :: Deleted {0}" -f $tn) -severity 'INFO' - } else { - Write-Log -message ("OneDriveTasks :: Failed delete {0} (exit {1})" -f $tn, $LASTEXITCODE) -severity 'WARN' - } - } catch { - Write-Log -message ("OneDriveTasks :: Exception deleting {0}: {1}" -f $tn, $_.Exception.Message) -severity 'WARN' - } - } - } - catch { - Write-Log -message ("OneDriveTasks :: failed: {0}" -f $_.Exception.Message) -severity 'WARN' - } - finally { - Write-Log -message "OneDriveTasks :: end" -severity 'DEBUG' - } -} - -function Ensure-OneDriveTaskCleanupHardeningTask { - [CmdletBinding()] - param() - - $dir = 'C:\ProgramData\Hardening' - $file = Join-Path $dir 'Remove-OneDriveScheduledTasks.ps1' - - Write-Log -message "OneDriveTasksHardening :: begin" -severity 'DEBUG' - - try { - if (-not (Test-Path $dir)) { New-Item -ItemType Directory -Path $dir -Force | Out-Null } - - # Minimal self-contained script: uses schtasks.exe only and writes to Event Log using your source/logName. - $payload = @' -function Write-Log { - param ( - [string] $message, - [string] $severity = 'INFO', - [string] $source = 'MaintainSystem', - [string] $logName = 'Application' - ) - try { - if (!([Diagnostics.EventLog]::Exists($logName)) -or !([Diagnostics.EventLog]::SourceExists($source))) { - New-EventLog -LogName $logName -Source $source - } - switch ($severity) { - 'DEBUG' { $entryType = 'SuccessAudit'; $eventId = 2; break } - 'WARN' { $entryType = 'Warning'; $eventId = 3; break } - 'ERROR' { $entryType = 'Error'; $eventId = 4; break } - default { $entryType = 'Information'; $eventId = 1; break } - } - Write-EventLog -LogName $logName -Source $source -EntryType $entryType -Category 0 -EventID $eventId -Message $message - } catch { } -} - -try { - $rows = @(schtasks.exe /Query /FO CSV /V 2>$null | ConvertFrom-Csv) - $targets = $rows | Where-Object { - ($_.TaskName -match '(?i)onedrive') -or - (($_.'Task To Run') -and (($_.'Task To Run') -match '(?i)onedrive(\\.exe)?')) -or - (($_.Actions) -and ($_.Actions -match '(?i)onedrive(\\.exe)?')) -or - (($_.'Task Run') -and (($_.'Task Run') -match '(?i)onedrive(\\.exe)?')) -or - (($_.Actions) -and ($_.Actions -match '(?i)OneDriveSetup\.exe|\\OneDrive\.exe')) -or - (($_.'Task To Run') -and (($_.'Task To Run') -match '(?i)OneDriveSetup\.exe|\\OneDrive\.exe')) - } | Select-Object -ExpandProperty TaskName -Unique - - foreach ($tn in $targets) { - schtasks.exe /Delete /TN "$tn" /F 2>$null | Out-Null - } - - Write-Log -message ("OneDriveTasksHardening :: removed {0} task(s)" -f ($targets.Count)) -severity 'INFO' -} catch { - Write-Log -message ("OneDriveTasksHardening :: failed: {0}" -f $_.Exception.Message) -severity 'WARN' -} -'@ - - Set-Content -Path $file -Value $payload -Encoding UTF8 -Force - - $taskName = 'Remove-OneDriveScheduledTasks' - $taskPath = '\Hardening\' - - schtasks.exe /Delete /TN "$taskPath$taskName" /F 2>$null | Out-Null - - # Create: AtStartup - schtasks.exe /Create /F /TN "$taskPath$taskName" ` - /SC ONSTART /RU SYSTEM /RL HIGHEST ` - /TR "powershell.exe -NoLogo -NonInteractive -WindowStyle Hidden -ExecutionPolicy Bypass -File `"$file`"" ` - 2>$null | Out-Null - - # Add a second trigger: AtLogOn (any user) - schtasks.exe /Create /F /TN "$taskPath$taskName-Logon" ` - /SC ONLOGON /RU SYSTEM /RL HIGHEST ` - /TR "powershell.exe -NoLogo -NonInteractive -WindowStyle Hidden -ExecutionPolicy Bypass -File `"$file`"" ` - 2>$null | Out-Null - - Write-Log -message "OneDriveTasksHardening :: installed (ONSTART + ONLOGON)" -severity 'INFO' - } - catch { - Write-Log -message ("OneDriveTasksHardening :: failed: {0}" -f $_.Exception.Message) -severity 'WARN' - } - finally { - Write-Log -message "OneDriveTasksHardening :: end" -severity 'DEBUG' - } -} - function Run-MaintainSystem { begin { Write-Log -message ('{0} :: begin - {1:o}' -f $($MyInvocation.MyCommand.Name), (Get-Date).ToUniversalTime()) -severity 'DEBUG' @@ -687,8 +549,6 @@ If ($bootstrap_stage -eq 'complete') { } } Disable-PerUserUwpServices - #Remove-OneDriveScheduledTasks - Ensure-OneDriveTaskCleanupHardeningTask ## Let's make sure the machine is online before checking the internet Test-ConnectionUntilOnline From 75bd500dc493a876704a951f66177dd6d34e20e0 Mon Sep 17 00:00:00 2001 From: Mark Cornmesser Date: Wed, 31 Dec 2025 14:10:41 -0800 Subject: [PATCH 060/105] testing --- .../files/appxpackages/2BAKuninstall.ps1 | 246 ++++++++++++++++++ .../files/appxpackages/uninstall.ps1 | 38 +-- 2 files changed, 265 insertions(+), 19 deletions(-) create mode 100644 modules/win_disable_services/files/appxpackages/2BAKuninstall.ps1 diff --git a/modules/win_disable_services/files/appxpackages/2BAKuninstall.ps1 b/modules/win_disable_services/files/appxpackages/2BAKuninstall.ps1 new file mode 100644 index 000000000..b5a3a405c --- /dev/null +++ b/modules/win_disable_services/files/appxpackages/2BAKuninstall.ps1 @@ -0,0 +1,246 @@ +function Write-Log { + param ( + [string] $message, + [string] $severity = 'INFO', + [string] $source = 'BootStrap', + [string] $logName = 'Application' + ) + + if (!([Diagnostics.EventLog]::Exists($logName)) -or + !([Diagnostics.EventLog]::SourceExists($source))) { + New-EventLog -LogName $logName -Source $source + } + + switch ($severity) { + 'DEBUG' { $entryType = 'SuccessAudit'; $eventId = 2; break } + 'WARN' { $entryType = 'Warning'; $eventId = 3; break } + 'ERROR' { $entryType = 'Error'; $eventId = 4; break } + default { $entryType = 'Information'; $eventId = 1; break } + } + + Write-EventLog -LogName $logName -Source $source ` + -EntryType $entryType -Category 0 -EventID $eventId ` + -Message $message + + if ([Environment]::UserInteractive) { + $fc = @{ + 'Information' = 'White' + 'Error' = 'Red' + 'Warning' = 'DarkYellow' + 'SuccessAudit'= 'DarkGray' + }[$entryType] + Write-Host $message -ForegroundColor $fc + } +} + +# IMPORTANT: use 'Continue' so normal AppX noise doesn't hard-fail Puppet +$ErrorActionPreference = 'Continue' + +$svcName = 'AppXSvc' +$svcKeyPath = 'HKLM:\SYSTEM\CurrentControlSet\Services\AppXSvc' + +function Remove-PreinstalledAppxPackages { + [CmdletBinding()] + param() + + $apps = @{ + "Bing Search" = @{ VDIState="Unchanged"; URL="https://apps.microsoft.com/detail/9nzbf4gt040c"; Description="Web Search from Microsoft Bing provides web results and answers in Windows Search" } + "Clipchamp.Clipchamp" = @{ VDIState="Unchanged"; URL="https://apps.microsoft.com/detail/9p1j8s7ccwwt?hl=en-us&gl=US"; Description="Create videos with a few clicks" } + "Microsoft.549981C3F5F10" = @{ VDIState="Unchanged"; URL="https://apps.microsoft.com/detail/cortana/9NFFX4SZZ23L?hl=en-us&gl=US"; Description="Cortana (could not update)" } + "Microsoft.BingNews" = @{ VDIState="Unchanged"; URL="https://www.microsoft.com/en-us/p/microsoft-news/9wzdncrfhvfw"; Description="Microsoft News app" } + "Microsoft.BingWeather" = @{ VDIState="Unchanged"; URL="https://www.microsoft.com/en-us/p/msn-weather/9wzdncrfj3q2"; Description="MSN Weather app" } + "Microsoft.DesktopAppInstaller" = @{ VDIState="Unchanged"; URL="https://apps.microsoft.com/detail/9NBLGGH4NNS1"; Description="Microsoft App Installer for Windows 10 makes sideloading Windows apps easy" } + "Microsoft.GetHelp" = @{ VDIState="Unchanged"; URL="https://docs.microsoft.com/en-us/windows-hardware/customize/desktop/customize-get-help-app"; Description="App that facilitates free support for Microsoft products" } + "Microsoft.Getstarted" = @{ VDIState="Unchanged"; URL="https://www.microsoft.com/en-us/p/microsoft-tips/9wzdncrdtbjj"; Description="Windows 10 tips app" } + "Microsoft.MicrosoftOfficeHub" = @{ VDIState="Unchanged"; URL="https://www.microsoft.com/en-us/p/office/9wzdncrd29v9"; Description="Office UWP app suite" } + "Microsoft.Office.OneNote" = @{ VDIState="Unchanged"; URL="https://www.microsoft.com/en-us/p/onenote-for-windows-10/9wzdncrfhvjl"; Description="Office UWP OneNote app" } + "Microsoft.MicrosoftSolitaireCollection" = @{ VDIState="Unchanged"; URL="https://www.microsoft.com/en-us/p/microsoft-solitaire-collection/9wzdncrfhwd2"; Description="Solitaire suite of games" } + "Microsoft.MicrosoftStickyNotes" = @{ VDIState="Unchanged"; URL="https://www.microsoft.com/en-us/p/microsoft-sticky-notes/9nblggh4qghw"; Description="Note-taking app" } + "Microsoft.OutlookForWindows" = @{ VDIState="Unchanged"; URL="https://apps.microsoft.com/detail/9NRX63209R7B?hl=en-us&gl=US"; Description="New Outlook app" } + "Microsoft.MSPaint" = @{ VDIState="Unchanged"; URL="https://apps.microsoft.com/store/detail/paint-3d/9NBLGGH5FV99"; Description="Paint 3D app" } + "Microsoft.Paint" = @{ VDIState="Unchanged"; URL="https://apps.microsoft.com/detail/9PCFS5B6T72H"; Description="Classic Paint app" } + "Microsoft.People" = @{ VDIState="Unchanged"; URL="https://www.microsoft.com/en-us/p/microsoft-people/9nblggh10pg8"; Description="Contact management app" } + "Microsoft.PowerAutomateDesktop" = @{ VDIState="Unchanged"; URL="https://flow.microsoft.com/en-us/desktop/"; Description="Power Automate Desktop" } + "Microsoft.ScreenSketch" = @{ VDIState="Unchanged"; URL="https://www.microsoft.com/en-us/p/snip-sketch/9mz95kl8mr0l"; Description="Snip and Sketch app" } + "Microsoft.SkypeApp" = @{ VDIState="Unchanged"; URL="https://www.microsoft.com/en-us/p/skype/9wzdncrfj364"; Description="Skype app" } + "Microsoft.StorePurchaseApp" = @{ VDIState="Unchanged"; URL=""; Description="Store purchase app helper" } + "Microsoft.Todos" = @{ VDIState="Unchanged"; URL="https://www.microsoft.com/en-us/p/microsoft-to-do-lists-tasks-reminders/9nblggh5r558"; Description="Microsoft To Do" } + "Microsoft.WinDbg.Fast" = @{ VDIState="Unchanged"; URL="https://apps.microsoft.com/detail/9PGJGD53TN86?hl=en-us&gl=US"; Description="WinDbg" } + "Microsoft.Windows.DevHome" = @{ VDIState="Unchanged"; URL="https://learn.microsoft.com/en-us/windows/dev-home/"; Description="Dev Home dashboard" } + "Microsoft.Windows.Photos" = @{ VDIState="Unchanged"; URL="https://www.microsoft.com/en-us/p/microsoft-photos/9wzdncrfjbh4"; Description="Photos app" } + "Microsoft.WindowsAlarms" = @{ VDIState="Unchanged"; URL="https://www.microsoft.com/en-us/p/windows-alarms-clock/9wzdncrfj3pr"; Description="Alarms & Clock" } + "Microsoft.WindowsCalculator" = @{ VDIState="Unchanged"; URL="https://www.microsoft.com/en-us/p/windows-calculator/9wzdncrfhvn5"; Description="Calculator" } + "Microsoft.WindowsCamera" = @{ VDIState="Unchanged"; URL="https://www.microsoft.com/en-us/p/windows-camera/9wzdncrfjbbg"; Description="Camera" } + "microsoft.windowscommunicationsapps" = @{ VDIState="Unchanged"; URL="https://www.microsoft.com/en-us/p/mail-and-calendar/9wzdncrfhvqm"; Description="Mail & Calendar" } + "Microsoft.WindowsFeedbackHub" = @{ VDIState="Unchanged"; URL="https://www.microsoft.com/en-us/p/feedback-hub/9nblggh4r32n"; Description="Feedback Hub" } + "Microsoft.WindowsMaps" = @{ VDIState="Unchanged"; URL="https://www.microsoft.com/en-us/p/windows-maps/9wzdncrdtbvb"; Description="Maps" } + "Microsoft.WindowsNotepad" = @{ VDIState="Unchanged"; URL="https://www.microsoft.com/en-us/p/windows-notepad/9msmlrh6lzf3"; Description="Notepad (Store)" } + "Microsoft.WindowsStore" = @{ VDIState="Unchanged"; URL="https://blogs.windows.com/windowsexperience/2021/06/24/building-a-new-open-microsoft-store-on-windows-11/"; Description="Microsoft Store" } + "Microsoft.WindowsSoundRecorder" = @{ VDIState="Unchanged"; URL="https://www.microsoft.com/en-us/p/windows-voice-recorder/9wzdncrfhwkn"; Description="Voice Recorder" } + "Microsoft.WindowsTerminal" = @{ VDIState="Unchanged"; URL="https://www.microsoft.com/en-us/p/windows-terminal/9n0dx20hk701"; Description="Windows Terminal" } + "Microsoft.Winget.Platform.Source"= @{ VDIState="Unchanged"; URL="https://learn.microsoft.com/en-us/windows/package-manager/winget/"; Description="Winget source" } + "Microsoft.Xbox.TCUI" = @{ VDIState="Unchanged"; URL="https://docs.microsoft.com/en-us/gaming/xbox-live/features/general/tcui/live-tcui-overview"; Description="Xbox TCUI" } + "Microsoft.XboxIdentityProvider" = @{ VDIState="Unchanged"; URL="https://www.microsoft.com/en-us/p/xbox-identity-provider/9wzdncrd1hkw"; Description="Xbox Identity Provider" } + "Microsoft.XboxSpeechToTextOverlay" = @{ VDIState="Unchanged"; URL="https://support.xbox.com/help/account-profile/accessibility/use-game-chat-transcription"; Description="Xbox chat transcription" } + "Microsoft.YourPhone" = @{ VDIState="Unchanged"; URL="https://www.microsoft.com/en-us/p/Your-phone/9nmpj99vjbwv"; Description="Phone Link" } + "Microsoft.ZuneMusic" = @{ VDIState="Unchanged"; URL="https://www.microsoft.com/en-us/p/groove-music/9wzdncrfj3pt"; Description="Groove Music" } + "Microsoft.ZuneVideo" = @{ VDIState="Unchanged"; URL="https://www.microsoft.com/en-us/p/movies-tv/9wzdncrfj3p2"; Description="Movies & TV" } + "MicrosoftCorporationII.QuickAssist" = @{ VDIState="Unchanged"; URL="https://apps.microsoft.com/detail/9P7BP5VNWKX5?hl=en-us&gl=US"; Description="Quick Assist" } + "MicrosoftWindows.Client.WebExperience" = @{ VDIState="Unchanged"; URL=""; Description="Windows 11 Web Experience" } + "Microsoft.XboxApp" = @{ VDIState="Unchanged"; URL="https://www.microsoft.com/store/apps/9wzdncrfjbd8"; Description="Xbox Console Companion" } + "Microsoft.MixedReality.Portal" = @{ VDIState="Unchanged"; URL="https://www.microsoft.com/en-us/p/mixed-reality-portal/9ng1h8b3zc7m"; Description="Mixed Reality Portal" } + "Microsoft.Microsoft3DViewer" = @{ VDIState="Unchanged"; URL="https://www.microsoft.com/en-us/p/3d-viewer/9nblggh42ths"; Description="3D Viewer" } + "MicrosoftTeams" = @{ VDIState="Unchanged"; URL="https://apps.microsoft.com/detail/xp8bt8dw290mpq"; Description="Microsoft Teams" } + "MSTeams" = @{ VDIState="Unchanged"; URL="https://apps.microsoft.com/detail/xp8bt8dw290mpq"; Description="Microsoft Teams (alt id)" } + "Microsoft.OneDriveSync" = @{ VDIState="Unchanged"; URL="https://docs.microsoft.com/en-us/onedrive/one-drive-sync"; Description="OneDrive sync app" } + "Microsoft.Wallet" = @{ VDIState="Unchanged"; URL="https://www.microsoft.com/en-us/payments"; Description="Microsoft Pay" } + } + + foreach ($Key in $apps.Keys) { + $null = $apps[$Key] # keep, in case you add logging later + + Get-AppxProvisionedPackage -Online | + Where-Object { $_.PackageName -like ("*{0}*" -f $Key) } | + Remove-AppxProvisionedPackage -Online -ErrorAction SilentlyContinue | + Out-Null + + Get-AppxPackage -AllUsers -Name ("*{0}*" -f $Key) | + Remove-AppxPackage -AllUsers -ErrorAction SilentlyContinue | + Out-Null + + Get-AppxPackage -Name ("*{0}*" -f $Key) | + Remove-AppxPackage -ErrorAction SilentlyContinue | + Out-Null + } + + $paths = @( + "$env:SystemRoot\System32\OneDriveSetup.exe", + "$env:SystemRoot\SysWOW64\OneDriveSetup.exe" + ) + + foreach ($p in $paths) { + if (Test-Path $p) { + Start-Process $p -ArgumentList '/uninstall' -Wait -NoNewWindow + } + } +} + +function Disable-AppXSvcCore { + [CmdletBinding()] + param() + + $svc = Get-Service -Name $svcName -ErrorAction SilentlyContinue + if ($null -ne $svc) { + if ($svc.Status -ne 'Stopped') { + Stop-Service -Name $svcName -Force -ErrorAction SilentlyContinue + } + Set-Service -Name $svcName -StartupType Disabled -ErrorAction SilentlyContinue + } + + if (Test-Path $svcKeyPath) { + New-ItemProperty -Path $svcKeyPath -Name Start -Value 4 -PropertyType DWord -Force | Out-Null + } + + # Best-effort: give it a moment to stop (can be sticky during provisioning) + for ($i=0; $i -lt 10; $i++) { + $s = Get-Service -Name $svcName -ErrorAction SilentlyContinue + if ($null -eq $s -or $s.Status -eq 'Stopped') { break } + Start-Sleep -Seconds 1 + } +} + +function Ensure-AppXSvcHardeningTask { + [CmdletBinding()] + param() + + $hardeningDir = 'C:\ProgramData\AppXLock' + $hardeningFile = Join-Path $hardeningDir 'Disable-AppXSvc.ps1' + + if (-not (Test-Path $hardeningDir)) { + New-Item -ItemType Directory -Path $hardeningDir -Force | Out-Null + } + + $hardeningScript = @' +param() + +$ErrorActionPreference = "SilentlyContinue" + +$svcName = "AppXSvc" +$svcKeyPath = "HKLM:\\SYSTEM\\CurrentControlSet\\Services\\AppXSvc" + +try { + $svc = Get-Service -Name $svcName -ErrorAction SilentlyContinue + if ($null -ne $svc) { + if ($svc.Status -ne "Stopped") { + Stop-Service -Name $svcName -Force -ErrorAction SilentlyContinue + } + Set-Service -Name $svcName -StartupType Disabled -ErrorAction SilentlyContinue + } + + if (Test-Path $svcKeyPath) { + New-ItemProperty -Path $svcKeyPath -Name Start -Value 4 -PropertyType DWord -Force | Out-Null + } +} catch { + # best-effort only +} +'@ + + Set-Content -Path $hardeningFile -Value $hardeningScript -Encoding UTF8 -Force + + $action = New-ScheduledTaskAction -Execute 'powershell.exe' ` + -Argument "-NoLogo -NonInteractive -WindowStyle Hidden -ExecutionPolicy Bypass -File `"$hardeningFile`"" + $trigger = New-ScheduledTaskTrigger -AtStartup + + $taskName = 'Hard-Disable-AppXSvc' + $taskPath = '\Hardening\' + + Unregister-ScheduledTask -TaskName $taskName -TaskPath $taskPath -Confirm:$false -ErrorAction SilentlyContinue + + Register-ScheduledTask -TaskName $taskName ` + -TaskPath $taskPath ` + -Action $action ` + -Trigger $trigger ` + -RunLevel Highest ` + -User 'SYSTEM' ` + -Force | Out-Null +} + +function Test-AppXSvcDisabled { + [CmdletBinding()] + param() + + $svc = Get-Service -Name $svcName -ErrorAction SilentlyContinue + if ($null -eq $svc) { return $true } + + # Success condition: Disabled. It may still be Running during early provisioning. + if ($svc.StartType.ToString() -eq 'Disabled') { + if ($svc.Status -ne 'Stopped') { + Write-Log -message ("uninstall_appx_packages :: AppXSvc is Disabled but currently {0}. Will be enforced at next boot." -f $svc.Status) -severity 'WARN' + } + return $true + } + + return $false +} + +Write-Log -message 'uninstall_appx_packages :: begin' -severity 'DEBUG' + +Write-Log -message 'uninstall_appx_packages :: Remove-PreinstalledAppxPackages' -severity 'DEBUG' +Remove-PreinstalledAppxPackages + +Write-Log -message 'uninstall_appx_packages :: Disable-AppXSvcCore' -severity 'DEBUG' +Disable-AppXSvcCore + +Write-Log -message 'uninstall_appx_packages :: Ensure-AppXSvcHardeningTask' -severity 'DEBUG' +Ensure-AppXSvcHardeningTask + +if (-not (Test-AppXSvcDisabled)) { + $svc = Get-Service -Name $svcName -ErrorAction SilentlyContinue + $status = if ($svc) { $svc.Status } else { 'Missing' } + $startType = if ($svc) { $svc.StartType } else { 'Missing' } + + Write-Log -message ("uninstall_appx_packages :: AppXSvc is NOT disabled. Status: {0}, StartType: {1}" -f $status, $startType) -severity 'ERROR' + throw "AppXSvc is NOT disabled. Status: $status, StartType: $startType" +} + +Write-Log -message 'uninstall_appx_packages :: complete (AppXSvc disabled)' -severity 'DEBUG' diff --git a/modules/win_disable_services/files/appxpackages/uninstall.ps1 b/modules/win_disable_services/files/appxpackages/uninstall.ps1 index b5a3a405c..7368349c5 100644 --- a/modules/win_disable_services/files/appxpackages/uninstall.ps1 +++ b/modules/win_disable_services/files/appxpackages/uninstall.ps1 @@ -1,3 +1,9 @@ +# Lab-only Windows 11 24H2 hardening: +# - Remove a predefined set of AppX packages +# - Disable AppXSvc (service + registry Start=4) +# - Install startup scheduled task (SYSTEM) to re-enforce disable every boot +# - Throw if AppXSvc is not disabled (Puppet will see non-zero) + function Write-Log { param ( [string] $message, @@ -97,7 +103,7 @@ function Remove-PreinstalledAppxPackages { } foreach ($Key in $apps.Keys) { - $null = $apps[$Key] # keep, in case you add logging later + $Item = $apps[$Key] Get-AppxProvisionedPackage -Online | Where-Object { $_.PackageName -like ("*{0}*" -f $Key) } | @@ -112,15 +118,14 @@ function Remove-PreinstalledAppxPackages { Remove-AppxPackage -ErrorAction SilentlyContinue | Out-Null } - $paths = @( "$env:SystemRoot\System32\OneDriveSetup.exe", "$env:SystemRoot\SysWOW64\OneDriveSetup.exe" - ) + ) - foreach ($p in $paths) { - if (Test-Path $p) { - Start-Process $p -ArgumentList '/uninstall' -Wait -NoNewWindow + foreach ($p in $paths) { + if (Test-Path $p) { + Start-Process $p -ArgumentList '/uninstall' -Wait -NoNewWindow } } } @@ -140,13 +145,6 @@ function Disable-AppXSvcCore { if (Test-Path $svcKeyPath) { New-ItemProperty -Path $svcKeyPath -Name Start -Value 4 -PropertyType DWord -Force | Out-Null } - - # Best-effort: give it a moment to stop (can be sticky during provisioning) - for ($i=0; $i -lt 10; $i++) { - $s = Get-Service -Name $svcName -ErrorAction SilentlyContinue - if ($null -eq $s -or $s.Status -eq 'Stopped') { break } - Start-Sleep -Seconds 1 - } } function Ensure-AppXSvcHardeningTask { @@ -210,19 +208,21 @@ function Test-AppXSvcDisabled { param() $svc = Get-Service -Name $svcName -ErrorAction SilentlyContinue - if ($null -eq $svc) { return $true } - # Success condition: Disabled. It may still be Running during early provisioning. - if ($svc.StartType.ToString() -eq 'Disabled') { - if ($svc.Status -ne 'Stopped') { - Write-Log -message ("uninstall_appx_packages :: AppXSvc is Disabled but currently {0}. Will be enforced at next boot." -f $svc.Status) -severity 'WARN' - } + if ($null -eq $svc) { + return $true + } + + $startType = $svc.StartType.ToString() + if ($svc.Status -eq 'Stopped' -and $startType -eq 'Disabled') { return $true } return $false } +# --- Main flow --------------------------------------------------------------- + Write-Log -message 'uninstall_appx_packages :: begin' -severity 'DEBUG' Write-Log -message 'uninstall_appx_packages :: Remove-PreinstalledAppxPackages' -severity 'DEBUG' From d323b5bb788d0206d86ca602f45111f01d7dfefe Mon Sep 17 00:00:00 2001 From: Mark Cornmesser Date: Wed, 31 Dec 2025 15:09:31 -0800 Subject: [PATCH 061/105] testing --- .../files/appxpackages/uninstall.ps1 | 10 ---------- 1 file changed, 10 deletions(-) diff --git a/modules/win_disable_services/files/appxpackages/uninstall.ps1 b/modules/win_disable_services/files/appxpackages/uninstall.ps1 index 7368349c5..0bd68b3cd 100644 --- a/modules/win_disable_services/files/appxpackages/uninstall.ps1 +++ b/modules/win_disable_services/files/appxpackages/uninstall.ps1 @@ -118,16 +118,6 @@ function Remove-PreinstalledAppxPackages { Remove-AppxPackage -ErrorAction SilentlyContinue | Out-Null } - $paths = @( - "$env:SystemRoot\System32\OneDriveSetup.exe", - "$env:SystemRoot\SysWOW64\OneDriveSetup.exe" - ) - - foreach ($p in $paths) { - if (Test-Path $p) { - Start-Process $p -ArgumentList '/uninstall' -Wait -NoNewWindow - } - } } function Disable-AppXSvcCore { From 3c993c032a54ce4f64056be203351a9122bc3aa2 Mon Sep 17 00:00:00 2001 From: Mark Cornmesser Date: Fri, 2 Jan 2026 09:01:40 -0800 Subject: [PATCH 062/105] testing --- .../files/at_task_user_logon.ps1 | 141 --------------- .../files/onedrive_task_deletion.ps1 | 167 ++++++++++++++++++ .../manifests/onedrive_task_deletion.pp | 28 +++ 3 files changed, 195 insertions(+), 141 deletions(-) create mode 100644 modules/win_scheduled_tasks/files/onedrive_task_deletion.ps1 create mode 100644 modules/win_scheduled_tasks/manifests/onedrive_task_deletion.pp diff --git a/modules/win_scheduled_tasks/files/at_task_user_logon.ps1 b/modules/win_scheduled_tasks/files/at_task_user_logon.ps1 index 52aeb83be..114302967 100644 --- a/modules/win_scheduled_tasks/files/at_task_user_logon.ps1 +++ b/modules/win_scheduled_tasks/files/at_task_user_logon.ps1 @@ -83,145 +83,6 @@ while ($true) { } } -function Ensure-OneDriveTaskCleanupHardeningTask { - [CmdletBinding()] - param() - - $dir = 'C:\ProgramData\Hardening' - $file = Join-Path $dir 'Remove-OneDriveScheduledTasks.ps1' - - Write-Log -message "OneDriveTasksHardening :: begin" -severity 'DEBUG' - - try { - if (-not (Test-Path $dir)) { New-Item -ItemType Directory -Path $dir -Force | Out-Null } - - # Minimal self-contained script: uses schtasks.exe only and writes to Event Log using your source/logName. - $payload = @' -function Write-Log { - param ( - [string] $message, - [string] $severity = 'INFO', - [string] $source = 'MaintainSystem', - [string] $logName = 'Application' - ) - try { - if (!([Diagnostics.EventLog]::Exists($logName)) -or !([Diagnostics.EventLog]::SourceExists($source))) { - New-EventLog -LogName $logName -Source $source - } - switch ($severity) { - 'DEBUG' { $entryType = 'SuccessAudit'; $eventId = 2; break } - 'WARN' { $entryType = 'Warning'; $eventId = 3; break } - 'ERROR' { $entryType = 'Error'; $eventId = 4; break } - default { $entryType = 'Information'; $eventId = 1; break } - } - Write-EventLog -LogName $logName -Source $source -EntryType $entryType -Category 0 -EventID $eventId -Message $message - } catch { } -} - -try { - $rows = @(schtasks.exe /Query /FO CSV /V 2>$null | ConvertFrom-Csv) - $targets = $rows | Where-Object { - ($_.TaskName -match '(?i)onedrive') -or - (($_.'Task To Run') -and (($_.'Task To Run') -match '(?i)onedrive(\\.exe)?')) -or - (($_.Actions) -and ($_.Actions -match '(?i)onedrive(\\.exe)?')) -or - (($_.'Task Run') -and (($_.'Task Run') -match '(?i)onedrive(\\.exe)?')) -or - (($_.Actions) -and ($_.Actions -match '(?i)OneDriveSetup\.exe|\\OneDrive\.exe')) -or - (($_.'Task To Run') -and (($_.'Task To Run') -match '(?i)OneDriveSetup\.exe|\\OneDrive\.exe')) - } | Select-Object -ExpandProperty TaskName -Unique - - foreach ($tn in $targets) { - schtasks.exe /Delete /TN "$tn" /F 2>$null | Out-Null - } - - Write-Log -message ("OneDriveTasksHardening :: removed {0} task(s)" -f ($targets.Count)) -severity 'INFO' -} catch { - Write-Log -message ("OneDriveTasksHardening :: failed: {0}" -f $_.Exception.Message) -severity 'WARN' -} -'@ - - Set-Content -Path $file -Value $payload -Encoding UTF8 -Force - - $taskName = 'Remove-OneDriveScheduledTasks' - $taskPath = '\Hardening\' - - schtasks.exe /Delete /TN "$taskPath$taskName" /F 2>$null | Out-Null - - # Create: AtStartup - schtasks.exe /Create /F /TN "$taskPath$taskName" ` - /SC ONSTART /RU SYSTEM /RL HIGHEST ` - /TR "powershell.exe -NoLogo -NonInteractive -WindowStyle Hidden -ExecutionPolicy Bypass -File `"$file`"" ` - 2>$null | Out-Null - - # Add a second trigger: AtLogOn (any user) - schtasks.exe /Create /F /TN "$taskPath$taskName-Logon" ` - /SC ONLOGON /RU SYSTEM /RL HIGHEST ` - /TR "powershell.exe -NoLogo -NonInteractive -WindowStyle Hidden -ExecutionPolicy Bypass -File `"$file`"" ` - 2>$null | Out-Null - - Write-Log -message "OneDriveTasksHardening :: installed (ONSTART + ONLOGON)" -severity 'INFO' - } - catch { - Write-Log -message ("OneDriveTasksHardening :: failed: {0}" -f $_.Exception.Message) -severity 'WARN' - } - finally { - Write-Log -message "OneDriveTasksHardening :: end" -severity 'DEBUG' - } -} - -function Remove-OneDriveScheduledTasks { - [CmdletBinding()] - param() - - Write-Log -message "OneDriveTasks :: begin" -severity 'DEBUG' - - try { - $rows = @(schtasks.exe /Query /FO CSV /V 2>$null | ConvertFrom-Csv) - - if (-not $rows -or $rows.Count -eq 0) { - Write-Log -message "OneDriveTasks :: schtasks returned no rows" -severity 'WARN' - return - } - - # Columns vary a bit across Windows builds, so check multiple possible fields. - $targets = $rows | Where-Object { - ($_.TaskName -match '(?i)onedrive') -or - (($_.'Task To Run') -and (($_.'Task To Run') -match '(?i)onedrive(\\.exe)?')) -or - (($_.Actions) -and ($_.Actions -match '(?i)onedrive(\\.exe)?')) -or - (($_.'Task Run') -and (($_.'Task Run') -match '(?i)onedrive(\\.exe)?')) -or - # extra-tight match on known binaries - (($_.Actions) -and ($_.Actions -match '(?i)OneDriveSetup\.exe|\\OneDrive\.exe')) -or - (($_.'Task To Run') -and (($_.'Task To Run') -match '(?i)OneDriveSetup\.exe|\\OneDrive\.exe')) - } | Select-Object -ExpandProperty TaskName -Unique - - if (-not $targets -or $targets.Count -eq 0) { - Write-Log -message "OneDriveTasks :: No matching tasks found" -severity 'DEBUG' - return - } - - Write-Log -message ("OneDriveTasks :: Found {0} task(s) to remove" -f $targets.Count) -severity 'INFO' - - foreach ($tn in $targets) { - try { - schtasks.exe /Delete /TN "$tn" /F 2>$null | Out-Null - if ($LASTEXITCODE -eq 0) { - Write-Log -message ("OneDriveTasks :: Deleted {0}" -f $tn) -severity 'INFO' - } else { - Write-Log -message ("OneDriveTasks :: Failed delete {0} (exit {1})" -f $tn, $LASTEXITCODE) -severity 'WARN' - } - } catch { - Write-Log -message ("OneDriveTasks :: Exception deleting {0}: {1}" -f $tn, $_.Exception.Message) -severity 'WARN' - } - } - } - catch { - Write-Log -message ("OneDriveTasks :: failed: {0}" -f $_.Exception.Message) -severity 'WARN' - } - finally { - Write-Log -message "OneDriveTasks :: end" -severity 'DEBUG' - } -} - - ## Accessibilty keys in HKCU $Accessibility = Get-ItemProperty -Path "HKCU:\Control Panel\Accessibility" @@ -234,8 +95,6 @@ switch ($os_version) { "win_11_2009" { Write-Log -Message ('{0} :: {1} - {2:o}' -f $($MyInvocation.MyCommand.Name), "Setting scrollbars to always show in task-user-init.ps1", (Get-Date).ToUniversalTime()) -severity 'DEBUG' New-ItemProperty -Path 'HKCU:\Control Panel\Accessibility' -Name 'DynamicScrollbars' -Value 0 -Force - Remove-OneDriveScheduledTasks - Ensure-OneDriveTaskCleanupHardeningTask } "win_2022" { ## Disable Server Manager Dashboard diff --git a/modules/win_scheduled_tasks/files/onedrive_task_deletion.ps1 b/modules/win_scheduled_tasks/files/onedrive_task_deletion.ps1 new file mode 100644 index 000000000..2350f14e0 --- /dev/null +++ b/modules/win_scheduled_tasks/files/onedrive_task_deletion.ps1 @@ -0,0 +1,167 @@ +<# +This Source Code Form is subject to the terms of the Mozilla Public +License, v. 2.0. If a copy of the MPL was not distributed with this +file, You can obtain one at http://mozilla.org/MPL/2.0/. +#> + +function Write-Log { + param ( + [string] $message, + [string] $severity = 'INFO', + [string] $source = 'MaintainSystem', + [string] $logName = 'Application' + ) + if (!([Diagnostics.EventLog]::Exists($logName)) -or !([Diagnostics.EventLog]::SourceExists($source))) { + New-EventLog -LogName $logName -Source $source + } + switch ($severity) { + 'DEBUG' { + $entryType = 'SuccessAudit' + $eventId = 2 + break + } + 'WARN' { + $entryType = 'Warning' + $eventId = 3 + break + } + 'ERROR' { + $entryType = 'Error' + $eventId = 4 + break + } + default { + $entryType = 'Information' + $eventId = 1 + break + } + } + Write-EventLog -LogName $logName -Source $source -EntryType $entryType -Category 0 -EventID $eventId -Message $message + if ([Environment]::UserInteractive) { + $fc = @{ 'Information' = 'White'; 'Error' = 'Red'; 'Warning' = 'DarkYellow'; 'SuccessAudit' = 'DarkGray' }[$entryType] + Write-Host -object $message -ForegroundColor $fc + } +} + +function Remove-OneDriveScheduledTasks { + [CmdletBinding()] + param( + [int]$TimeoutSeconds = 180, + [int]$RetryIntervalSeconds = 10, + [int]$PerTaskDeleteTimeoutSeconds = 60, + [int]$PerTaskRetryIntervalSeconds = 3 + ) + + function Get-OneDriveTaskNames { + try { + $rows = @(schtasks.exe /Query /FO CSV /V 2>$null | ConvertFrom-Csv) + if (-not $rows -or $rows.Count -eq 0) { return @() } + + $matches = $rows | Where-Object { + ($_.TaskName -match '(?i)onedrive') -or + (($_.'Task To Run') -and (($_.'Task To Run') -match '(?i)onedrive(\\.exe)?')) -or + (($_.Actions) -and ($_.Actions -match '(?i)onedrive(\\.exe)?')) -or + (($_.'Task Run') -and (($_.'Task Run') -match '(?i)onedrive(\\.exe)?')) -or + (($_.Actions) -and ($_.Actions -match '(?i)OneDriveSetup\.exe|\\OneDrive\.exe')) -or + (($_.'Task To Run') -and (($_.'Task To Run') -match '(?i)OneDriveSetup\.exe|\\OneDrive\.exe')) + } + + return @($matches | Select-Object -ExpandProperty TaskName -Unique) + } + catch { + Write-Log -message ("OneDriveTasks :: enumerate failed: {0}" -f $_.Exception.Message) -severity 'WARN' + return @() + } + } + + function Test-TaskExists([string]$TaskName) { + try { + schtasks.exe /Query /TN "$TaskName" 1>$null 2>$null + return ($LASTEXITCODE -eq 0) + } catch { + return $true # assume it exists if we couldn't query + } + } + + function Remove-TaskWithRetries { + param( + [Parameter(Mandatory)][string]$TaskName + ) + + $deadline = (Get-Date).AddSeconds($PerTaskDeleteTimeoutSeconds) + $attempt = 0 + + while ((Get-Date) -lt $deadline) { + $attempt++ + + try { + schtasks.exe /Delete /TN "$TaskName" /F 2>$null | Out-Null + $exit = $LASTEXITCODE + + if ($exit -eq 0) { + # Some tasks "delete" but linger briefly; verify + if (-not (Test-TaskExists -TaskName $TaskName)) { + Write-Log -message ("OneDriveTasks :: deleted {0} (attempt {1})" -f $TaskName, $attempt) -severity 'INFO' + return $true + } + + Write-Log -message ("OneDriveTasks :: delete reported success but task still exists: {0} (attempt {1})" -f $TaskName, $attempt) -severity 'WARN' + } else { + Write-Log -message ("OneDriveTasks :: delete failed {0} (exit {1}, attempt {2})" -f $TaskName, $exit, $attempt) -severity 'WARN' + } + } + catch { + Write-Log -message ("OneDriveTasks :: exception deleting {0} (attempt {1}): {2}" -f $TaskName, $attempt, $_.Exception.Message) -severity 'WARN' + } + + Start-Sleep -Seconds $PerTaskRetryIntervalSeconds + } + + Write-Log -message ("OneDriveTasks :: timeout deleting {0} after {1}s" -f $TaskName, $PerTaskDeleteTimeoutSeconds) -severity 'ERROR' + return $false + } + + Write-Log -message ("OneDriveTasks :: begin (timeout={0}s, interval={1}s, perTaskTimeout={2}s)" -f $TimeoutSeconds, $RetryIntervalSeconds, $PerTaskDeleteTimeoutSeconds) -severity 'DEBUG' + + $deadline = (Get-Date).AddSeconds($TimeoutSeconds) + $pass = 0 + + while ((Get-Date) -lt $deadline) { + $pass++ + $targets = Get-OneDriveTaskNames + + if (-not $targets -or $targets.Count -eq 0) { + Write-Log -message ("OneDriveTasks :: none found (pass {0})" -f $pass) -severity 'INFO' + Write-Log -message "OneDriveTasks :: end (success)" -severity 'DEBUG' + return + } + + Write-Log -message ("OneDriveTasks :: pass {0}: found {1} task(s)" -f $pass, $targets.Count) -severity 'INFO' + + foreach ($tn in $targets) { + $null = Remove-TaskWithRetries -TaskName $tn + } + + # Re-check right away; if still present, sleep and retry until overall timeout + $stillThere = Get-OneDriveTaskNames + if (-not $stillThere -or $stillThere.Count -eq 0) { + Write-Log -message ("OneDriveTasks :: verification OK after pass {0}" -f $pass) -severity 'INFO' + Write-Log -message "OneDriveTasks :: end (success)" -severity 'DEBUG' + return + } + + $remaining = [math]::Max(0, [int]($deadline - (Get-Date)).TotalSeconds) + Write-Log -message ("OneDriveTasks :: still present after pass {0} (remaining {1}s). Sleeping {2}s..." -f $pass, $remaining, $RetryIntervalSeconds) -severity 'WARN' + Start-Sleep -Seconds $RetryIntervalSeconds + } + + $final = Get-OneDriveTaskNames + if ($final -and $final.Count -gt 0) { + $sample = ($final | Select-Object -First 10) -join '; ' + Write-Log -message ("OneDriveTasks :: timeout after {0}s. Remaining task(s): {1}" -f $TimeoutSeconds, $sample) -severity 'ERROR' + } else { + Write-Log -message "OneDriveTasks :: end (success at timeout boundary)" -severity 'INFO' + } +} + +Remove-OneDriveScheduledTasks diff --git a/modules/win_scheduled_tasks/manifests/onedrive_task_deletion.pp b/modules/win_scheduled_tasks/manifests/onedrive_task_deletion.pp new file mode 100644 index 000000000..9d7c4a178 --- /dev/null +++ b/modules/win_scheduled_tasks/manifests/onedrive_task_deletion.pp @@ -0,0 +1,28 @@ +# This Source Code Form is subject to the terms of the Mozilla Public +# License, v. 2.0. If a copy of the MPL was not distributed with this +# file, You can obtain one at http://mozilla.org/MPL/2.0/. + +class win_scheduled_tasks::onedrive_task_deletion { + $onedrive_task_deletion_ps = "${facts['custom_win_roninprogramdata']}\\onedrive_task_deletion.ps1" + + if $facts['os']['name'] == 'Windows' { + file { $onedrive_task_deletion_ps: + content => file('win_scheduled_tasks/onedrive_task_deletion.ps1'), + } + # Resource from puppetlabs-scheduled_task + scheduled_task { 'onedrive_task_deletion': + ensure => 'present', + command => "${facts['custom_win_system32']}\\WindowsPowerShell\\v1.0\\powershell.exe", + arguments => "-executionpolicy bypass -File ${onedrive_task_deletion_ps}", + enabled => true, + trigger => [{ + 'schedule' => 'boot', + 'minutes_interval' => '0', + 'minutes_duration' => '0' + }], + user => 'system', + } + } else { + fail("${module_name} does not support ${$facts['os']['name']}") + } +} From 04bacd883843d9d12bc60127af0a26a8e06b0d99 Mon Sep 17 00:00:00 2001 From: Mark Cornmesser Date: Fri, 2 Jan 2026 09:55:18 -0800 Subject: [PATCH 063/105] testing --- modules/roles_profiles/manifests/profiles/disable_services.pp | 1 + 1 file changed, 1 insertion(+) diff --git a/modules/roles_profiles/manifests/profiles/disable_services.pp b/modules/roles_profiles/manifests/profiles/disable_services.pp index 2d6d641b7..ff512eede 100644 --- a/modules/roles_profiles/manifests/profiles/disable_services.pp +++ b/modules/roles_profiles/manifests/profiles/disable_services.pp @@ -44,6 +44,7 @@ ## Bug 1913499 https://bugzilla.mozilla.org/show_bug.cgi?id=1913499 include win_disable_services::uninstall_appx_packages include win_disable_services::disable_optional_services + include win_scheduled_tasks::onedrive_task_deletion if ($facts['custom_win_location'] == 'azure') { include win_scheduled_tasks::kill_local_clipboard } From 411a67abca1502fc1fd02ef61e76f72b6289dda4 Mon Sep 17 00:00:00 2001 From: Mark Cornmesser Date: Fri, 2 Jan 2026 10:37:13 -0800 Subject: [PATCH 064/105] testing --- modules/win_scheduled_tasks/manifests/onedrive_task_deletion.pp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/modules/win_scheduled_tasks/manifests/onedrive_task_deletion.pp b/modules/win_scheduled_tasks/manifests/onedrive_task_deletion.pp index 9d7c4a178..49815ab48 100644 --- a/modules/win_scheduled_tasks/manifests/onedrive_task_deletion.pp +++ b/modules/win_scheduled_tasks/manifests/onedrive_task_deletion.pp @@ -10,7 +10,7 @@ content => file('win_scheduled_tasks/onedrive_task_deletion.ps1'), } # Resource from puppetlabs-scheduled_task - scheduled_task { 'onedrive_task_deletion': + scheduled_task { '1drive_task_deletion': ensure => 'present', command => "${facts['custom_win_system32']}\\WindowsPowerShell\\v1.0\\powershell.exe", arguments => "-executionpolicy bypass -File ${onedrive_task_deletion_ps}", From e3d960ee01e6597b9193631826dbe502e293b749 Mon Sep 17 00:00:00 2001 From: Mark Cornmesser Date: Fri, 2 Jan 2026 11:31:01 -0800 Subject: [PATCH 065/105] testing --- modules/win_scheduled_tasks/manifests/onedrive_task_deletion.pp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/modules/win_scheduled_tasks/manifests/onedrive_task_deletion.pp b/modules/win_scheduled_tasks/manifests/onedrive_task_deletion.pp index 49815ab48..71d9fd8b0 100644 --- a/modules/win_scheduled_tasks/manifests/onedrive_task_deletion.pp +++ b/modules/win_scheduled_tasks/manifests/onedrive_task_deletion.pp @@ -10,7 +10,7 @@ content => file('win_scheduled_tasks/onedrive_task_deletion.ps1'), } # Resource from puppetlabs-scheduled_task - scheduled_task { '1drive_task_deletion': + scheduled_task { 'one_drive_task_deletion': ensure => 'present', command => "${facts['custom_win_system32']}\\WindowsPowerShell\\v1.0\\powershell.exe", arguments => "-executionpolicy bypass -File ${onedrive_task_deletion_ps}", From 4b1932f3d8ff78352cfbdf38e486addce1a4c6d4 Mon Sep 17 00:00:00 2001 From: Mark Cornmesser Date: Fri, 2 Jan 2026 12:21:53 -0800 Subject: [PATCH 066/105] testing --- .../manifests/onedrive_task_deletion.pp | 22 +++++++++---------- 1 file changed, 10 insertions(+), 12 deletions(-) diff --git a/modules/win_scheduled_tasks/manifests/onedrive_task_deletion.pp b/modules/win_scheduled_tasks/manifests/onedrive_task_deletion.pp index 71d9fd8b0..c00e2998a 100644 --- a/modules/win_scheduled_tasks/manifests/onedrive_task_deletion.pp +++ b/modules/win_scheduled_tasks/manifests/onedrive_task_deletion.pp @@ -1,28 +1,26 @@ -# This Source Code Form is subject to the terms of the Mozilla Public -# License, v. 2.0. If a copy of the MPL was not distributed with this -# file, You can obtain one at http://mozilla.org/MPL/2.0/. - class win_scheduled_tasks::onedrive_task_deletion { $onedrive_task_deletion_ps = "${facts['custom_win_roninprogramdata']}\\onedrive_task_deletion.ps1" if $facts['os']['name'] == 'Windows' { + file { $onedrive_task_deletion_ps: + ensure => file, content => file('win_scheduled_tasks/onedrive_task_deletion.ps1'), } - # Resource from puppetlabs-scheduled_task + scheduled_task { 'one_drive_task_deletion': - ensure => 'present', + ensure => present, command => "${facts['custom_win_system32']}\\WindowsPowerShell\\v1.0\\powershell.exe", - arguments => "-executionpolicy bypass -File ${onedrive_task_deletion_ps}", + arguments => "-executionpolicy bypass -File \"${onedrive_task_deletion_ps}\"", enabled => true, trigger => [{ - 'schedule' => 'boot', - 'minutes_interval' => '0', - 'minutes_duration' => '0' + schedule => boot, }], - user => 'system', + user => 'SYSTEM', + require => File[$onedrive_task_deletion_ps], } + } else { - fail("${module_name} does not support ${$facts['os']['name']}") + fail("${module_name} does not support ${facts['os']['name']}") } } From ddd6c16ca98ac90cdcba0485bca6da2f5a365eae Mon Sep 17 00:00:00 2001 From: Mark Cornmesser Date: Fri, 2 Jan 2026 13:58:20 -0800 Subject: [PATCH 067/105] testing --- .../manifests/profiles/disable_services.pp | 1 - .../files/at_task_user_logon.ps1 | 121 ++++++++++++++++++ 2 files changed, 121 insertions(+), 1 deletion(-) diff --git a/modules/roles_profiles/manifests/profiles/disable_services.pp b/modules/roles_profiles/manifests/profiles/disable_services.pp index ff512eede..2d6d641b7 100644 --- a/modules/roles_profiles/manifests/profiles/disable_services.pp +++ b/modules/roles_profiles/manifests/profiles/disable_services.pp @@ -44,7 +44,6 @@ ## Bug 1913499 https://bugzilla.mozilla.org/show_bug.cgi?id=1913499 include win_disable_services::uninstall_appx_packages include win_disable_services::disable_optional_services - include win_scheduled_tasks::onedrive_task_deletion if ($facts['custom_win_location'] == 'azure') { include win_scheduled_tasks::kill_local_clipboard } diff --git a/modules/win_scheduled_tasks/files/at_task_user_logon.ps1 b/modules/win_scheduled_tasks/files/at_task_user_logon.ps1 index 114302967..4a0e60761 100644 --- a/modules/win_scheduled_tasks/files/at_task_user_logon.ps1 +++ b/modules/win_scheduled_tasks/files/at_task_user_logon.ps1 @@ -46,6 +46,126 @@ function Write-Log { } } +function Remove-OneDriveScheduledTasks { + [CmdletBinding()] + param( + [int]$TimeoutSeconds = 180, + [int]$RetryIntervalSeconds = 10, + [int]$PerTaskDeleteTimeoutSeconds = 60, + [int]$PerTaskRetryIntervalSeconds = 3 + ) + + function Get-OneDriveTaskNames { + try { + $rows = @(schtasks.exe /Query /FO CSV /V 2>$null | ConvertFrom-Csv) + if (-not $rows -or $rows.Count -eq 0) { return @() } + + $matches = $rows | Where-Object { + ($_.TaskName -match '(?i)onedrive') -or + (($_.'Task To Run') -and (($_.'Task To Run') -match '(?i)onedrive(\\.exe)?')) -or + (($_.Actions) -and ($_.Actions -match '(?i)onedrive(\\.exe)?')) -or + (($_.'Task Run') -and (($_.'Task Run') -match '(?i)onedrive(\\.exe)?')) -or + (($_.Actions) -and ($_.Actions -match '(?i)OneDriveSetup\.exe|\\OneDrive\.exe')) -or + (($_.'Task To Run') -and (($_.'Task To Run') -match '(?i)OneDriveSetup\.exe|\\OneDrive\.exe')) + } + + return @($matches | Select-Object -ExpandProperty TaskName -Unique) + } + catch { + Write-Log -message ("OneDriveTasks :: enumerate failed: {0}" -f $_.Exception.Message) -severity 'WARN' + return @() + } + } + + function Test-TaskExists([string]$TaskName) { + try { + schtasks.exe /Query /TN "$TaskName" 1>$null 2>$null + return ($LASTEXITCODE -eq 0) + } catch { + return $true # assume it exists if we couldn't query + } + } + + function Remove-TaskWithRetries { + param( + [Parameter(Mandatory)][string]$TaskName + ) + + $deadline = (Get-Date).AddSeconds($PerTaskDeleteTimeoutSeconds) + $attempt = 0 + + while ((Get-Date) -lt $deadline) { + $attempt++ + + try { + schtasks.exe /Delete /TN "$TaskName" /F 2>$null | Out-Null + $exit = $LASTEXITCODE + + if ($exit -eq 0) { + # Some tasks "delete" but linger briefly; verify + if (-not (Test-TaskExists -TaskName $TaskName)) { + Write-Log -message ("OneDriveTasks :: deleted {0} (attempt {1})" -f $TaskName, $attempt) -severity 'INFO' + return $true + } + + Write-Log -message ("OneDriveTasks :: delete reported success but task still exists: {0} (attempt {1})" -f $TaskName, $attempt) -severity 'WARN' + } else { + Write-Log -message ("OneDriveTasks :: delete failed {0} (exit {1}, attempt {2})" -f $TaskName, $exit, $attempt) -severity 'WARN' + } + } + catch { + Write-Log -message ("OneDriveTasks :: exception deleting {0} (attempt {1}): {2}" -f $TaskName, $attempt, $_.Exception.Message) -severity 'WARN' + } + + Start-Sleep -Seconds $PerTaskRetryIntervalSeconds + } + + Write-Log -message ("OneDriveTasks :: timeout deleting {0} after {1}s" -f $TaskName, $PerTaskDeleteTimeoutSeconds) -severity 'ERROR' + return $false + } + + Write-Log -message ("OneDriveTasks :: begin (timeout={0}s, interval={1}s, perTaskTimeout={2}s)" -f $TimeoutSeconds, $RetryIntervalSeconds, $PerTaskDeleteTimeoutSeconds) -severity 'DEBUG' + + $deadline = (Get-Date).AddSeconds($TimeoutSeconds) + $pass = 0 + + while ((Get-Date) -lt $deadline) { + $pass++ + $targets = Get-OneDriveTaskNames + + if (-not $targets -or $targets.Count -eq 0) { + Write-Log -message ("OneDriveTasks :: none found (pass {0})" -f $pass) -severity 'INFO' + Write-Log -message "OneDriveTasks :: end (success)" -severity 'DEBUG' + return + } + + Write-Log -message ("OneDriveTasks :: pass {0}: found {1} task(s)" -f $pass, $targets.Count) -severity 'INFO' + + foreach ($tn in $targets) { + $null = Remove-TaskWithRetries -TaskName $tn + } + + # Re-check right away; if still present, sleep and retry until overall timeout + $stillThere = Get-OneDriveTaskNames + if (-not $stillThere -or $stillThere.Count -eq 0) { + Write-Log -message ("OneDriveTasks :: verification OK after pass {0}" -f $pass) -severity 'INFO' + Write-Log -message "OneDriveTasks :: end (success)" -severity 'DEBUG' + return + } + + $remaining = [math]::Max(0, [int]($deadline - (Get-Date)).TotalSeconds) + Write-Log -message ("OneDriveTasks :: still present after pass {0} (remaining {1}s). Sleeping {2}s..." -f $pass, $remaining, $RetryIntervalSeconds) -severity 'WARN' + Start-Sleep -Seconds $RetryIntervalSeconds + } + + $final = Get-OneDriveTaskNames + if ($final -and $final.Count -gt 0) { + $sample = ($final | Select-Object -First 10) -join '; ' + Write-Log -message ("OneDriveTasks :: timeout after {0}s. Remaining task(s): {1}" -f $TimeoutSeconds, $sample) -severity 'ERROR' + } else { + Write-Log -message "OneDriveTasks :: end (success at timeout boundary)" -severity 'INFO' + } + # Windows release ID. # From time to time we need to have the different releases of the same OS version $release_key = (Get-ItemProperty -Path 'HKLM:\SOFTWARE\Microsoft\Windows NT\CurrentVersion') @@ -95,6 +215,7 @@ switch ($os_version) { "win_11_2009" { Write-Log -Message ('{0} :: {1} - {2:o}' -f $($MyInvocation.MyCommand.Name), "Setting scrollbars to always show in task-user-init.ps1", (Get-Date).ToUniversalTime()) -severity 'DEBUG' New-ItemProperty -Path 'HKCU:\Control Panel\Accessibility' -Name 'DynamicScrollbars' -Value 0 -Force + Remove-OneDriveScheduledTasks } "win_2022" { ## Disable Server Manager Dashboard From 251baeb18a2b53d4ce41f2800eb727a7313f8112 Mon Sep 17 00:00:00 2001 From: Mark Cornmesser Date: Fri, 2 Jan 2026 15:17:28 -0800 Subject: [PATCH 068/105] testing --- modules/win_scheduled_tasks/files/at_task_user_logon.ps1 | 1 + 1 file changed, 1 insertion(+) diff --git a/modules/win_scheduled_tasks/files/at_task_user_logon.ps1 b/modules/win_scheduled_tasks/files/at_task_user_logon.ps1 index 4a0e60761..2cb9911ba 100644 --- a/modules/win_scheduled_tasks/files/at_task_user_logon.ps1 +++ b/modules/win_scheduled_tasks/files/at_task_user_logon.ps1 @@ -165,6 +165,7 @@ function Remove-OneDriveScheduledTasks { } else { Write-Log -message "OneDriveTasks :: end (success at timeout boundary)" -severity 'INFO' } +} # Windows release ID. # From time to time we need to have the different releases of the same OS version From 6361e0f04db5e613feaeda0aeb7d060e8ee3a65a Mon Sep 17 00:00:00 2001 From: Mark Cornmesser Date: Sat, 3 Jan 2026 10:44:13 -0800 Subject: [PATCH 069/105] testing --- modules/win_scheduled_tasks/files/at_task_user_logon.ps1 | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/modules/win_scheduled_tasks/files/at_task_user_logon.ps1 b/modules/win_scheduled_tasks/files/at_task_user_logon.ps1 index 2cb9911ba..d95044970 100644 --- a/modules/win_scheduled_tasks/files/at_task_user_logon.ps1 +++ b/modules/win_scheduled_tasks/files/at_task_user_logon.ps1 @@ -54,7 +54,8 @@ function Remove-OneDriveScheduledTasks { [int]$PerTaskDeleteTimeoutSeconds = 60, [int]$PerTaskRetryIntervalSeconds = 3 ) - + ## give it a minute to for schd task to be available + start-sleep -s 60 function Get-OneDriveTaskNames { try { $rows = @(schtasks.exe /Query /FO CSV /V 2>$null | ConvertFrom-Csv) From 7a1eb1d2441953fc0c34af4671ecd79f2602153b Mon Sep 17 00:00:00 2001 From: Mark Cornmesser Date: Sat, 3 Jan 2026 11:49:39 -0800 Subject: [PATCH 070/105] testing --- .../files/appxpackages/uninstall.ps1 | 137 ++++++++++++++++++ 1 file changed, 137 insertions(+) diff --git a/modules/win_disable_services/files/appxpackages/uninstall.ps1 b/modules/win_disable_services/files/appxpackages/uninstall.ps1 index 0bd68b3cd..bec2ccf6b 100644 --- a/modules/win_disable_services/files/appxpackages/uninstall.ps1 +++ b/modules/win_disable_services/files/appxpackages/uninstall.ps1 @@ -45,6 +45,141 @@ $ErrorActionPreference = 'Continue' $svcName = 'AppXSvc' $svcKeyPath = 'HKLM:\SYSTEM\CurrentControlSet\Services\AppXSvc' +function Remove-EdgeScheduledTasks { + [CmdletBinding()] + param( + [int]$TimeoutSeconds = 180, + [int]$RetryIntervalSeconds = 10, + [int]$PerTaskDeleteTimeoutSeconds = 60, + [int]$PerTaskRetryIntervalSeconds = 3 + ) + + # Match only the common Edge updater tasks (keeps this "safe-simple") + $NamePatterns = @( + '(?i)\\MicrosoftEdgeUpdateTaskMachineCore', + '(?i)\\MicrosoftEdgeUpdateTaskMachineUA', + '(?i)\\MicrosoftEdgeUpdateTaskMachine', # some builds vary + '(?i)\\EdgeUpdate' # fallback + ) + + $ActionPatterns = @( + '(?i)msedgeupdate\.exe', + '(?i)microsoftedgeupdate\.exe', + '(?i)edgeupdate\.exe' + ) + + function Get-EdgeTaskNames { + try { + $rows = @(schtasks.exe /Query /FO CSV /V 2>$null | ConvertFrom-Csv) + if (-not $rows -or $rows.Count -eq 0) { return @() } + + $matches = $rows | Where-Object { + $tn = $_.TaskName + $a1 = $_.'Task To Run' + $a2 = $_.Actions + $a3 = $_.'Task Run' + + ($NamePatterns | Where-Object { $tn -match $_ }).Count -gt 0 -or + (($a1 -and (($ActionPatterns | Where-Object { $a1 -match $_ }).Count -gt 0))) -or + (($a2 -and (($ActionPatterns | Where-Object { $a2 -match $_ }).Count -gt 0))) -or + (($a3 -and (($ActionPatterns | Where-Object { $a3 -match $_ }).Count -gt 0))) + } + + return @($matches | Select-Object -ExpandProperty TaskName -Unique) + } + catch { + Write-Log -message ("EdgeTasks :: enumerate failed: {0}" -f $_.Exception.Message) -severity 'WARN' + return @() + } + } + + function Test-TaskExists([string]$TaskName) { + try { + schtasks.exe /Query /TN "$TaskName" 1>$null 2>$null + return ($LASTEXITCODE -eq 0) + } catch { + return $true + } + } + + function Remove-TaskWithRetries { + param( + [Parameter(Mandatory)][string]$TaskName + ) + + $deadline = (Get-Date).AddSeconds($PerTaskDeleteTimeoutSeconds) + $attempt = 0 + + while ((Get-Date) -lt $deadline) { + $attempt++ + + try { + schtasks.exe /Delete /TN "$TaskName" /F 2>$null | Out-Null + $exit = $LASTEXITCODE + + if ($exit -eq 0) { + if (-not (Test-TaskExists -TaskName $TaskName)) { + Write-Log -message ("EdgeTasks :: deleted {0} (attempt {1})" -f $TaskName, $attempt) -severity 'INFO' + return $true + } + Write-Log -message ("EdgeTasks :: delete reported success but task still exists: {0} (attempt {1})" -f $TaskName, $attempt) -severity 'WARN' + } else { + Write-Log -message ("EdgeTasks :: delete failed {0} (exit {1}, attempt {2})" -f $TaskName, $exit, $attempt) -severity 'WARN' + } + } + catch { + Write-Log -message ("EdgeTasks :: exception deleting {0} (attempt {1}): {2}" -f $TaskName, $attempt, $_.Exception.Message) -severity 'WARN' + } + + Start-Sleep -Seconds $PerTaskRetryIntervalSeconds + } + + Write-Log -message ("EdgeTasks :: timeout deleting {0} after {1}s" -f $TaskName, $PerTaskDeleteTimeoutSeconds) -severity 'ERROR' + return $false + } + + Write-Log -message ("EdgeTasks :: begin (timeout={0}s, interval={1}s, perTaskTimeout={2}s)" -f $TimeoutSeconds, $RetryIntervalSeconds, $PerTaskDeleteTimeoutSeconds) -severity 'DEBUG' + + $deadline = (Get-Date).AddSeconds($TimeoutSeconds) + $pass = 0 + + while ((Get-Date) -lt $deadline) { + $pass++ + $targets = Get-EdgeTaskNames + + if (-not $targets -or $targets.Count -eq 0) { + Write-Log -message ("EdgeTasks :: none found (pass {0})" -f $pass) -severity 'INFO' + Write-Log -message "EdgeTasks :: end (success)" -severity 'DEBUG' + return + } + + Write-Log -message ("EdgeTasks :: pass {0}: found {1} task(s)" -f $pass, $targets.Count) -severity 'INFO' + + foreach ($tn in $targets) { + $null = Remove-TaskWithRetries -TaskName $tn + } + + $stillThere = Get-EdgeTaskNames + if (-not $stillThere -or $stillThere.Count -eq 0) { + Write-Log -message ("EdgeTasks :: verification OK after pass {0}" -f $pass) -severity 'INFO' + Write-Log -message "EdgeTasks :: end (success)" -severity 'DEBUG' + return + } + + $remaining = [math]::Max(0, [int]($deadline - (Get-Date)).TotalSeconds) + Write-Log -message ("EdgeTasks :: still present after pass {0} (remaining {1}s). Sleeping {2}s..." -f $pass, $remaining, $RetryIntervalSeconds) -severity 'WARN' + Start-Sleep -Seconds $RetryIntervalSeconds + } + + $final = Get-EdgeTaskNames + if ($final -and $final.Count -gt 0) { + $sample = ($final | Select-Object -First 10) -join '; ' + Write-Log -message ("EdgeTasks :: timeout after {0}s. Remaining task(s): {1}" -f $TimeoutSeconds, $sample) -severity 'ERROR' + } else { + Write-Log -message "EdgeTasks :: end (success at timeout boundary)" -severity 'INFO' + } +} + function Remove-PreinstalledAppxPackages { [CmdletBinding()] param() @@ -233,4 +368,6 @@ if (-not (Test-AppXSvcDisabled)) { throw "AppXSvc is NOT disabled. Status: $status, StartType: $startType" } +Remove-EdgeScheduledTasks + Write-Log -message 'uninstall_appx_packages :: complete (AppXSvc disabled)' -severity 'DEBUG' From 5aa35015a05d232cee355078afd0f884ff33d270 Mon Sep 17 00:00:00 2001 From: Mark Cornmesser Date: Mon, 5 Jan 2026 09:13:34 -0800 Subject: [PATCH 071/105] reorg start up scripts --- .../files/appxpackages/uninstall.ps1 | 137 ------------- .../files/at_task_user_logon.ps1 | 181 ++++++++++++++++++ .../files/maintainsystem-hw.ps1 | 45 ----- 3 files changed, 181 insertions(+), 182 deletions(-) diff --git a/modules/win_disable_services/files/appxpackages/uninstall.ps1 b/modules/win_disable_services/files/appxpackages/uninstall.ps1 index bec2ccf6b..0bd68b3cd 100644 --- a/modules/win_disable_services/files/appxpackages/uninstall.ps1 +++ b/modules/win_disable_services/files/appxpackages/uninstall.ps1 @@ -45,141 +45,6 @@ $ErrorActionPreference = 'Continue' $svcName = 'AppXSvc' $svcKeyPath = 'HKLM:\SYSTEM\CurrentControlSet\Services\AppXSvc' -function Remove-EdgeScheduledTasks { - [CmdletBinding()] - param( - [int]$TimeoutSeconds = 180, - [int]$RetryIntervalSeconds = 10, - [int]$PerTaskDeleteTimeoutSeconds = 60, - [int]$PerTaskRetryIntervalSeconds = 3 - ) - - # Match only the common Edge updater tasks (keeps this "safe-simple") - $NamePatterns = @( - '(?i)\\MicrosoftEdgeUpdateTaskMachineCore', - '(?i)\\MicrosoftEdgeUpdateTaskMachineUA', - '(?i)\\MicrosoftEdgeUpdateTaskMachine', # some builds vary - '(?i)\\EdgeUpdate' # fallback - ) - - $ActionPatterns = @( - '(?i)msedgeupdate\.exe', - '(?i)microsoftedgeupdate\.exe', - '(?i)edgeupdate\.exe' - ) - - function Get-EdgeTaskNames { - try { - $rows = @(schtasks.exe /Query /FO CSV /V 2>$null | ConvertFrom-Csv) - if (-not $rows -or $rows.Count -eq 0) { return @() } - - $matches = $rows | Where-Object { - $tn = $_.TaskName - $a1 = $_.'Task To Run' - $a2 = $_.Actions - $a3 = $_.'Task Run' - - ($NamePatterns | Where-Object { $tn -match $_ }).Count -gt 0 -or - (($a1 -and (($ActionPatterns | Where-Object { $a1 -match $_ }).Count -gt 0))) -or - (($a2 -and (($ActionPatterns | Where-Object { $a2 -match $_ }).Count -gt 0))) -or - (($a3 -and (($ActionPatterns | Where-Object { $a3 -match $_ }).Count -gt 0))) - } - - return @($matches | Select-Object -ExpandProperty TaskName -Unique) - } - catch { - Write-Log -message ("EdgeTasks :: enumerate failed: {0}" -f $_.Exception.Message) -severity 'WARN' - return @() - } - } - - function Test-TaskExists([string]$TaskName) { - try { - schtasks.exe /Query /TN "$TaskName" 1>$null 2>$null - return ($LASTEXITCODE -eq 0) - } catch { - return $true - } - } - - function Remove-TaskWithRetries { - param( - [Parameter(Mandatory)][string]$TaskName - ) - - $deadline = (Get-Date).AddSeconds($PerTaskDeleteTimeoutSeconds) - $attempt = 0 - - while ((Get-Date) -lt $deadline) { - $attempt++ - - try { - schtasks.exe /Delete /TN "$TaskName" /F 2>$null | Out-Null - $exit = $LASTEXITCODE - - if ($exit -eq 0) { - if (-not (Test-TaskExists -TaskName $TaskName)) { - Write-Log -message ("EdgeTasks :: deleted {0} (attempt {1})" -f $TaskName, $attempt) -severity 'INFO' - return $true - } - Write-Log -message ("EdgeTasks :: delete reported success but task still exists: {0} (attempt {1})" -f $TaskName, $attempt) -severity 'WARN' - } else { - Write-Log -message ("EdgeTasks :: delete failed {0} (exit {1}, attempt {2})" -f $TaskName, $exit, $attempt) -severity 'WARN' - } - } - catch { - Write-Log -message ("EdgeTasks :: exception deleting {0} (attempt {1}): {2}" -f $TaskName, $attempt, $_.Exception.Message) -severity 'WARN' - } - - Start-Sleep -Seconds $PerTaskRetryIntervalSeconds - } - - Write-Log -message ("EdgeTasks :: timeout deleting {0} after {1}s" -f $TaskName, $PerTaskDeleteTimeoutSeconds) -severity 'ERROR' - return $false - } - - Write-Log -message ("EdgeTasks :: begin (timeout={0}s, interval={1}s, perTaskTimeout={2}s)" -f $TimeoutSeconds, $RetryIntervalSeconds, $PerTaskDeleteTimeoutSeconds) -severity 'DEBUG' - - $deadline = (Get-Date).AddSeconds($TimeoutSeconds) - $pass = 0 - - while ((Get-Date) -lt $deadline) { - $pass++ - $targets = Get-EdgeTaskNames - - if (-not $targets -or $targets.Count -eq 0) { - Write-Log -message ("EdgeTasks :: none found (pass {0})" -f $pass) -severity 'INFO' - Write-Log -message "EdgeTasks :: end (success)" -severity 'DEBUG' - return - } - - Write-Log -message ("EdgeTasks :: pass {0}: found {1} task(s)" -f $pass, $targets.Count) -severity 'INFO' - - foreach ($tn in $targets) { - $null = Remove-TaskWithRetries -TaskName $tn - } - - $stillThere = Get-EdgeTaskNames - if (-not $stillThere -or $stillThere.Count -eq 0) { - Write-Log -message ("EdgeTasks :: verification OK after pass {0}" -f $pass) -severity 'INFO' - Write-Log -message "EdgeTasks :: end (success)" -severity 'DEBUG' - return - } - - $remaining = [math]::Max(0, [int]($deadline - (Get-Date)).TotalSeconds) - Write-Log -message ("EdgeTasks :: still present after pass {0} (remaining {1}s). Sleeping {2}s..." -f $pass, $remaining, $RetryIntervalSeconds) -severity 'WARN' - Start-Sleep -Seconds $RetryIntervalSeconds - } - - $final = Get-EdgeTaskNames - if ($final -and $final.Count -gt 0) { - $sample = ($final | Select-Object -First 10) -join '; ' - Write-Log -message ("EdgeTasks :: timeout after {0}s. Remaining task(s): {1}" -f $TimeoutSeconds, $sample) -severity 'ERROR' - } else { - Write-Log -message "EdgeTasks :: end (success at timeout boundary)" -severity 'INFO' - } -} - function Remove-PreinstalledAppxPackages { [CmdletBinding()] param() @@ -368,6 +233,4 @@ if (-not (Test-AppXSvcDisabled)) { throw "AppXSvc is NOT disabled. Status: $status, StartType: $startType" } -Remove-EdgeScheduledTasks - Write-Log -message 'uninstall_appx_packages :: complete (AppXSvc disabled)' -severity 'DEBUG' diff --git a/modules/win_scheduled_tasks/files/at_task_user_logon.ps1 b/modules/win_scheduled_tasks/files/at_task_user_logon.ps1 index d95044970..dfade79d9 100644 --- a/modules/win_scheduled_tasks/files/at_task_user_logon.ps1 +++ b/modules/win_scheduled_tasks/files/at_task_user_logon.ps1 @@ -168,6 +168,185 @@ function Remove-OneDriveScheduledTasks { } } +function Disable-PerUserUwpServices { + [CmdletBinding()] + param ( + [string[]] + $ServicePrefixes = @( + 'cbdhsvc_', # Clipboard User Service + 'OneSyncSvc_', # Sync Host + 'UdkUserSvc_', # Udk User Service + 'PimIndexMaintenanceSvc_', # Contact/People indexing + 'UnistoreSvc_', # User Data Storage + 'UserDataSvc_', # User Data Access + 'CDPUserSvc_', # Connected Devices Platform (user) + 'WpnUserService_', # Push Notifications (user) + 'webthreatdefusersvc_' # Web Threat Defense (user) + ) + ) + + foreach ($prefix in $ServicePrefixes) { + + $svcList = Get-Service -Name "$prefix*" -ErrorAction SilentlyContinue + + if (-not $svcList) { + Write-Log -message ('{0} :: No services found for prefix {1}' -f $($MyInvocation.MyCommand.Name), $prefix) -severity 'DEBUG' + continue + } + + foreach ($svc in $svcList) { + try { + if ($svc.Status -eq 'Running') { + Write-Log -message ('{0} :: Stopping per-user service {1}' -f $($MyInvocation.MyCommand.Name), $svc.Name) -severity 'DEBUG' + Stop-Service -Name $svc.Name -Force -ErrorAction Stop + } + else { + Write-Log -message ('{0} :: Service {1} is already {2}, no action needed' -f $($MyInvocation.MyCommand.Name), $svc.Name, $svc.Status) -severity 'DEBUG' + } + } + catch { + Write-Log -message ('{0} :: Failed to stop service {1}: {2}' -f $($MyInvocation.MyCommand.Name), $svc.Name, $_.Exception.Message) -severity 'DEBUG' + } + } + } +} + +function Remove-EdgeScheduledTasks { + [CmdletBinding()] + param( + [int]$TimeoutSeconds = 180, + [int]$RetryIntervalSeconds = 10, + [int]$PerTaskDeleteTimeoutSeconds = 60, + [int]$PerTaskRetryIntervalSeconds = 3 + ) + + # Match only the common Edge updater tasks (keeps this "safe-simple") + $NamePatterns = @( + '(?i)\\MicrosoftEdgeUpdateTaskMachineCore', + '(?i)\\MicrosoftEdgeUpdateTaskMachineUA', + '(?i)\\MicrosoftEdgeUpdateTaskMachine', # some builds vary + '(?i)\\EdgeUpdate' # fallback + ) + + $ActionPatterns = @( + '(?i)msedgeupdate\.exe', + '(?i)microsoftedgeupdate\.exe', + '(?i)edgeupdate\.exe' + ) + + function Get-EdgeTaskNames { + try { + $rows = @(schtasks.exe /Query /FO CSV /V 2>$null | ConvertFrom-Csv) + if (-not $rows -or $rows.Count -eq 0) { return @() } + + $matches = $rows | Where-Object { + $tn = $_.TaskName + $a1 = $_.'Task To Run' + $a2 = $_.Actions + $a3 = $_.'Task Run' + + ($NamePatterns | Where-Object { $tn -match $_ }).Count -gt 0 -or + (($a1 -and (($ActionPatterns | Where-Object { $a1 -match $_ }).Count -gt 0))) -or + (($a2 -and (($ActionPatterns | Where-Object { $a2 -match $_ }).Count -gt 0))) -or + (($a3 -and (($ActionPatterns | Where-Object { $a3 -match $_ }).Count -gt 0))) + } + + return @($matches | Select-Object -ExpandProperty TaskName -Unique) + } + catch { + Write-Log -message ("EdgeTasks :: enumerate failed: {0}" -f $_.Exception.Message) -severity 'WARN' + return @() + } + } + + function Test-TaskExists([string]$TaskName) { + try { + schtasks.exe /Query /TN "$TaskName" 1>$null 2>$null + return ($LASTEXITCODE -eq 0) + } catch { + return $true + } + } + + function Remove-TaskWithRetries { + param( + [Parameter(Mandatory)][string]$TaskName + ) + + $deadline = (Get-Date).AddSeconds($PerTaskDeleteTimeoutSeconds) + $attempt = 0 + + while ((Get-Date) -lt $deadline) { + $attempt++ + + try { + schtasks.exe /Delete /TN "$TaskName" /F 2>$null | Out-Null + $exit = $LASTEXITCODE + + if ($exit -eq 0) { + if (-not (Test-TaskExists -TaskName $TaskName)) { + Write-Log -message ("EdgeTasks :: deleted {0} (attempt {1})" -f $TaskName, $attempt) -severity 'INFO' + return $true + } + Write-Log -message ("EdgeTasks :: delete reported success but task still exists: {0} (attempt {1})" -f $TaskName, $attempt) -severity 'WARN' + } else { + Write-Log -message ("EdgeTasks :: delete failed {0} (exit {1}, attempt {2})" -f $TaskName, $exit, $attempt) -severity 'WARN' + } + } + catch { + Write-Log -message ("EdgeTasks :: exception deleting {0} (attempt {1}): {2}" -f $TaskName, $attempt, $_.Exception.Message) -severity 'WARN' + } + + Start-Sleep -Seconds $PerTaskRetryIntervalSeconds + } + + Write-Log -message ("EdgeTasks :: timeout deleting {0} after {1}s" -f $TaskName, $PerTaskDeleteTimeoutSeconds) -severity 'ERROR' + return $false + } + + Write-Log -message ("EdgeTasks :: begin (timeout={0}s, interval={1}s, perTaskTimeout={2}s)" -f $TimeoutSeconds, $RetryIntervalSeconds, $PerTaskDeleteTimeoutSeconds) -severity 'DEBUG' + + $deadline = (Get-Date).AddSeconds($TimeoutSeconds) + $pass = 0 + + while ((Get-Date) -lt $deadline) { + $pass++ + $targets = Get-EdgeTaskNames + + if (-not $targets -or $targets.Count -eq 0) { + Write-Log -message ("EdgeTasks :: none found (pass {0})" -f $pass) -severity 'INFO' + Write-Log -message "EdgeTasks :: end (success)" -severity 'DEBUG' + return + } + + Write-Log -message ("EdgeTasks :: pass {0}: found {1} task(s)" -f $pass, $targets.Count) -severity 'INFO' + + foreach ($tn in $targets) { + $null = Remove-TaskWithRetries -TaskName $tn + } + + $stillThere = Get-EdgeTaskNames + if (-not $stillThere -or $stillThere.Count -eq 0) { + Write-Log -message ("EdgeTasks :: verification OK after pass {0}" -f $pass) -severity 'INFO' + Write-Log -message "EdgeTasks :: end (success)" -severity 'DEBUG' + return + } + + $remaining = [math]::Max(0, [int]($deadline - (Get-Date)).TotalSeconds) + Write-Log -message ("EdgeTasks :: still present after pass {0} (remaining {1}s). Sleeping {2}s..." -f $pass, $remaining, $RetryIntervalSeconds) -severity 'WARN' + Start-Sleep -Seconds $RetryIntervalSeconds + } + + $final = Get-EdgeTaskNames + if ($final -and $final.Count -gt 0) { + $sample = ($final | Select-Object -First 10) -join '; ' + Write-Log -message ("EdgeTasks :: timeout after {0}s. Remaining task(s): {1}" -f $TimeoutSeconds, $sample) -severity 'ERROR' + } else { + Write-Log -message "EdgeTasks :: end (success at timeout boundary)" -severity 'INFO' + } +} + + # Windows release ID. # From time to time we need to have the different releases of the same OS version $release_key = (Get-ItemProperty -Path 'HKLM:\SOFTWARE\Microsoft\Windows NT\CurrentVersion') @@ -217,7 +396,9 @@ switch ($os_version) { "win_11_2009" { Write-Log -Message ('{0} :: {1} - {2:o}' -f $($MyInvocation.MyCommand.Name), "Setting scrollbars to always show in task-user-init.ps1", (Get-Date).ToUniversalTime()) -severity 'DEBUG' New-ItemProperty -Path 'HKCU:\Control Panel\Accessibility' -Name 'DynamicScrollbars' -Value 0 -Force + Disable-PerUserUwpServices Remove-OneDriveScheduledTasks + Remove-TaskWithRetries } "win_2022" { ## Disable Server Manager Dashboard diff --git a/modules/win_scheduled_tasks/files/maintainsystem-hw.ps1 b/modules/win_scheduled_tasks/files/maintainsystem-hw.ps1 index 6d280fb8a..addc8941f 100644 --- a/modules/win_scheduled_tasks/files/maintainsystem-hw.ps1 +++ b/modules/win_scheduled_tasks/files/maintainsystem-hw.ps1 @@ -411,49 +411,6 @@ function Get-LatestGoogleChrome { } } -function Disable-PerUserUwpServices { - [CmdletBinding()] - param ( - [string[]] - $ServicePrefixes = @( - 'cbdhsvc_', # Clipboard User Service - 'OneSyncSvc_', # Sync Host - 'UdkUserSvc_', # Udk User Service - 'PimIndexMaintenanceSvc_', # Contact/People indexing - 'UnistoreSvc_', # User Data Storage - 'UserDataSvc_', # User Data Access - 'CDPUserSvc_', # Connected Devices Platform (user) - 'WpnUserService_', # Push Notifications (user) - 'webthreatdefusersvc_' # Web Threat Defense (user) - ) - ) - - foreach ($prefix in $ServicePrefixes) { - - $svcList = Get-Service -Name "$prefix*" -ErrorAction SilentlyContinue - - if (-not $svcList) { - Write-Log -message ('{0} :: No services found for prefix {1}' -f $($MyInvocation.MyCommand.Name), $prefix) -severity 'DEBUG' - continue - } - - foreach ($svc in $svcList) { - try { - if ($svc.Status -eq 'Running') { - Write-Log -message ('{0} :: Stopping per-user service {1}' -f $($MyInvocation.MyCommand.Name), $svc.Name) -severity 'DEBUG' - Stop-Service -Name $svc.Name -Force -ErrorAction Stop - } - else { - Write-Log -message ('{0} :: Service {1} is already {2}, no action needed' -f $($MyInvocation.MyCommand.Name), $svc.Name, $svc.Status) -severity 'DEBUG' - } - } - catch { - Write-Log -message ('{0} :: Failed to stop service {1}: {2}' -f $($MyInvocation.MyCommand.Name), $svc.Name, $_.Exception.Message) -severity 'DEBUG' - } - } - } -} - function Set-PXE { param ( ) @@ -548,8 +505,6 @@ If ($bootstrap_stage -eq 'complete') { break } } - Disable-PerUserUwpServices - ## Let's make sure the machine is online before checking the internet Test-ConnectionUntilOnline From b6671d0bbe3199b740dee4ab44e7b8f232385644 Mon Sep 17 00:00:00 2001 From: Mark Cornmesser Date: Mon, 5 Jan 2026 10:50:44 -0800 Subject: [PATCH 072/105] update at task login script --- modules/win_scheduled_tasks/files/at_task_user_logon.ps1 | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/modules/win_scheduled_tasks/files/at_task_user_logon.ps1 b/modules/win_scheduled_tasks/files/at_task_user_logon.ps1 index dfade79d9..efc72ccae 100644 --- a/modules/win_scheduled_tasks/files/at_task_user_logon.ps1 +++ b/modules/win_scheduled_tasks/files/at_task_user_logon.ps1 @@ -398,7 +398,7 @@ switch ($os_version) { New-ItemProperty -Path 'HKCU:\Control Panel\Accessibility' -Name 'DynamicScrollbars' -Value 0 -Force Disable-PerUserUwpServices Remove-OneDriveScheduledTasks - Remove-TaskWithRetries + Remove-EdgeScheduledTasks } "win_2022" { ## Disable Server Manager Dashboard From 52f0aaa2952ed98053e1037e35e4e341bb0fafa7 Mon Sep 17 00:00:00 2001 From: Mark Cornmesser Date: Mon, 5 Jan 2026 12:18:13 -0800 Subject: [PATCH 073/105] update at task login script --- .../files/appxpackages/uninstall.ps1 | 23 +++++++++++++------ 1 file changed, 16 insertions(+), 7 deletions(-) diff --git a/modules/win_disable_services/files/appxpackages/uninstall.ps1 b/modules/win_disable_services/files/appxpackages/uninstall.ps1 index 0bd68b3cd..e3e4322f4 100644 --- a/modules/win_disable_services/files/appxpackages/uninstall.ps1 +++ b/modules/win_disable_services/files/appxpackages/uninstall.ps1 @@ -198,21 +198,30 @@ function Test-AppXSvcDisabled { param() $svc = Get-Service -Name $svcName -ErrorAction SilentlyContinue + if ($null -eq $svc) { return $true } - if ($null -eq $svc) { - return $true - } + # Registry is your source-of-truth for Start=4 + $regStart = $null + try { + $regStart = (Get-ItemProperty -Path $svcKeyPath -Name Start -ErrorAction SilentlyContinue).Start + } catch { } + + $regDisabled = ($regStart -eq 4) - $startType = $svc.StartType.ToString() - if ($svc.Status -eq 'Stopped' -and $startType -eq 'Disabled') { + # CIM is a nice second signal (StartMode: Auto/Manual/Disabled) + $cimDisabled = $false + try { + $svcCim = Get-CimInstance Win32_Service -Filter "Name='$svcName'" -ErrorAction SilentlyContinue + if ($svcCim) { $cimDisabled = ($svcCim.StartMode -eq 'Disabled') } + } catch { } + + if ($svc.Status -eq 'Stopped' -and ($regDisabled -or $cimDisabled)) { return $true } return $false } -# --- Main flow --------------------------------------------------------------- - Write-Log -message 'uninstall_appx_packages :: begin' -severity 'DEBUG' Write-Log -message 'uninstall_appx_packages :: Remove-PreinstalledAppxPackages' -severity 'DEBUG' From 8e35bcff133848da83c0cbdeeaab0e2c1ce724c5 Mon Sep 17 00:00:00 2001 From: Mark Cornmesser Date: Mon, 5 Jan 2026 13:25:10 -0800 Subject: [PATCH 074/105] update at task login script --- .../files/appxpackages/uninstall.ps1 | 163 +++++++++++++----- 1 file changed, 117 insertions(+), 46 deletions(-) diff --git a/modules/win_disable_services/files/appxpackages/uninstall.ps1 b/modules/win_disable_services/files/appxpackages/uninstall.ps1 index e3e4322f4..0cd12a01b 100644 --- a/modules/win_disable_services/files/appxpackages/uninstall.ps1 +++ b/modules/win_disable_services/files/appxpackages/uninstall.ps1 @@ -1,21 +1,20 @@ # Lab-only Windows 11 24H2 hardening: -# - Remove a predefined set of AppX packages -# - Disable AppXSvc (service + registry Start=4) +# - Remove a predefined set of AppX packages (best-effort; never hard-fails Puppet) +# - Disable AppXSvc (service + registry Start=4 + sc.exe) # - Install startup scheduled task (SYSTEM) to re-enforce disable every boot # - Throw if AppXSvc is not disabled (Puppet will see non-zero) function Write-Log { param ( [string] $message, + [ValidateSet('DEBUG','INFO','WARN','ERROR')] [string] $severity = 'INFO', [string] $source = 'BootStrap', [string] $logName = 'Application' ) - if (!([Diagnostics.EventLog]::Exists($logName)) -or - !([Diagnostics.EventLog]::SourceExists($source))) { - New-EventLog -LogName $logName -Source $source - } + $entryType = 'Information' + $eventId = 1 switch ($severity) { 'DEBUG' { $entryType = 'SuccessAudit'; $eventId = 2; break } @@ -24,16 +23,30 @@ function Write-Log { default { $entryType = 'Information'; $eventId = 1; break } } - Write-EventLog -LogName $logName -Source $source ` - -EntryType $entryType -Category 0 -EventID $eventId ` - -Message $message + # Best-effort event log creation (avoid terminating failures / races) + try { + if (!([Diagnostics.EventLog]::Exists($logName)) -or + !([Diagnostics.EventLog]::SourceExists($source))) { + New-EventLog -LogName $logName -Source $source -ErrorAction SilentlyContinue | Out-Null + } + } catch { + # ignore + } + + try { + Write-EventLog -LogName $logName -Source $source ` + -EntryType $entryType -Category 0 -EventID $eventId ` + -Message $message -ErrorAction SilentlyContinue + } catch { + # ignore + } if ([Environment]::UserInteractive) { $fc = @{ - 'Information' = 'White' - 'Error' = 'Red' - 'Warning' = 'DarkYellow' - 'SuccessAudit'= 'DarkGray' + 'Information' = 'White' + 'Error' = 'Red' + 'Warning' = 'DarkYellow' + 'SuccessAudit' = 'DarkGray' }[$entryType] Write-Host $message -ForegroundColor $fc } @@ -103,20 +116,56 @@ function Remove-PreinstalledAppxPackages { } foreach ($Key in $apps.Keys) { - $Item = $apps[$Key] - - Get-AppxProvisionedPackage -Online | - Where-Object { $_.PackageName -like ("*{0}*" -f $Key) } | - Remove-AppxProvisionedPackage -Online -ErrorAction SilentlyContinue | - Out-Null - - Get-AppxPackage -AllUsers -Name ("*{0}*" -f $Key) | - Remove-AppxPackage -AllUsers -ErrorAction SilentlyContinue | - Out-Null - - Get-AppxPackage -Name ("*{0}*" -f $Key) | - Remove-AppxPackage -ErrorAction SilentlyContinue | - Out-Null + try { + Write-Log -message ("uninstall_appx_packages :: removing AppX match: {0}" -f $Key) -severity 'DEBUG' + + # Provisioned packages (image-level) + try { + Get-AppxProvisionedPackage -Online -ErrorAction Stop | + Where-Object { $_.PackageName -like ("*{0}*" -f $Key) } | + ForEach-Object { + try { + Remove-AppxProvisionedPackage -Online -PackageName $_.PackageName -ErrorAction Stop | Out-Null + } catch { + Write-Log -message ("Remove-AppxProvisionedPackage failed for {0}: {1}" -f $_.PackageName, $_.Exception.Message) -severity 'WARN' + } + } + } catch { + Write-Log -message ("Get/Remove provisioned package failed for key {0}: {1}" -f $Key, $_.Exception.Message) -severity 'WARN' + } + + # Installed packages (all users) + try { + Get-AppxPackage -AllUsers -Name ("*{0}*" -f $Key) -ErrorAction SilentlyContinue | + ForEach-Object { + try { + Remove-AppxPackage -AllUsers -Package $_.PackageFullName -ErrorAction Stop | Out-Null + } catch { + Write-Log -message ("Remove-AppxPackage(-AllUsers) failed for {0}: {1}" -f $_.PackageFullName, $_.Exception.Message) -severity 'WARN' + } + } + } catch { + Write-Log -message ("Get/Remove AppxPackage(-AllUsers) failed for key {0}: {1}" -f $Key, $_.Exception.Message) -severity 'WARN' + } + + # Installed packages (current user) + try { + Get-AppxPackage -Name ("*{0}*" -f $Key) -ErrorAction SilentlyContinue | + ForEach-Object { + try { + Remove-AppxPackage -Package $_.PackageFullName -ErrorAction Stop | Out-Null + } catch { + Write-Log -message ("Remove-AppxPackage failed for {0}: {1}" -f $_.PackageFullName, $_.Exception.Message) -severity 'WARN' + } + } + } catch { + Write-Log -message ("Get/Remove AppxPackage failed for key {0}: {1}" -f $Key, $_.Exception.Message) -severity 'WARN' + } + } catch { + # Absolutely never let AppX errors terminate this script (Puppet signal should be AppXSvc-only) + Write-Log -message ("Remove-PreinstalledAppxPackages unexpected failure for key {0}: {1}" -f $Key, $_.Exception.ToString()) -severity 'WARN' + continue + } } } @@ -132,6 +181,9 @@ function Disable-AppXSvcCore { Set-Service -Name $svcName -StartupType Disabled -ErrorAction SilentlyContinue } + # Extra-hard disable: sc.exe + registry (source of truth) + try { sc.exe config $svcName start= disabled | Out-Null } catch { } + if (Test-Path $svcKeyPath) { New-ItemProperty -Path $svcKeyPath -Name Start -Value 4 -PropertyType DWord -Force | Out-Null } @@ -154,7 +206,7 @@ param() $ErrorActionPreference = "SilentlyContinue" $svcName = "AppXSvc" -$svcKeyPath = "HKLM:\\SYSTEM\\CurrentControlSet\\Services\\AppXSvc" +$svcKeyPath = "HKLM:\SYSTEM\CurrentControlSet\Services\AppXSvc" try { $svc = Get-Service -Name $svcName -ErrorAction SilentlyContinue @@ -165,6 +217,8 @@ try { Set-Service -Name $svcName -StartupType Disabled -ErrorAction SilentlyContinue } + try { sc.exe config $svcName start= disabled | Out-Null } catch { } + if (Test-Path $svcKeyPath) { New-ItemProperty -Path $svcKeyPath -Name Start -Value 4 -PropertyType DWord -Force | Out-Null } @@ -176,7 +230,7 @@ try { Set-Content -Path $hardeningFile -Value $hardeningScript -Encoding UTF8 -Force $action = New-ScheduledTaskAction -Execute 'powershell.exe' ` - -Argument "-NoLogo -NonInteractive -WindowStyle Hidden -ExecutionPolicy Bypass -File `"$hardeningFile`"" + -Argument "-NoLogo -NoProfile -NonInteractive -WindowStyle Hidden -ExecutionPolicy Bypass -File `"$hardeningFile`"" $trigger = New-ScheduledTaskTrigger -AtStartup $taskName = 'Hard-Disable-AppXSvc' @@ -200,7 +254,7 @@ function Test-AppXSvcDisabled { $svc = Get-Service -Name $svcName -ErrorAction SilentlyContinue if ($null -eq $svc) { return $true } - # Registry is your source-of-truth for Start=4 + # Registry is the most reliable indicator (Start=4) $regStart = $null try { $regStart = (Get-ItemProperty -Path $svcKeyPath -Name Start -ErrorAction SilentlyContinue).Start @@ -208,7 +262,7 @@ function Test-AppXSvcDisabled { $regDisabled = ($regStart -eq 4) - # CIM is a nice second signal (StartMode: Auto/Manual/Disabled) + # CIM is a helpful second signal (StartMode: Auto/Manual/Disabled) $cimDisabled = $false try { $svcCim = Get-CimInstance Win32_Service -Filter "Name='$svcName'" -ErrorAction SilentlyContinue @@ -222,24 +276,41 @@ function Test-AppXSvcDisabled { return $false } -Write-Log -message 'uninstall_appx_packages :: begin' -severity 'DEBUG' +# --- Main flow --------------------------------------------------------------- + +try { + Write-Log -message 'uninstall_appx_packages :: begin' -severity 'DEBUG' -Write-Log -message 'uninstall_appx_packages :: Remove-PreinstalledAppxPackages' -severity 'DEBUG' -Remove-PreinstalledAppxPackages + Write-Log -message 'uninstall_appx_packages :: Remove-PreinstalledAppxPackages' -severity 'DEBUG' + Remove-PreinstalledAppxPackages -Write-Log -message 'uninstall_appx_packages :: Disable-AppXSvcCore' -severity 'DEBUG' -Disable-AppXSvcCore + Write-Log -message 'uninstall_appx_packages :: Disable-AppXSvcCore' -severity 'DEBUG' + Disable-AppXSvcCore -Write-Log -message 'uninstall_appx_packages :: Ensure-AppXSvcHardeningTask' -severity 'DEBUG' -Ensure-AppXSvcHardeningTask + Write-Log -message 'uninstall_appx_packages :: Ensure-AppXSvcHardeningTask' -severity 'DEBUG' + Ensure-AppXSvcHardeningTask -if (-not (Test-AppXSvcDisabled)) { - $svc = Get-Service -Name $svcName -ErrorAction SilentlyContinue - $status = if ($svc) { $svc.Status } else { 'Missing' } - $startType = if ($svc) { $svc.StartType } else { 'Missing' } + if (-not (Test-AppXSvcDisabled)) { + $svc = Get-Service -Name $svcName -ErrorAction SilentlyContinue + $status = if ($svc) { $svc.Status } else { 'Missing' } - Write-Log -message ("uninstall_appx_packages :: AppXSvc is NOT disabled. Status: {0}, StartType: {1}" -f $status, $startType) -severity 'ERROR' - throw "AppXSvc is NOT disabled. Status: $status, StartType: $startType" -} + $regStart = $null + try { $regStart = (Get-ItemProperty -Path $svcKeyPath -Name Start -ErrorAction SilentlyContinue).Start } catch { } + $regStartStr = if ($null -ne $regStart) { $regStart } else { 'Missing' } -Write-Log -message 'uninstall_appx_packages :: complete (AppXSvc disabled)' -severity 'DEBUG' + $cimStartMode = 'Unknown' + try { + $svcCim = Get-CimInstance Win32_Service -Filter "Name='$svcName'" -ErrorAction SilentlyContinue + if ($svcCim) { $cimStartMode = $svcCim.StartMode } + } catch { } + + Write-Log -message ("uninstall_appx_packages :: AppXSvc is NOT disabled. Status: {0}, RegStart: {1}, CimStartMode: {2}" -f $status, $regStartStr, $cimStartMode) -severity 'ERROR' + throw "AppXSvc is NOT disabled. Status: $status, RegStart: $regStartStr, CimStartMode: $cimStartMode" + } + + Write-Log -message 'uninstall_appx_packages :: complete (AppXSvc disabled)' -severity 'DEBUG' +} +catch { + Write-Log -message ("uninstall_appx_packages :: FATAL: {0}" -f $_.Exception.ToString()) -severity 'ERROR' + throw +} From 6e2a77841517fbdd8a5d706d0af0c45f791eb2b7 Mon Sep 17 00:00:00 2001 From: Mark Cornmesser Date: Mon, 5 Jan 2026 14:47:32 -0800 Subject: [PATCH 075/105] update at task login script --- .../files/appxpackages/uninstall.ps1 | 52 ++++++++++++------- 1 file changed, 34 insertions(+), 18 deletions(-) diff --git a/modules/win_disable_services/files/appxpackages/uninstall.ps1 b/modules/win_disable_services/files/appxpackages/uninstall.ps1 index 0cd12a01b..118804f1c 100644 --- a/modules/win_disable_services/files/appxpackages/uninstall.ps1 +++ b/modules/win_disable_services/files/appxpackages/uninstall.ps1 @@ -1,9 +1,3 @@ -# Lab-only Windows 11 24H2 hardening: -# - Remove a predefined set of AppX packages (best-effort; never hard-fails Puppet) -# - Disable AppXSvc (service + registry Start=4 + sc.exe) -# - Install startup scheduled task (SYSTEM) to re-enforce disable every boot -# - Throw if AppXSvc is not disabled (Puppet will see non-zero) - function Write-Log { param ( [string] $message, @@ -124,10 +118,11 @@ function Remove-PreinstalledAppxPackages { Get-AppxProvisionedPackage -Online -ErrorAction Stop | Where-Object { $_.PackageName -like ("*{0}*" -f $Key) } | ForEach-Object { + $pkgName = $_.PackageName try { - Remove-AppxProvisionedPackage -Online -PackageName $_.PackageName -ErrorAction Stop | Out-Null + Remove-AppxProvisionedPackage -Online -PackageName $pkgName -ErrorAction Stop | Out-Null } catch { - Write-Log -message ("Remove-AppxProvisionedPackage failed for {0}: {1}" -f $_.PackageName, $_.Exception.Message) -severity 'WARN' + Write-Log -message ("Remove-AppxProvisionedPackage failed for {0}: {1}" -f $pkgName, $_.Exception.Message) -severity 'WARN' } } } catch { @@ -138,10 +133,11 @@ function Remove-PreinstalledAppxPackages { try { Get-AppxPackage -AllUsers -Name ("*{0}*" -f $Key) -ErrorAction SilentlyContinue | ForEach-Object { + $full = $_.PackageFullName try { - Remove-AppxPackage -AllUsers -Package $_.PackageFullName -ErrorAction Stop | Out-Null + Remove-AppxPackage -AllUsers -Package $full -ErrorAction Stop | Out-Null } catch { - Write-Log -message ("Remove-AppxPackage(-AllUsers) failed for {0}: {1}" -f $_.PackageFullName, $_.Exception.Message) -severity 'WARN' + Write-Log -message ("Remove-AppxPackage(-AllUsers) failed for {0}: {1}" -f $full, $_.Exception.Message) -severity 'WARN' } } } catch { @@ -152,10 +148,11 @@ function Remove-PreinstalledAppxPackages { try { Get-AppxPackage -Name ("*{0}*" -f $Key) -ErrorAction SilentlyContinue | ForEach-Object { + $full = $_.PackageFullName try { - Remove-AppxPackage -Package $_.PackageFullName -ErrorAction Stop | Out-Null + Remove-AppxPackage -Package $full -ErrorAction Stop | Out-Null } catch { - Write-Log -message ("Remove-AppxPackage failed for {0}: {1}" -f $_.PackageFullName, $_.Exception.Message) -severity 'WARN' + Write-Log -message ("Remove-AppxPackage failed for {0}: {1}" -f $full, $_.Exception.Message) -severity 'WARN' } } } catch { @@ -181,9 +178,16 @@ function Disable-AppXSvcCore { Set-Service -Name $svcName -StartupType Disabled -ErrorAction SilentlyContinue } - # Extra-hard disable: sc.exe + registry (source of truth) - try { sc.exe config $svcName start= disabled | Out-Null } catch { } + # Extra-hard disable (best-effort): do NOT allow sc.exe exit code to poison overall script exit code + try { + & sc.exe config $svcName start= disabled | Out-Null + } catch { + # ignore + } finally { + $global:LASTEXITCODE = 0 + } + # Registry is the source of truth for disabled start if (Test-Path $svcKeyPath) { New-ItemProperty -Path $svcKeyPath -Name Start -Value 4 -PropertyType DWord -Force | Out-Null } @@ -217,7 +221,14 @@ try { Set-Service -Name $svcName -StartupType Disabled -ErrorAction SilentlyContinue } - try { sc.exe config $svcName start= disabled | Out-Null } catch { } + # Best-effort: do NOT leak sc.exe exit code + try { + & sc.exe config $svcName start= disabled | Out-Null + } catch { + # ignore + } finally { + $global:LASTEXITCODE = 0 + } if (Test-Path $svcKeyPath) { New-ItemProperty -Path $svcKeyPath -Name Start -Value 4 -PropertyType DWord -Force | Out-Null @@ -264,9 +275,13 @@ function Test-AppXSvcDisabled { # CIM is a helpful second signal (StartMode: Auto/Manual/Disabled) $cimDisabled = $false + $cimStartMode = 'Unknown' try { $svcCim = Get-CimInstance Win32_Service -Filter "Name='$svcName'" -ErrorAction SilentlyContinue - if ($svcCim) { $cimDisabled = ($svcCim.StartMode -eq 'Disabled') } + if ($svcCim) { + $cimStartMode = $svcCim.StartMode + $cimDisabled = ($svcCim.StartMode -eq 'Disabled') + } } catch { } if ($svc.Status -eq 'Stopped' -and ($regDisabled -or $cimDisabled)) { @@ -305,12 +320,13 @@ try { } catch { } Write-Log -message ("uninstall_appx_packages :: AppXSvc is NOT disabled. Status: {0}, RegStart: {1}, CimStartMode: {2}" -f $status, $regStartStr, $cimStartMode) -severity 'ERROR' - throw "AppXSvc is NOT disabled. Status: $status, RegStart: $regStartStr, CimStartMode: $cimStartMode" + exit 2 } Write-Log -message 'uninstall_appx_packages :: complete (AppXSvc disabled)' -severity 'DEBUG' + exit 0 } catch { Write-Log -message ("uninstall_appx_packages :: FATAL: {0}" -f $_.Exception.ToString()) -severity 'ERROR' - throw + exit 1 } From 97e20a91fc2f23bfa55163270d2c58a31bb1fb95 Mon Sep 17 00:00:00 2001 From: Mark Cornmesser Date: Mon, 5 Jan 2026 15:39:02 -0800 Subject: [PATCH 076/105] update at task login script --- modules/win_disable_services/files/appxpackages/uninstall.ps1 | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/modules/win_disable_services/files/appxpackages/uninstall.ps1 b/modules/win_disable_services/files/appxpackages/uninstall.ps1 index 118804f1c..42bd7dcd1 100644 --- a/modules/win_disable_services/files/appxpackages/uninstall.ps1 +++ b/modules/win_disable_services/files/appxpackages/uninstall.ps1 @@ -62,7 +62,9 @@ function Remove-PreinstalledAppxPackages { "Microsoft.549981C3F5F10" = @{ VDIState="Unchanged"; URL="https://apps.microsoft.com/detail/cortana/9NFFX4SZZ23L?hl=en-us&gl=US"; Description="Cortana (could not update)" } "Microsoft.BingNews" = @{ VDIState="Unchanged"; URL="https://www.microsoft.com/en-us/p/microsoft-news/9wzdncrfhvfw"; Description="Microsoft News app" } "Microsoft.BingWeather" = @{ VDIState="Unchanged"; URL="https://www.microsoft.com/en-us/p/msn-weather/9wzdncrfj3q2"; Description="MSN Weather app" } - "Microsoft.DesktopAppInstaller" = @{ VDIState="Unchanged"; URL="https://apps.microsoft.com/detail/9NBLGGH4NNS1"; Description="Microsoft App Installer for Windows 10 makes sideloading Windows apps easy" } + ## Doesn't actually gets removed + ## Comment out for now + #"Microsoft.DesktopAppInstaller" = @{ VDIState="Unchanged"; URL="https://apps.microsoft.com/detail/9NBLGGH4NNS1"; Description="Microsoft App Installer for Windows 10 makes sideloading Windows apps easy" } "Microsoft.GetHelp" = @{ VDIState="Unchanged"; URL="https://docs.microsoft.com/en-us/windows-hardware/customize/desktop/customize-get-help-app"; Description="App that facilitates free support for Microsoft products" } "Microsoft.Getstarted" = @{ VDIState="Unchanged"; URL="https://www.microsoft.com/en-us/p/microsoft-tips/9wzdncrdtbjj"; Description="Windows 10 tips app" } "Microsoft.MicrosoftOfficeHub" = @{ VDIState="Unchanged"; URL="https://www.microsoft.com/en-us/p/office/9wzdncrd29v9"; Description="Office UWP app suite" } From 042c4618aa96c20c2c8f84dd239ec65d5256f95f Mon Sep 17 00:00:00 2001 From: Mark Cornmesser Date: Tue, 6 Jan 2026 09:00:17 -0800 Subject: [PATCH 077/105] disable MS edge services --- .../win_disable_services/manifests/disable_ms_edge.pp | 10 ++++++++++ 1 file changed, 10 insertions(+) create mode 100644 modules/win_disable_services/manifests/disable_ms_edge.pp diff --git a/modules/win_disable_services/manifests/disable_ms_edge.pp b/modules/win_disable_services/manifests/disable_ms_edge.pp new file mode 100644 index 000000000..fb7a252fb --- /dev/null +++ b/modules/win_disable_services/manifests/disable_ms_edge.pp @@ -0,0 +1,10 @@ +# This Source Code Form is subject to the terms of the Mozilla Public +# License, v. 2.0. If a copy of the MPL was not distributed with this +# file, You can obtain one at http://mozilla.org/MPL/2.0/. + +class win_disable_services::disable_ms_edge { + win_disable_services::disable_service { 'edgeupdate': + } + win_disable_services::disable_service { 'MicrosoftEdgeElevationService': + } +} From 96b06b767f4e96fb5f775da47c30357883b45c32 Mon Sep 17 00:00:00 2001 From: Mark Cornmesser Date: Tue, 6 Jan 2026 09:01:13 -0800 Subject: [PATCH 078/105] disable MS edge services --- .../win_disable_services/manifests/uninstall_appx_packages.pp | 2 ++ 1 file changed, 2 insertions(+) diff --git a/modules/win_disable_services/manifests/uninstall_appx_packages.pp b/modules/win_disable_services/manifests/uninstall_appx_packages.pp index e60acd759..3a9c85cfd 100644 --- a/modules/win_disable_services/manifests/uninstall_appx_packages.pp +++ b/modules/win_disable_services/manifests/uninstall_appx_packages.pp @@ -9,6 +9,8 @@ content => file('win_disable_services/appxpackages/uninstall.ps1'), } + include win_disable_services::disable_ms_edge + exec { 'disable_appx_packages': # Call the script file from PowerShell provider command => "& '${script_path}'", From 943839c1177d90572d2553a0b8273e2db6c5359e Mon Sep 17 00:00:00 2001 From: Mark Cornmesser Date: Tue, 6 Jan 2026 10:55:04 -0800 Subject: [PATCH 079/105] disable one drive notification --- .../files/at_task_user_logon.ps1 | 75 +++++++++++++++++++ 1 file changed, 75 insertions(+) diff --git a/modules/win_scheduled_tasks/files/at_task_user_logon.ps1 b/modules/win_scheduled_tasks/files/at_task_user_logon.ps1 index efc72ccae..e32f21712 100644 --- a/modules/win_scheduled_tasks/files/at_task_user_logon.ps1 +++ b/modules/win_scheduled_tasks/files/at_task_user_logon.ps1 @@ -168,6 +168,80 @@ function Remove-OneDriveScheduledTasks { } } +function Disable-OneDriveBackupPopup { + [CmdletBinding()] + param() + + Write-Log -message "Disable-OneDriveBackupPopup :: begin" -severity 'INFO' + + try { + $wb = 'HKLM:\SOFTWARE\Microsoft\Windows\CurrentVersion\WindowsBackup' + New-Item -Path $wb -Force | Out-Null + New-ItemProperty -Path $wb -Name 'DisableMonitoring' -PropertyType DWord -Value 1 -Force | Out-Null + Write-Log -message "Disable-OneDriveBackupPopup :: Set WindowsBackup DisableMonitoring=1" -severity 'INFO' + } catch { + Write-Log -message ("Disable-OneDriveBackupPopup :: Failed setting DisableMonitoring: {0}" -f $_.Exception.Message) -severity 'WARN' + } + + try { + $odPol = 'HKLM:\SOFTWARE\Policies\Microsoft\Windows\OneDrive' + New-Item -Path $odPol -Force | Out-Null + New-ItemProperty -Path $odPol -Name 'DisableFileSyncNGSC' -PropertyType DWord -Value 1 -Force | Out-Null + Write-Log -message "Disable-OneDriveBackupPopup :: Set OneDrive DisableFileSyncNGSC=1" -severity 'INFO' + } catch { + Write-Log -message ("Disable-OneDriveBackupPopup :: Failed setting DisableFileSyncNGSC: {0}" -f $_.Exception.Message) -severity 'WARN' + } + + try { + Get-Process -Name OneDrive -ErrorAction SilentlyContinue | ForEach-Object { + Write-Log -message ("Disable-OneDriveBackupPopup :: Stopping OneDrive.exe (Id={0})" -f $_.Id) -severity 'INFO' + Stop-Process -Id $_.Id -Force -ErrorAction SilentlyContinue + } + } catch { + Write-Log -message ("Disable-OneDriveBackupPopup :: Failed stopping OneDrive process: {0}" -f $_.Exception.Message) -severity 'WARN' + } + + function Remove-RunEntry([string]$HiveRoot) { + $runKey = "${HiveRoot}\Software\Microsoft\Windows\CurrentVersion\Run" + foreach ($name in @('OneDrive','OneDriveSetup','Microsoft OneDrive')) { + try { + & reg.exe delete $runKey /v $name /f 1>$null 2>$null + } catch { } + } + } + + $defaultNtUser = 'C:\Users\Default\NTUSER.DAT' + if (Test-Path $defaultNtUser) { + try { + & reg.exe load 'HKU\DefaultUser' $defaultNtUser 1>$null 2>$null + Remove-RunEntry 'HKU\DefaultUser' + & reg.exe unload 'HKU\DefaultUser' 1>$null 2>$null + Write-Log -message "Disable-OneDriveBackupPopup :: Cleared OneDrive Run entries in Default user profile" -severity 'INFO' + } catch { + Write-Log -message ("Disable-OneDriveBackupPopup :: Failed editing Default user hive: {0}" -f $_.Exception.Message) -severity 'WARN' + try { & reg.exe unload 'HKU\DefaultUser' 1>$null 2>$null } catch { } + } + } else { + Write-Log -message "Disable-OneDriveBackupPopup :: Default NTUSER.DAT not found; skipping default profile edit" -severity 'DEBUG' + } + + try { + $userSids = @(Get-ChildItem Registry::HKEY_USERS -ErrorAction SilentlyContinue | + Where-Object { $_.PSChildName -match '^S-1-5-21-' } | + Select-Object -ExpandProperty PSChildName) + + foreach ($sid in $userSids) { + Remove-RunEntry ("HKU\{0}" -f $sid) + } + + Write-Log -message ("Disable-OneDriveBackupPopup :: Cleared OneDrive Run entries in {0} loaded user hive(s)" -f $userSids.Count) -severity 'INFO' + } catch { + Write-Log -message ("Disable-OneDriveBackupPopup :: Failed clearing loaded user hives: {0}" -f $_.Exception.Message) -severity 'WARN' + } + + Write-Log -message "Disable-OneDriveBackupPopup :: complete (recommend reboot)" -severity 'INFO' +} + function Disable-PerUserUwpServices { [CmdletBinding()] param ( @@ -398,6 +472,7 @@ switch ($os_version) { New-ItemProperty -Path 'HKCU:\Control Panel\Accessibility' -Name 'DynamicScrollbars' -Value 0 -Force Disable-PerUserUwpServices Remove-OneDriveScheduledTasks + Disable-OneDriveBackupPopup Remove-EdgeScheduledTasks } "win_2022" { From 1af45cda3444e78c9919e8316430168932585d05 Mon Sep 17 00:00:00 2001 From: Mark Cornmesser Date: Tue, 6 Jan 2026 12:49:55 -0800 Subject: [PATCH 080/105] disable one drive notification --- modules/win_scheduled_tasks/manifests/self_redeploy_check.pp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/modules/win_scheduled_tasks/manifests/self_redeploy_check.pp b/modules/win_scheduled_tasks/manifests/self_redeploy_check.pp index a4869a898..271fb5885 100644 --- a/modules/win_scheduled_tasks/manifests/self_redeploy_check.pp +++ b/modules/win_scheduled_tasks/manifests/self_redeploy_check.pp @@ -19,8 +19,8 @@ trigger => [{ schedule => 'daily', start_time => '00:00', - #minutes_interval => 120, - minutes_interval => 5, + minutes_interval => 120, + #minutes_interval => 5, #minutes_duration => 1440, # 24 hours = repeat every 2 hours all day }], user => 'SYSTEM', From 779fb1c015e351b768b6dda33c31f58a5d2b2f63 Mon Sep 17 00:00:00 2001 From: Mark Cornmesser Date: Thu, 8 Jan 2026 11:12:54 -0800 Subject: [PATCH 081/105] disable more stuff --- .../manifests/profiles/disable_services.pp | 1 + .../manifests/disable_smartscreen_shell.pp | 20 +++++++++ .../files/at_task_user_logon.ps1 | 45 +++++++++++++++++++ 3 files changed, 66 insertions(+) create mode 100644 modules/win_disable_services/manifests/disable_smartscreen_shell.pp diff --git a/modules/roles_profiles/manifests/profiles/disable_services.pp b/modules/roles_profiles/manifests/profiles/disable_services.pp index 2d6d641b7..e03d9e36b 100644 --- a/modules/roles_profiles/manifests/profiles/disable_services.pp +++ b/modules/roles_profiles/manifests/profiles/disable_services.pp @@ -44,6 +44,7 @@ ## Bug 1913499 https://bugzilla.mozilla.org/show_bug.cgi?id=1913499 include win_disable_services::uninstall_appx_packages include win_disable_services::disable_optional_services + include win_disable_services::disable_smartscreen_shell if ($facts['custom_win_location'] == 'azure') { include win_scheduled_tasks::kill_local_clipboard } diff --git a/modules/win_disable_services/manifests/disable_smartscreen_shell.pp b/modules/win_disable_services/manifests/disable_smartscreen_shell.pp new file mode 100644 index 000000000..3540be271 --- /dev/null +++ b/modules/win_disable_services/manifests/disable_smartscreen_shell.pp @@ -0,0 +1,20 @@ +# This Source Code Form is subject to the terms of the Mozilla Public +# License, v. 2.0. If a copy of the MPL was not distributed with this +# file, You can obtain one at http://mozilla.org/MPL/2.0/. + +class win_disable_services::disable_smartscreen_shell { + + registry_key { 'HKLM\SOFTWARE\Policies\Microsoft\Windows\System': + ensure => present, + } + + registry_value { 'HKLM\SOFTWARE\Policies\Microsoft\Windows\System\EnableSmartScreen': + ensure => present, + type => dword, + data => '0', + } + + registry_value { 'HKLM\SOFTWARE\Policies\Microsoft\Windows\System\ShellSmartScreenLevel': + ensure => absent, + } +} diff --git a/modules/win_scheduled_tasks/files/at_task_user_logon.ps1 b/modules/win_scheduled_tasks/files/at_task_user_logon.ps1 index e32f21712..ddfc87a14 100644 --- a/modules/win_scheduled_tasks/files/at_task_user_logon.ps1 +++ b/modules/win_scheduled_tasks/files/at_task_user_logon.ps1 @@ -420,6 +420,50 @@ function Remove-EdgeScheduledTasks { } } +function Disable-SyncFromCloud { + [CmdletBinding()] + param() + + Write-Log -message "Disable-SyncFromCloud :: begin (disable Language settings sync)" -severity 'INFO' + + # 1) Always do per-user disable (no admin required) + try { + $kUser = 'HKCU:\SOFTWARE\Microsoft\Windows\CurrentVersion\SettingSync\Groups\Language' + New-Item -Path $kUser -Force | Out-Null + New-ItemProperty -Path $kUser -Name 'Enabled' -PropertyType DWord -Value 0 -Force | Out-Null + + $val = (Get-ItemProperty -Path $kUser -Name Enabled -ErrorAction SilentlyContinue).Enabled + Write-Log -message ("Disable-SyncFromCloud :: HKCU Language sync disabled (Enabled={0})" -f $val) -severity 'INFO' + } + catch { + Write-Log -message ("Disable-SyncFromCloud :: HKCU write failed: {0}" -f $_.Exception.Message) -severity 'WARN' + } + + # 2) If elevated, also enforce via machine policy (optional hard block) + try { + $isAdmin = ([Security.Principal.WindowsPrincipal] [Security.Principal.WindowsIdentity]::GetCurrent() + ).IsInRole([Security.Principal.WindowsBuiltInRole]::Administrator) + + if ($isAdmin) { + $kPol = 'HKLM:\SOFTWARE\Policies\Microsoft\Windows\SettingSync' + New-Item -Path $kPol -Force | Out-Null + + # Common policy convention: 2 = disable + New-ItemProperty -Path $kPol -Name 'DisableLanguageSettingSync' -PropertyType DWord -Value 2 -Force | Out-Null + + $pval = (Get-ItemProperty -Path $kPol -Name DisableLanguageSettingSync -ErrorAction SilentlyContinue).DisableLanguageSettingSync + Write-Log -message ("Disable-SyncFromCloud :: HKLM policy set DisableLanguageSettingSync={0}" -f $pval) -severity 'INFO' + } + else { + Write-Log -message "Disable-SyncFromCloud :: not elevated; skipping HKLM policy enforcement" -severity 'DEBUG' + } + } + catch { + Write-Log -message ("Disable-SyncFromCloud :: HKLM policy step failed: {0}" -f $_.Exception.Message) -severity 'DEBUG' + } + + Write-Log -message "Disable-SyncFromCloud :: complete (recommend sign out/in or reboot)" -severity 'INFO' +} # Windows release ID. # From time to time we need to have the different releases of the same OS version @@ -474,6 +518,7 @@ switch ($os_version) { Remove-OneDriveScheduledTasks Disable-OneDriveBackupPopup Remove-EdgeScheduledTasks + Disable-SyncFromCloud } "win_2022" { ## Disable Server Manager Dashboard From 794891e49e6c0e8b789056835f6e74d8fbded8fa Mon Sep 17 00:00:00 2001 From: Mark Cornmesser Date: Fri, 9 Jan 2026 12:38:32 -0800 Subject: [PATCH 082/105] disable more stuff --- .../manifests/profiles/disable_services.pp | 3 +- .../manifests/disable_defender_smartscreen.pp | 47 +++++++++++++++++++ .../manifests/disable_smartscreen_shell.pp | 20 -------- .../manifests/disable_sync_from_cloud.pp | 28 +++++++++++ 4 files changed, 77 insertions(+), 21 deletions(-) create mode 100644 modules/win_disable_services/manifests/disable_defender_smartscreen.pp delete mode 100644 modules/win_disable_services/manifests/disable_smartscreen_shell.pp create mode 100644 modules/win_disable_services/manifests/disable_sync_from_cloud.pp diff --git a/modules/roles_profiles/manifests/profiles/disable_services.pp b/modules/roles_profiles/manifests/profiles/disable_services.pp index e03d9e36b..b95734a3a 100644 --- a/modules/roles_profiles/manifests/profiles/disable_services.pp +++ b/modules/roles_profiles/manifests/profiles/disable_services.pp @@ -44,7 +44,8 @@ ## Bug 1913499 https://bugzilla.mozilla.org/show_bug.cgi?id=1913499 include win_disable_services::uninstall_appx_packages include win_disable_services::disable_optional_services - include win_disable_services::disable_smartscreen_shell + include win_disable_services::disable_defender_smartscreen + include win_disable_services::disable_sync_from_cloud if ($facts['custom_win_location'] == 'azure') { include win_scheduled_tasks::kill_local_clipboard } diff --git a/modules/win_disable_services/manifests/disable_defender_smartscreen.pp b/modules/win_disable_services/manifests/disable_defender_smartscreen.pp new file mode 100644 index 000000000..f6ee5fcfb --- /dev/null +++ b/modules/win_disable_services/manifests/disable_defender_smartscreen.pp @@ -0,0 +1,47 @@ +# This Source Code Form is subject to the terms of the Mozilla Public +# License, v. 2.0. If a copy of the MPL was not distributed with this +# file, You can obtain one at http://mozilla.org/MPL/2.0/. + +class win_disable_services::disable_defender_smartscreen { + + # 1) Windows shell / Explorer SmartScreen ("Check apps and files") + # HKLM\SOFTWARE\Policies\Microsoft\Windows\System + # EnableSmartScreen (DWORD): 0=Off, 1=On + # ShellSmartScreenLevel (REG_SZ): Warn/Block when enabled + registry_key { 'HKLM\SOFTWARE\Policies\Microsoft\Windows\System': + ensure => present, + } + + registry_value { 'HKLM\SOFTWARE\Policies\Microsoft\Windows\System\EnableSmartScreen': + ensure => present, + type => dword, + data => '0', + } + + registry_value { 'HKLM\SOFTWARE\Policies\Microsoft\Windows\System\ShellSmartScreenLevel': + ensure => absent, + } + + # 2) Microsoft Edge SmartScreen + registry_key { 'HKLM\SOFTWARE\Policies\Microsoft\Edge': + ensure => present, + } + + registry_value { 'HKLM\SOFTWARE\Policies\Microsoft\Edge\SmartScreenEnabled': + ensure => present, + type => dword, + data => '0', + } + + # 3) SmartScreen for Microsoft Store apps (web content evaluation) + # (Commonly controlled via EnableWebContentEvaluation) + registry_key { 'HKLM\SOFTWARE\Microsoft\Windows\CurrentVersion\AppHost': + ensure => present, + } + + registry_value { 'HKLM\SOFTWARE\Microsoft\Windows\CurrentVersion\AppHost\EnableWebContentEvaluation': + ensure => present, + type => dword, + data => '0', + } +} diff --git a/modules/win_disable_services/manifests/disable_smartscreen_shell.pp b/modules/win_disable_services/manifests/disable_smartscreen_shell.pp deleted file mode 100644 index 3540be271..000000000 --- a/modules/win_disable_services/manifests/disable_smartscreen_shell.pp +++ /dev/null @@ -1,20 +0,0 @@ -# This Source Code Form is subject to the terms of the Mozilla Public -# License, v. 2.0. If a copy of the MPL was not distributed with this -# file, You can obtain one at http://mozilla.org/MPL/2.0/. - -class win_disable_services::disable_smartscreen_shell { - - registry_key { 'HKLM\SOFTWARE\Policies\Microsoft\Windows\System': - ensure => present, - } - - registry_value { 'HKLM\SOFTWARE\Policies\Microsoft\Windows\System\EnableSmartScreen': - ensure => present, - type => dword, - data => '0', - } - - registry_value { 'HKLM\SOFTWARE\Policies\Microsoft\Windows\System\ShellSmartScreenLevel': - ensure => absent, - } -} diff --git a/modules/win_disable_services/manifests/disable_sync_from_cloud.pp b/modules/win_disable_services/manifests/disable_sync_from_cloud.pp new file mode 100644 index 000000000..75ee23477 --- /dev/null +++ b/modules/win_disable_services/manifests/disable_sync_from_cloud.pp @@ -0,0 +1,28 @@ +# This Source Code Form is subject to the terms of the Mozilla Public +# License, v. 2.0. If a copy of the MPL was not distributed with this +# file, You can obtain one at http://mozilla.org/MPL/2.0/. + +class win_disable_services::disable_sync_from_cloud { + + # GPO: Computer Configuration > Administrative Templates > Windows Components > Sync your settings > Do not sync + # Registry: HKLM\SOFTWARE\Policies\Microsoft\Windows\SettingSync + # Effect: turns off "Remember my preferences" and none of the preferences are synced. :contentReference[oaicite:1]{index=1} + + registry_key { 'HKLM\SOFTWARE\Policies\Microsoft\Windows\SettingSync': + ensure => present, + } + + # DisableSettingSync: 2 = disable + registry_value { 'HKLM\SOFTWARE\Policies\Microsoft\Windows\SettingSync\DisableSettingSync': + ensure => present, + type => dword, + data => '2', + } + + # DisableSettingSyncUserOverride: 1 = prevent user override (keeps it off) + registry_value { 'HKLM\SOFTWARE\Policies\Microsoft\Windows\SettingSync\DisableSettingSyncUserOverride': + ensure => present, + type => dword, + data => '1', + } +} From c355a5a9d959a39394a018bcc00d1e1dac1bf042 Mon Sep 17 00:00:00 2001 From: Mark Cornmesser Date: Mon, 12 Jan 2026 09:11:54 -0800 Subject: [PATCH 083/105] disable more smart screen --- .../manifests/disable_defender_smartscreen.pp | 28 +++++++++++-------- 1 file changed, 16 insertions(+), 12 deletions(-) diff --git a/modules/win_disable_services/manifests/disable_defender_smartscreen.pp b/modules/win_disable_services/manifests/disable_defender_smartscreen.pp index f6ee5fcfb..a621787e2 100644 --- a/modules/win_disable_services/manifests/disable_defender_smartscreen.pp +++ b/modules/win_disable_services/manifests/disable_defender_smartscreen.pp @@ -4,10 +4,7 @@ class win_disable_services::disable_defender_smartscreen { - # 1) Windows shell / Explorer SmartScreen ("Check apps and files") - # HKLM\SOFTWARE\Policies\Microsoft\Windows\System - # EnableSmartScreen (DWORD): 0=Off, 1=On - # ShellSmartScreenLevel (REG_SZ): Warn/Block when enabled + ## Windows Shell / Explorer SmartScreen ("Check apps and files") POLICY registry_key { 'HKLM\SOFTWARE\Policies\Microsoft\Windows\System': ensure => present, } @@ -22,7 +19,19 @@ ensure => absent, } - # 2) Microsoft Edge SmartScreen + ## Explorer non-policy setting (per NinjaOne) + registry_key { 'HKLM\SOFTWARE\Microsoft\Windows\CurrentVersion\Explorer': + ensure => present, + } + + ## Values: "Off", "Warn", "RequireAdmin" + registry_value { 'HKLM\SOFTWARE\Microsoft\Windows\CurrentVersion\Explorer\SmartScreenEnabled': + ensure => present, + type => string, + data => 'Off', + } + + ## Microsoft Edge SmartScreen (Edge policy registry path) registry_key { 'HKLM\SOFTWARE\Policies\Microsoft\Edge': ensure => present, } @@ -33,13 +42,8 @@ data => '0', } - # 3) SmartScreen for Microsoft Store apps (web content evaluation) - # (Commonly controlled via EnableWebContentEvaluation) - registry_key { 'HKLM\SOFTWARE\Microsoft\Windows\CurrentVersion\AppHost': - ensure => present, - } - - registry_value { 'HKLM\SOFTWARE\Microsoft\Windows\CurrentVersion\AppHost\EnableWebContentEvaluation': + ## disable Edge PUA reputation as well + registry_value { 'HKLM\SOFTWARE\Policies\Microsoft\Edge\SmartScreenPuaEnabled': ensure => present, type => dword, data => '0', From e6493262045ffec2cea018702e9c49bfc7b84400 Mon Sep 17 00:00:00 2001 From: Mark Cornmesser Date: Mon, 12 Jan 2026 15:49:41 -0800 Subject: [PATCH 084/105] disable more smart screen --- .../manifests/disable_defender_smartscreen.pp | 19 +++++++++---------- 1 file changed, 9 insertions(+), 10 deletions(-) diff --git a/modules/win_disable_services/manifests/disable_defender_smartscreen.pp b/modules/win_disable_services/manifests/disable_defender_smartscreen.pp index a621787e2..c21bfe933 100644 --- a/modules/win_disable_services/manifests/disable_defender_smartscreen.pp +++ b/modules/win_disable_services/manifests/disable_defender_smartscreen.pp @@ -1,10 +1,6 @@ -# This Source Code Form is subject to the terms of the Mozilla Public -# License, v. 2.0. If a copy of the MPL was not distributed with this -# file, You can obtain one at http://mozilla.org/MPL/2.0/. - class win_disable_services::disable_defender_smartscreen { - ## Windows Shell / Explorer SmartScreen ("Check apps and files") POLICY + ## 1) Shell/Explorer SmartScreen (policy) registry_key { 'HKLM\SOFTWARE\Policies\Microsoft\Windows\System': ensure => present, } @@ -19,19 +15,18 @@ ensure => absent, } - ## Explorer non-policy setting (per NinjaOne) + ## 2) Explorer non-policy setting (per NinjaOne) registry_key { 'HKLM\SOFTWARE\Microsoft\Windows\CurrentVersion\Explorer': ensure => present, } - ## Values: "Off", "Warn", "RequireAdmin" registry_value { 'HKLM\SOFTWARE\Microsoft\Windows\CurrentVersion\Explorer\SmartScreenEnabled': ensure => present, type => string, data => 'Off', } - ## Microsoft Edge SmartScreen (Edge policy registry path) + ## 3) Edge SmartScreen (official Edge policy) registry_key { 'HKLM\SOFTWARE\Policies\Microsoft\Edge': ensure => present, } @@ -42,8 +37,12 @@ data => '0', } - ## disable Edge PUA reputation as well - registry_value { 'HKLM\SOFTWARE\Policies\Microsoft\Edge\SmartScreenPuaEnabled': + ## 4) Store apps / AppHost web content evaluation + registry_key { 'HKLM\SOFTWARE\Microsoft\Windows\CurrentVersion\AppHost': + ensure => present, + } + + registry_value { 'HKLM\SOFTWARE\Microsoft\Windows\CurrentVersion\AppHost\EnableWebContentEvaluation': ensure => present, type => dword, data => '0', From a1ff48a5df2dcdd08f7627dd504b8311785f936d Mon Sep 17 00:00:00 2001 From: Mark Cornmesser Date: Tue, 13 Jan 2026 10:23:31 -0800 Subject: [PATCH 085/105] disable more smart screen --- .../files/at_task_user_logon.ps1 | 53 +++++++++++++++++++ 1 file changed, 53 insertions(+) diff --git a/modules/win_scheduled_tasks/files/at_task_user_logon.ps1 b/modules/win_scheduled_tasks/files/at_task_user_logon.ps1 index ddfc87a14..9d272e150 100644 --- a/modules/win_scheduled_tasks/files/at_task_user_logon.ps1 +++ b/modules/win_scheduled_tasks/files/at_task_user_logon.ps1 @@ -465,6 +465,58 @@ function Disable-SyncFromCloud { Write-Log -message "Disable-SyncFromCloud :: complete (recommend sign out/in or reboot)" -severity 'INFO' } +function Disable-SmartScreenStoreApps { + [CmdletBinding()] + param() + + Write-Log -message "Disable-SmartScreenStoreApps :: begin (disable SmartScreen for Microsoft Store apps)" -severity 'INFO' + + # 1) Always do per-user disable (no admin required) + try { + $kUser = 'HKCU:\Software\Microsoft\Windows\CurrentVersion\AppHost' + New-Item -Path $kUser -Force | Out-Null + + # Disable SmartScreen for Microsoft Store apps + New-ItemProperty -Path $kUser -Name 'EnableWebContentEvaluation' -PropertyType DWord -Value 0 -Force | Out-Null + + # Optional: allow override in UI (PreventOverride=0 means user can change it) + New-ItemProperty -Path $kUser -Name 'PreventOverride' -PropertyType DWord -Value 0 -Force | Out-Null + + $valEnable = (Get-ItemProperty -Path $kUser -Name EnableWebContentEvaluation -ErrorAction SilentlyContinue).EnableWebContentEvaluation + $valOverride = (Get-ItemProperty -Path $kUser -Name PreventOverride -ErrorAction SilentlyContinue).PreventOverride + + Write-Log -message ("Disable-SmartScreenStoreApps :: HKCU Store app SmartScreen disabled (EnableWebContentEvaluation={0}, PreventOverride={1})" -f $valEnable, $valOverride) -severity 'INFO' + } + catch { + Write-Log -message ("Disable-SmartScreenStoreApps :: HKCU write failed: {0}" -f $_.Exception.Message) -severity 'WARN' + } + + # 2) If elevated, also set machine-wide (optional; affects all users) + try { + $isAdmin = ([Security.Principal.WindowsPrincipal] [Security.Principal.WindowsIdentity]::GetCurrent() + ).IsInRole([Security.Principal.WindowsBuiltInRole]::Administrator) + + if ($isAdmin) { + $kMachine = 'HKLM:\SOFTWARE\Microsoft\Windows\CurrentVersion\AppHost' + New-Item -Path $kMachine -Force | Out-Null + + New-ItemProperty -Path $kMachine -Name 'EnableWebContentEvaluation' -PropertyType DWord -Value 0 -Force | Out-Null + + $mValEnable = (Get-ItemProperty -Path $kMachine -Name EnableWebContentEvaluation -ErrorAction SilentlyContinue).EnableWebContentEvaluation + Write-Log -message ("Disable-SmartScreenStoreApps :: HKLM Store app SmartScreen disabled (EnableWebContentEvaluation={0})" -f $mValEnable) -severity 'INFO' + } + else { + Write-Log -message "Disable-SmartScreenStoreApps :: not elevated; skipping HKLM machine-wide setting" -severity 'DEBUG' + } + } + catch { + Write-Log -message ("Disable-SmartScreenStoreApps :: HKLM step failed: {0}" -f $_.Exception.Message) -severity 'DEBUG' + } + + Write-Log -message "Disable-SmartScreenStoreApps :: complete (recommend sign out/in or restart Store apps)" -severity 'INFO' +} + + # Windows release ID. # From time to time we need to have the different releases of the same OS version $release_key = (Get-ItemProperty -Path 'HKLM:\SOFTWARE\Microsoft\Windows NT\CurrentVersion') @@ -519,6 +571,7 @@ switch ($os_version) { Disable-OneDriveBackupPopup Remove-EdgeScheduledTasks Disable-SyncFromCloud + Disable-SmartScreenStoreApps } "win_2022" { ## Disable Server Manager Dashboard From 6e298883449f11852f3e34530b687697da03e0bb Mon Sep 17 00:00:00 2001 From: Mark Cornmesser Date: Tue, 13 Jan 2026 12:08:27 -0800 Subject: [PATCH 086/105] disable more smart screen --- modules/win_scheduled_tasks/manifests/at_task_user_logon.pp | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/modules/win_scheduled_tasks/manifests/at_task_user_logon.pp b/modules/win_scheduled_tasks/manifests/at_task_user_logon.pp index 285be7e99..e178483fe 100644 --- a/modules/win_scheduled_tasks/manifests/at_task_user_logon.pp +++ b/modules/win_scheduled_tasks/manifests/at_task_user_logon.pp @@ -16,9 +16,7 @@ arguments => "-executionpolicy bypass -File ${at_task_user_logon_ps}", enabled => true, trigger => [{ - 'schedule' => 'boot', - 'minutes_interval' => '0', - 'minutes_duration' => '0' + 'schedule' => 'logon', }], user => 'system', } From 1d820385bb6a1589f88a1b08d767f250302b082f Mon Sep 17 00:00:00 2001 From: Mark Cornmesser Date: Tue, 13 Jan 2026 13:25:40 -0800 Subject: [PATCH 087/105] disable more smart screen --- modules/win_scheduled_tasks/manifests/at_task_user_logon.pp | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/modules/win_scheduled_tasks/manifests/at_task_user_logon.pp b/modules/win_scheduled_tasks/manifests/at_task_user_logon.pp index e178483fe..285be7e99 100644 --- a/modules/win_scheduled_tasks/manifests/at_task_user_logon.pp +++ b/modules/win_scheduled_tasks/manifests/at_task_user_logon.pp @@ -16,7 +16,9 @@ arguments => "-executionpolicy bypass -File ${at_task_user_logon_ps}", enabled => true, trigger => [{ - 'schedule' => 'logon', + 'schedule' => 'boot', + 'minutes_interval' => '0', + 'minutes_duration' => '0' }], user => 'system', } From fafdba84b7f47aec3ceb2bf3f9640e4aa5911d41 Mon Sep 17 00:00:00 2001 From: Mark Cornmesser Date: Tue, 13 Jan 2026 14:53:18 -0800 Subject: [PATCH 088/105] disable more smart screen --- .../files/at_task_user_logon.ps1 | 36 +++++++++++++++---- 1 file changed, 29 insertions(+), 7 deletions(-) diff --git a/modules/win_scheduled_tasks/files/at_task_user_logon.ps1 b/modules/win_scheduled_tasks/files/at_task_user_logon.ps1 index 9d272e150..fb1f69325 100644 --- a/modules/win_scheduled_tasks/files/at_task_user_logon.ps1 +++ b/modules/win_scheduled_tasks/files/at_task_user_logon.ps1 @@ -471,9 +471,22 @@ function Disable-SmartScreenStoreApps { Write-Log -message "Disable-SmartScreenStoreApps :: begin (disable SmartScreen for Microsoft Store apps)" -severity 'INFO' + # Helper: normalize raw registry root strings to a PowerShell registry provider path + function Convert-ToRegistryProviderPath { + param([Parameter(Mandatory)][string]$Path) + + switch -Regex ($Path) { + '^HKLM:\\' { return $Path } + '^HKCU:\\' { return $Path } + '^HKEY_LOCAL_MACHINE\\' { return "Registry::$Path" } + '^HKEY_CURRENT_USER\\' { return "Registry::$Path" } + default { return $Path } + } + } + # 1) Always do per-user disable (no admin required) try { - $kUser = 'HKCU:\Software\Microsoft\Windows\CurrentVersion\AppHost' + $kUser = Convert-ToRegistryProviderPath 'HKCU:\Software\Microsoft\Windows\CurrentVersion\AppHost' New-Item -Path $kUser -Force | Out-Null # Disable SmartScreen for Microsoft Store apps @@ -482,13 +495,13 @@ function Disable-SmartScreenStoreApps { # Optional: allow override in UI (PreventOverride=0 means user can change it) New-ItemProperty -Path $kUser -Name 'PreventOverride' -PropertyType DWord -Value 0 -Force | Out-Null - $valEnable = (Get-ItemProperty -Path $kUser -Name EnableWebContentEvaluation -ErrorAction SilentlyContinue).EnableWebContentEvaluation - $valOverride = (Get-ItemProperty -Path $kUser -Name PreventOverride -ErrorAction SilentlyContinue).PreventOverride + $valEnable = (Get-ItemProperty -Path $kUser -Name EnableWebContentEvaluation -ErrorAction SilentlyContinue).EnableWebContentEvaluation + $valOverride = (Get-ItemProperty -Path $kUser -Name PreventOverride -ErrorAction SilentlyContinue).PreventOverride Write-Log -message ("Disable-SmartScreenStoreApps :: HKCU Store app SmartScreen disabled (EnableWebContentEvaluation={0}, PreventOverride={1})" -f $valEnable, $valOverride) -severity 'INFO' } catch { - Write-Log -message ("Disable-SmartScreenStoreApps :: HKCU write failed: {0}" -f $_.Exception.Message) -severity 'WARN' + Write-Log -message ("Disable-SmartScreenStoreApps :: HKCU step failed (path='{0}'): {1}" -f $kUser, $_.Exception.Message) -severity 'WARN' } # 2) If elevated, also set machine-wide (optional; affects all users) @@ -497,9 +510,18 @@ function Disable-SmartScreenStoreApps { ).IsInRole([Security.Principal.WindowsBuiltInRole]::Administrator) if ($isAdmin) { - $kMachine = 'HKLM:\SOFTWARE\Microsoft\Windows\CurrentVersion\AppHost' - New-Item -Path $kMachine -Force | Out-Null + # Ensure HKLM: drive exists (rare edge-case; makes the function more robust) + if (-not (Get-PSDrive -Name HKLM -ErrorAction SilentlyContinue)) { + New-PSDrive -Name HKLM -PSProvider Registry -Root HKEY_LOCAL_MACHINE | Out-Null + } + + $kMachine = Convert-ToRegistryProviderPath 'HKLM:\SOFTWARE\Microsoft\Windows\CurrentVersion\AppHost' + + # Debug breadcrumbs in case something upstream mutates the path + Write-Log -message ("Disable-SmartScreenStoreApps :: DEBUG kMachine='{0}'" -f $kMachine) -severity 'DEBUG' + + New-Item -Path $kMachine -Force | Out-Null New-ItemProperty -Path $kMachine -Name 'EnableWebContentEvaluation' -PropertyType DWord -Value 0 -Force | Out-Null $mValEnable = (Get-ItemProperty -Path $kMachine -Name EnableWebContentEvaluation -ErrorAction SilentlyContinue).EnableWebContentEvaluation @@ -510,7 +532,7 @@ function Disable-SmartScreenStoreApps { } } catch { - Write-Log -message ("Disable-SmartScreenStoreApps :: HKLM step failed: {0}" -f $_.Exception.Message) -severity 'DEBUG' + Write-Log -message ("Disable-SmartScreenStoreApps :: HKLM step failed (path='{0}'): {1}" -f $kMachine, $_.Exception.Message) -severity 'DEBUG' } Write-Log -message "Disable-SmartScreenStoreApps :: complete (recommend sign out/in or restart Store apps)" -severity 'INFO' From 3c0c059294faa92f935a63263081109611afb1a9 Mon Sep 17 00:00:00 2001 From: Mark Cornmesser Date: Wed, 14 Jan 2026 14:01:37 -0800 Subject: [PATCH 089/105] address conflict --- data/os/Windows.yaml | 1 + .../manifests/profiles/windows_generic_worker_standalone.pp | 2 +- 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/data/os/Windows.yaml b/data/os/Windows.yaml index 0c1b80723..d9999b7e8 100644 --- a/data/os/Windows.yaml +++ b/data/os/Windows.yaml @@ -56,6 +56,7 @@ windows: relops_s3: "https://s3-us-west-2.amazonaws.com/ronin-puppet-package-repo/Windows/taskcluster" download_url: "https://github.com/taskcluster/taskcluster/releases/download" version: "95.1.1" + hw_version: "93.1.4" generic-worker: name: amd64: "generic-worker-multiuser-windows-amd64" diff --git a/modules/roles_profiles/manifests/profiles/windows_generic_worker_standalone.pp b/modules/roles_profiles/manifests/profiles/windows_generic_worker_standalone.pp index 0b58360a8..8ffda6ebb 100644 --- a/modules/roles_profiles/manifests/profiles/windows_generic_worker_standalone.pp +++ b/modules/roles_profiles/manifests/profiles/windows_generic_worker_standalone.pp @@ -15,7 +15,7 @@ $gw_exe_path = "${generic_worker_dir}\\generic-worker.exe" $gw_name = lookup('windows.taskcluster.generic-worker.name.amd64') $taskcluster_version = - lookup(['win-worker.variant.taskcluster.version', 'windows.taskcluster.version']) + lookup(['win-worker.variant.taskcluster.version', 'windows.taskcluster.hw_version']) $worker_pool_id = $facts['custom_win_worker_pool_id'] $gw_config_path = "${generic_worker_dir}\\generic-worker.config" $proxy_name = lookup('windows.taskcluster.proxy.name.amd64') From bf8b8acef8d4e71c63d2380a56d1eb4c59693070 Mon Sep 17 00:00:00 2001 From: Mark Cornmesser Date: Wed, 14 Jan 2026 09:27:06 -0800 Subject: [PATCH 090/105] update gw ver value --- .../manifests/profiles/windows_worker_runner.pp | 14 ++++++++++---- 1 file changed, 10 insertions(+), 4 deletions(-) diff --git a/modules/roles_profiles/manifests/profiles/windows_worker_runner.pp b/modules/roles_profiles/manifests/profiles/windows_worker_runner.pp index 045b8fe1d..e74282de2 100644 --- a/modules/roles_profiles/manifests/profiles/windows_worker_runner.pp +++ b/modules/roles_profiles/manifests/profiles/windows_worker_runner.pp @@ -21,10 +21,16 @@ $provider = lookup('windows.taskcluster.worker_runner.provider') } } - - $taskcluster_version = - lookup(['win-worker.variant.taskcluster.version', 'windows.taskcluster.version']) - + case $facts['custom_win_location'] { + 'datacenter': { + $taskcluster_version = + lookup(['win-worker.variant.taskcluster.version', 'windows.taskcluster.hw_version']) + } + default: { + $taskcluster_version = + lookup(['win-worker.variant.taskcluster.version', 'windows.taskcluster.version']) + } + } case $facts['custom_win_os_arch'] { 'aarch64': { $gw_name = lookup('windows.taskcluster.generic-worker.name.arm64') From 9ef6fc57c64a02bb1b2e8d49025ea3c393e82772 Mon Sep 17 00:00:00 2001 From: Mark Cornmesser Date: Wed, 14 Jan 2026 13:44:06 -0800 Subject: [PATCH 091/105] clean up --- .../manifests/profiles/disable_services.pp | 6 +- .../windows_generic_worker_standalone.pp | 2 +- .../profiles/windows_worker_runner.pp | 2 - .../roles/win116424h2hwrelops1213.pp | 2 +- .../files/appxpackages/2BAKuninstall.ps1 | 246 ------------------ .../{BAKuninstall.ps1 => uninstall.ps1.BAK} | 0 6 files changed, 6 insertions(+), 252 deletions(-) delete mode 100644 modules/win_disable_services/files/appxpackages/2BAKuninstall.ps1 rename modules/win_disable_services/files/appxpackages/{BAKuninstall.ps1 => uninstall.ps1.BAK} (100%) diff --git a/modules/roles_profiles/manifests/profiles/disable_services.pp b/modules/roles_profiles/manifests/profiles/disable_services.pp index b95734a3a..d043aaf6d 100644 --- a/modules/roles_profiles/manifests/profiles/disable_services.pp +++ b/modules/roles_profiles/manifests/profiles/disable_services.pp @@ -44,8 +44,10 @@ ## Bug 1913499 https://bugzilla.mozilla.org/show_bug.cgi?id=1913499 include win_disable_services::uninstall_appx_packages include win_disable_services::disable_optional_services - include win_disable_services::disable_defender_smartscreen - include win_disable_services::disable_sync_from_cloud + ## WIP for RELOPS-1946 + ## Not currently working. Leaving place for ref. + #include win_disable_services::disable_defender_smartscreen + #include win_disable_services::disable_sync_from_cloud if ($facts['custom_win_location'] == 'azure') { include win_scheduled_tasks::kill_local_clipboard } diff --git a/modules/roles_profiles/manifests/profiles/windows_generic_worker_standalone.pp b/modules/roles_profiles/manifests/profiles/windows_generic_worker_standalone.pp index 8ffda6ebb..0b58360a8 100644 --- a/modules/roles_profiles/manifests/profiles/windows_generic_worker_standalone.pp +++ b/modules/roles_profiles/manifests/profiles/windows_generic_worker_standalone.pp @@ -15,7 +15,7 @@ $gw_exe_path = "${generic_worker_dir}\\generic-worker.exe" $gw_name = lookup('windows.taskcluster.generic-worker.name.amd64') $taskcluster_version = - lookup(['win-worker.variant.taskcluster.version', 'windows.taskcluster.hw_version']) + lookup(['win-worker.variant.taskcluster.version', 'windows.taskcluster.version']) $worker_pool_id = $facts['custom_win_worker_pool_id'] $gw_config_path = "${generic_worker_dir}\\generic-worker.config" $proxy_name = lookup('windows.taskcluster.proxy.name.amd64') diff --git a/modules/roles_profiles/manifests/profiles/windows_worker_runner.pp b/modules/roles_profiles/manifests/profiles/windows_worker_runner.pp index e74282de2..76a3d4fb2 100644 --- a/modules/roles_profiles/manifests/profiles/windows_worker_runner.pp +++ b/modules/roles_profiles/manifests/profiles/windows_worker_runner.pp @@ -15,9 +15,7 @@ $provider = 'standalone' } default: { - #$ext_pkg_src_loc = lookup('windows.taskcluster.relops_az') $ext_pkg_src_loc = "${lookup('windows.taskcluster.download_url')}/v" - #$ext_pkg_src_loc = "https://github.com/taskcluster/taskcluster/releases/download/v93.1.4/generic-worker-multiuser-windows-arm64" $provider = lookup('windows.taskcluster.worker_runner.provider') } } diff --git a/modules/roles_profiles/manifests/roles/win116424h2hwrelops1213.pp b/modules/roles_profiles/manifests/roles/win116424h2hwrelops1213.pp index f153a6c6f..9e876d4a8 100644 --- a/modules/roles_profiles/manifests/roles/win116424h2hwrelops1213.pp +++ b/modules/roles_profiles/manifests/roles/win116424h2hwrelops1213.pp @@ -1,6 +1,6 @@ class roles_profiles::roles::win116424h2hwrelops1213 { include roles_profiles::profiles::chocolatey - ## Install before Widnows Updates is disabled. + # Install before Widnows Updates is disabled. include roles_profiles::profiles::microsoft_tools include roles_profiles::profiles::ssh # System diff --git a/modules/win_disable_services/files/appxpackages/2BAKuninstall.ps1 b/modules/win_disable_services/files/appxpackages/2BAKuninstall.ps1 deleted file mode 100644 index b5a3a405c..000000000 --- a/modules/win_disable_services/files/appxpackages/2BAKuninstall.ps1 +++ /dev/null @@ -1,246 +0,0 @@ -function Write-Log { - param ( - [string] $message, - [string] $severity = 'INFO', - [string] $source = 'BootStrap', - [string] $logName = 'Application' - ) - - if (!([Diagnostics.EventLog]::Exists($logName)) -or - !([Diagnostics.EventLog]::SourceExists($source))) { - New-EventLog -LogName $logName -Source $source - } - - switch ($severity) { - 'DEBUG' { $entryType = 'SuccessAudit'; $eventId = 2; break } - 'WARN' { $entryType = 'Warning'; $eventId = 3; break } - 'ERROR' { $entryType = 'Error'; $eventId = 4; break } - default { $entryType = 'Information'; $eventId = 1; break } - } - - Write-EventLog -LogName $logName -Source $source ` - -EntryType $entryType -Category 0 -EventID $eventId ` - -Message $message - - if ([Environment]::UserInteractive) { - $fc = @{ - 'Information' = 'White' - 'Error' = 'Red' - 'Warning' = 'DarkYellow' - 'SuccessAudit'= 'DarkGray' - }[$entryType] - Write-Host $message -ForegroundColor $fc - } -} - -# IMPORTANT: use 'Continue' so normal AppX noise doesn't hard-fail Puppet -$ErrorActionPreference = 'Continue' - -$svcName = 'AppXSvc' -$svcKeyPath = 'HKLM:\SYSTEM\CurrentControlSet\Services\AppXSvc' - -function Remove-PreinstalledAppxPackages { - [CmdletBinding()] - param() - - $apps = @{ - "Bing Search" = @{ VDIState="Unchanged"; URL="https://apps.microsoft.com/detail/9nzbf4gt040c"; Description="Web Search from Microsoft Bing provides web results and answers in Windows Search" } - "Clipchamp.Clipchamp" = @{ VDIState="Unchanged"; URL="https://apps.microsoft.com/detail/9p1j8s7ccwwt?hl=en-us&gl=US"; Description="Create videos with a few clicks" } - "Microsoft.549981C3F5F10" = @{ VDIState="Unchanged"; URL="https://apps.microsoft.com/detail/cortana/9NFFX4SZZ23L?hl=en-us&gl=US"; Description="Cortana (could not update)" } - "Microsoft.BingNews" = @{ VDIState="Unchanged"; URL="https://www.microsoft.com/en-us/p/microsoft-news/9wzdncrfhvfw"; Description="Microsoft News app" } - "Microsoft.BingWeather" = @{ VDIState="Unchanged"; URL="https://www.microsoft.com/en-us/p/msn-weather/9wzdncrfj3q2"; Description="MSN Weather app" } - "Microsoft.DesktopAppInstaller" = @{ VDIState="Unchanged"; URL="https://apps.microsoft.com/detail/9NBLGGH4NNS1"; Description="Microsoft App Installer for Windows 10 makes sideloading Windows apps easy" } - "Microsoft.GetHelp" = @{ VDIState="Unchanged"; URL="https://docs.microsoft.com/en-us/windows-hardware/customize/desktop/customize-get-help-app"; Description="App that facilitates free support for Microsoft products" } - "Microsoft.Getstarted" = @{ VDIState="Unchanged"; URL="https://www.microsoft.com/en-us/p/microsoft-tips/9wzdncrdtbjj"; Description="Windows 10 tips app" } - "Microsoft.MicrosoftOfficeHub" = @{ VDIState="Unchanged"; URL="https://www.microsoft.com/en-us/p/office/9wzdncrd29v9"; Description="Office UWP app suite" } - "Microsoft.Office.OneNote" = @{ VDIState="Unchanged"; URL="https://www.microsoft.com/en-us/p/onenote-for-windows-10/9wzdncrfhvjl"; Description="Office UWP OneNote app" } - "Microsoft.MicrosoftSolitaireCollection" = @{ VDIState="Unchanged"; URL="https://www.microsoft.com/en-us/p/microsoft-solitaire-collection/9wzdncrfhwd2"; Description="Solitaire suite of games" } - "Microsoft.MicrosoftStickyNotes" = @{ VDIState="Unchanged"; URL="https://www.microsoft.com/en-us/p/microsoft-sticky-notes/9nblggh4qghw"; Description="Note-taking app" } - "Microsoft.OutlookForWindows" = @{ VDIState="Unchanged"; URL="https://apps.microsoft.com/detail/9NRX63209R7B?hl=en-us&gl=US"; Description="New Outlook app" } - "Microsoft.MSPaint" = @{ VDIState="Unchanged"; URL="https://apps.microsoft.com/store/detail/paint-3d/9NBLGGH5FV99"; Description="Paint 3D app" } - "Microsoft.Paint" = @{ VDIState="Unchanged"; URL="https://apps.microsoft.com/detail/9PCFS5B6T72H"; Description="Classic Paint app" } - "Microsoft.People" = @{ VDIState="Unchanged"; URL="https://www.microsoft.com/en-us/p/microsoft-people/9nblggh10pg8"; Description="Contact management app" } - "Microsoft.PowerAutomateDesktop" = @{ VDIState="Unchanged"; URL="https://flow.microsoft.com/en-us/desktop/"; Description="Power Automate Desktop" } - "Microsoft.ScreenSketch" = @{ VDIState="Unchanged"; URL="https://www.microsoft.com/en-us/p/snip-sketch/9mz95kl8mr0l"; Description="Snip and Sketch app" } - "Microsoft.SkypeApp" = @{ VDIState="Unchanged"; URL="https://www.microsoft.com/en-us/p/skype/9wzdncrfj364"; Description="Skype app" } - "Microsoft.StorePurchaseApp" = @{ VDIState="Unchanged"; URL=""; Description="Store purchase app helper" } - "Microsoft.Todos" = @{ VDIState="Unchanged"; URL="https://www.microsoft.com/en-us/p/microsoft-to-do-lists-tasks-reminders/9nblggh5r558"; Description="Microsoft To Do" } - "Microsoft.WinDbg.Fast" = @{ VDIState="Unchanged"; URL="https://apps.microsoft.com/detail/9PGJGD53TN86?hl=en-us&gl=US"; Description="WinDbg" } - "Microsoft.Windows.DevHome" = @{ VDIState="Unchanged"; URL="https://learn.microsoft.com/en-us/windows/dev-home/"; Description="Dev Home dashboard" } - "Microsoft.Windows.Photos" = @{ VDIState="Unchanged"; URL="https://www.microsoft.com/en-us/p/microsoft-photos/9wzdncrfjbh4"; Description="Photos app" } - "Microsoft.WindowsAlarms" = @{ VDIState="Unchanged"; URL="https://www.microsoft.com/en-us/p/windows-alarms-clock/9wzdncrfj3pr"; Description="Alarms & Clock" } - "Microsoft.WindowsCalculator" = @{ VDIState="Unchanged"; URL="https://www.microsoft.com/en-us/p/windows-calculator/9wzdncrfhvn5"; Description="Calculator" } - "Microsoft.WindowsCamera" = @{ VDIState="Unchanged"; URL="https://www.microsoft.com/en-us/p/windows-camera/9wzdncrfjbbg"; Description="Camera" } - "microsoft.windowscommunicationsapps" = @{ VDIState="Unchanged"; URL="https://www.microsoft.com/en-us/p/mail-and-calendar/9wzdncrfhvqm"; Description="Mail & Calendar" } - "Microsoft.WindowsFeedbackHub" = @{ VDIState="Unchanged"; URL="https://www.microsoft.com/en-us/p/feedback-hub/9nblggh4r32n"; Description="Feedback Hub" } - "Microsoft.WindowsMaps" = @{ VDIState="Unchanged"; URL="https://www.microsoft.com/en-us/p/windows-maps/9wzdncrdtbvb"; Description="Maps" } - "Microsoft.WindowsNotepad" = @{ VDIState="Unchanged"; URL="https://www.microsoft.com/en-us/p/windows-notepad/9msmlrh6lzf3"; Description="Notepad (Store)" } - "Microsoft.WindowsStore" = @{ VDIState="Unchanged"; URL="https://blogs.windows.com/windowsexperience/2021/06/24/building-a-new-open-microsoft-store-on-windows-11/"; Description="Microsoft Store" } - "Microsoft.WindowsSoundRecorder" = @{ VDIState="Unchanged"; URL="https://www.microsoft.com/en-us/p/windows-voice-recorder/9wzdncrfhwkn"; Description="Voice Recorder" } - "Microsoft.WindowsTerminal" = @{ VDIState="Unchanged"; URL="https://www.microsoft.com/en-us/p/windows-terminal/9n0dx20hk701"; Description="Windows Terminal" } - "Microsoft.Winget.Platform.Source"= @{ VDIState="Unchanged"; URL="https://learn.microsoft.com/en-us/windows/package-manager/winget/"; Description="Winget source" } - "Microsoft.Xbox.TCUI" = @{ VDIState="Unchanged"; URL="https://docs.microsoft.com/en-us/gaming/xbox-live/features/general/tcui/live-tcui-overview"; Description="Xbox TCUI" } - "Microsoft.XboxIdentityProvider" = @{ VDIState="Unchanged"; URL="https://www.microsoft.com/en-us/p/xbox-identity-provider/9wzdncrd1hkw"; Description="Xbox Identity Provider" } - "Microsoft.XboxSpeechToTextOverlay" = @{ VDIState="Unchanged"; URL="https://support.xbox.com/help/account-profile/accessibility/use-game-chat-transcription"; Description="Xbox chat transcription" } - "Microsoft.YourPhone" = @{ VDIState="Unchanged"; URL="https://www.microsoft.com/en-us/p/Your-phone/9nmpj99vjbwv"; Description="Phone Link" } - "Microsoft.ZuneMusic" = @{ VDIState="Unchanged"; URL="https://www.microsoft.com/en-us/p/groove-music/9wzdncrfj3pt"; Description="Groove Music" } - "Microsoft.ZuneVideo" = @{ VDIState="Unchanged"; URL="https://www.microsoft.com/en-us/p/movies-tv/9wzdncrfj3p2"; Description="Movies & TV" } - "MicrosoftCorporationII.QuickAssist" = @{ VDIState="Unchanged"; URL="https://apps.microsoft.com/detail/9P7BP5VNWKX5?hl=en-us&gl=US"; Description="Quick Assist" } - "MicrosoftWindows.Client.WebExperience" = @{ VDIState="Unchanged"; URL=""; Description="Windows 11 Web Experience" } - "Microsoft.XboxApp" = @{ VDIState="Unchanged"; URL="https://www.microsoft.com/store/apps/9wzdncrfjbd8"; Description="Xbox Console Companion" } - "Microsoft.MixedReality.Portal" = @{ VDIState="Unchanged"; URL="https://www.microsoft.com/en-us/p/mixed-reality-portal/9ng1h8b3zc7m"; Description="Mixed Reality Portal" } - "Microsoft.Microsoft3DViewer" = @{ VDIState="Unchanged"; URL="https://www.microsoft.com/en-us/p/3d-viewer/9nblggh42ths"; Description="3D Viewer" } - "MicrosoftTeams" = @{ VDIState="Unchanged"; URL="https://apps.microsoft.com/detail/xp8bt8dw290mpq"; Description="Microsoft Teams" } - "MSTeams" = @{ VDIState="Unchanged"; URL="https://apps.microsoft.com/detail/xp8bt8dw290mpq"; Description="Microsoft Teams (alt id)" } - "Microsoft.OneDriveSync" = @{ VDIState="Unchanged"; URL="https://docs.microsoft.com/en-us/onedrive/one-drive-sync"; Description="OneDrive sync app" } - "Microsoft.Wallet" = @{ VDIState="Unchanged"; URL="https://www.microsoft.com/en-us/payments"; Description="Microsoft Pay" } - } - - foreach ($Key in $apps.Keys) { - $null = $apps[$Key] # keep, in case you add logging later - - Get-AppxProvisionedPackage -Online | - Where-Object { $_.PackageName -like ("*{0}*" -f $Key) } | - Remove-AppxProvisionedPackage -Online -ErrorAction SilentlyContinue | - Out-Null - - Get-AppxPackage -AllUsers -Name ("*{0}*" -f $Key) | - Remove-AppxPackage -AllUsers -ErrorAction SilentlyContinue | - Out-Null - - Get-AppxPackage -Name ("*{0}*" -f $Key) | - Remove-AppxPackage -ErrorAction SilentlyContinue | - Out-Null - } - - $paths = @( - "$env:SystemRoot\System32\OneDriveSetup.exe", - "$env:SystemRoot\SysWOW64\OneDriveSetup.exe" - ) - - foreach ($p in $paths) { - if (Test-Path $p) { - Start-Process $p -ArgumentList '/uninstall' -Wait -NoNewWindow - } - } -} - -function Disable-AppXSvcCore { - [CmdletBinding()] - param() - - $svc = Get-Service -Name $svcName -ErrorAction SilentlyContinue - if ($null -ne $svc) { - if ($svc.Status -ne 'Stopped') { - Stop-Service -Name $svcName -Force -ErrorAction SilentlyContinue - } - Set-Service -Name $svcName -StartupType Disabled -ErrorAction SilentlyContinue - } - - if (Test-Path $svcKeyPath) { - New-ItemProperty -Path $svcKeyPath -Name Start -Value 4 -PropertyType DWord -Force | Out-Null - } - - # Best-effort: give it a moment to stop (can be sticky during provisioning) - for ($i=0; $i -lt 10; $i++) { - $s = Get-Service -Name $svcName -ErrorAction SilentlyContinue - if ($null -eq $s -or $s.Status -eq 'Stopped') { break } - Start-Sleep -Seconds 1 - } -} - -function Ensure-AppXSvcHardeningTask { - [CmdletBinding()] - param() - - $hardeningDir = 'C:\ProgramData\AppXLock' - $hardeningFile = Join-Path $hardeningDir 'Disable-AppXSvc.ps1' - - if (-not (Test-Path $hardeningDir)) { - New-Item -ItemType Directory -Path $hardeningDir -Force | Out-Null - } - - $hardeningScript = @' -param() - -$ErrorActionPreference = "SilentlyContinue" - -$svcName = "AppXSvc" -$svcKeyPath = "HKLM:\\SYSTEM\\CurrentControlSet\\Services\\AppXSvc" - -try { - $svc = Get-Service -Name $svcName -ErrorAction SilentlyContinue - if ($null -ne $svc) { - if ($svc.Status -ne "Stopped") { - Stop-Service -Name $svcName -Force -ErrorAction SilentlyContinue - } - Set-Service -Name $svcName -StartupType Disabled -ErrorAction SilentlyContinue - } - - if (Test-Path $svcKeyPath) { - New-ItemProperty -Path $svcKeyPath -Name Start -Value 4 -PropertyType DWord -Force | Out-Null - } -} catch { - # best-effort only -} -'@ - - Set-Content -Path $hardeningFile -Value $hardeningScript -Encoding UTF8 -Force - - $action = New-ScheduledTaskAction -Execute 'powershell.exe' ` - -Argument "-NoLogo -NonInteractive -WindowStyle Hidden -ExecutionPolicy Bypass -File `"$hardeningFile`"" - $trigger = New-ScheduledTaskTrigger -AtStartup - - $taskName = 'Hard-Disable-AppXSvc' - $taskPath = '\Hardening\' - - Unregister-ScheduledTask -TaskName $taskName -TaskPath $taskPath -Confirm:$false -ErrorAction SilentlyContinue - - Register-ScheduledTask -TaskName $taskName ` - -TaskPath $taskPath ` - -Action $action ` - -Trigger $trigger ` - -RunLevel Highest ` - -User 'SYSTEM' ` - -Force | Out-Null -} - -function Test-AppXSvcDisabled { - [CmdletBinding()] - param() - - $svc = Get-Service -Name $svcName -ErrorAction SilentlyContinue - if ($null -eq $svc) { return $true } - - # Success condition: Disabled. It may still be Running during early provisioning. - if ($svc.StartType.ToString() -eq 'Disabled') { - if ($svc.Status -ne 'Stopped') { - Write-Log -message ("uninstall_appx_packages :: AppXSvc is Disabled but currently {0}. Will be enforced at next boot." -f $svc.Status) -severity 'WARN' - } - return $true - } - - return $false -} - -Write-Log -message 'uninstall_appx_packages :: begin' -severity 'DEBUG' - -Write-Log -message 'uninstall_appx_packages :: Remove-PreinstalledAppxPackages' -severity 'DEBUG' -Remove-PreinstalledAppxPackages - -Write-Log -message 'uninstall_appx_packages :: Disable-AppXSvcCore' -severity 'DEBUG' -Disable-AppXSvcCore - -Write-Log -message 'uninstall_appx_packages :: Ensure-AppXSvcHardeningTask' -severity 'DEBUG' -Ensure-AppXSvcHardeningTask - -if (-not (Test-AppXSvcDisabled)) { - $svc = Get-Service -Name $svcName -ErrorAction SilentlyContinue - $status = if ($svc) { $svc.Status } else { 'Missing' } - $startType = if ($svc) { $svc.StartType } else { 'Missing' } - - Write-Log -message ("uninstall_appx_packages :: AppXSvc is NOT disabled. Status: {0}, StartType: {1}" -f $status, $startType) -severity 'ERROR' - throw "AppXSvc is NOT disabled. Status: $status, StartType: $startType" -} - -Write-Log -message 'uninstall_appx_packages :: complete (AppXSvc disabled)' -severity 'DEBUG' diff --git a/modules/win_disable_services/files/appxpackages/BAKuninstall.ps1 b/modules/win_disable_services/files/appxpackages/uninstall.ps1.BAK similarity index 100% rename from modules/win_disable_services/files/appxpackages/BAKuninstall.ps1 rename to modules/win_disable_services/files/appxpackages/uninstall.ps1.BAK From b15751c36eae42e0526cc609cadd071bc66d8616 Mon Sep 17 00:00:00 2001 From: Mark Cornmesser Date: Wed, 14 Jan 2026 14:05:06 -0800 Subject: [PATCH 092/105] remove win hw variant value --- data/roles/win116424h2hw.yaml | 2 -- data/roles/win116424h2hwalpha.yaml | 2 -- data/roles/win116424h2hwperfsheriff.yaml | 2 -- data/roles/win116424h2hwref.yaml | 2 -- data/roles/win116424h2hwrefalpha.yaml | 2 -- data/roles/win116424h2hwrelops1213.yaml | 2 -- 6 files changed, 12 deletions(-) diff --git a/data/roles/win116424h2hw.yaml b/data/roles/win116424h2hw.yaml index 7e7ef0f83..efe65b488 100644 --- a/data/roles/win116424h2hw.yaml +++ b/data/roles/win116424h2hw.yaml @@ -18,5 +18,3 @@ win-worker: ## Use to overwrite values in the Windows yaml file. ## Replace windows. with win-worker.variant. variant: - taskcluster: - version: "91.1.0" diff --git a/data/roles/win116424h2hwalpha.yaml b/data/roles/win116424h2hwalpha.yaml index 62e6718af..717a61798 100644 --- a/data/roles/win116424h2hwalpha.yaml +++ b/data/roles/win116424h2hwalpha.yaml @@ -18,5 +18,3 @@ win-worker: ## Use to overwrite values in the Windows yaml file. ## Replace windows. with win-worker.variant. variant: - taskcluster: - version: "91.1.0" diff --git a/data/roles/win116424h2hwperfsheriff.yaml b/data/roles/win116424h2hwperfsheriff.yaml index 2d4d94c34..eeffd0093 100644 --- a/data/roles/win116424h2hwperfsheriff.yaml +++ b/data/roles/win116424h2hwperfsheriff.yaml @@ -19,5 +19,3 @@ win-worker: ## Use to overwrite values in the Windows yaml file. ## Replace windows. with win-worker.variant. variant: - taskcluster: - version: "91.1.0" diff --git a/data/roles/win116424h2hwref.yaml b/data/roles/win116424h2hwref.yaml index 917cf305e..7393de1b7 100644 --- a/data/roles/win116424h2hwref.yaml +++ b/data/roles/win116424h2hwref.yaml @@ -18,5 +18,3 @@ win-worker: ## Use to overwrite values in the Windows yaml file. ## Replace windows. with win-worker.variant. variant: - taskcluster: - version: "91.1.0" diff --git a/data/roles/win116424h2hwrefalpha.yaml b/data/roles/win116424h2hwrefalpha.yaml index 7551367e6..5c0c99905 100644 --- a/data/roles/win116424h2hwrefalpha.yaml +++ b/data/roles/win116424h2hwrefalpha.yaml @@ -18,5 +18,3 @@ win-worker: ## Use to overwrite values in the Windows yaml file. ## Replace windows. with win-worker.variant. variant: - taskcluster: - version: "91.1.0" diff --git a/data/roles/win116424h2hwrelops1213.yaml b/data/roles/win116424h2hwrelops1213.yaml index a0ca52cf8..4ea5ee74c 100644 --- a/data/roles/win116424h2hwrelops1213.yaml +++ b/data/roles/win116424h2hwrelops1213.yaml @@ -19,5 +19,3 @@ win-worker: ## Use to overwrite values in the Windows yaml file. ## Replace windows. with win-worker.variant. variant: - taskcluster: - version: "91.1.0" From af7f7f0a9fec1a636483cda54e27251cbad1fe91 Mon Sep 17 00:00:00 2001 From: Jonathan Moss Date: Thu, 15 Jan 2026 09:39:25 -0500 Subject: [PATCH 093/105] fix(taskcluster): correct URL construction for GitHub release downloads --- .../profiles/windows_generic_worker_standalone.pp | 8 ++++---- .../manifests/profiles/windows_worker_runner.pp | 10 +++++----- 2 files changed, 9 insertions(+), 9 deletions(-) diff --git a/modules/roles_profiles/manifests/profiles/windows_generic_worker_standalone.pp b/modules/roles_profiles/manifests/profiles/windows_generic_worker_standalone.pp index 0b58360a8..5c170780c 100644 --- a/modules/roles_profiles/manifests/profiles/windows_generic_worker_standalone.pp +++ b/modules/roles_profiles/manifests/profiles/windows_generic_worker_standalone.pp @@ -9,7 +9,7 @@ $arch = 'win64' - $ext_pkg_src_loc = lookup('windows.taskcluster.relops_az') + $ext_pkg_src_loc = "${lookup('windows.taskcluster.relops_az')}/" $generic_worker_dir = lookup('windows.dir.generic_worker') $gw_exe_path = "${generic_worker_dir}\\generic-worker.exe" @@ -51,14 +51,14 @@ generic_worker_dir => $generic_worker_dir, gw_config_path => $gw_config_path, gw_exe_path => $gw_exe_path, - gw_exe_source => "${ext_pkg_src_loc}/${taskcluster_version}/${gw_name}", + gw_exe_source => "${ext_pkg_src_loc}${taskcluster_version}/${gw_name}", gw_status => $facts['custom_win_genericworker_service'], livelog_exe => "${facts['custom_win_systemdrive']}\\\\generic-worker\\\\livelog.exe", - livelog_exe_source => "${ext_pkg_src_loc}/${$taskcluster_version}/${livelog_name}", + livelog_exe_source => "${ext_pkg_src_loc}${taskcluster_version}/${livelog_name}", task_dir => "${facts['custom_win_systemdrive']}\\\\", taskcluster_access_token => lookup('taskcluster_access_token'), taskcluster_proxy_exe => "${facts['custom_win_systemdrive']}\\\\generic-worker\\\\taskcluster-proxy.exe", - taskcluster_proxy_source => "${ext_pkg_src_loc}/${taskcluster_version}/${proxy_name}", + taskcluster_proxy_source => "${ext_pkg_src_loc}${taskcluster_version}/${proxy_name}", taskcluster_root => lookup('windows.taskcluster.root_url'), #task_user_init_cmd => $init, worker_type => $worker_pool_id, diff --git a/modules/roles_profiles/manifests/profiles/windows_worker_runner.pp b/modules/roles_profiles/manifests/profiles/windows_worker_runner.pp index 76a3d4fb2..52b663285 100644 --- a/modules/roles_profiles/manifests/profiles/windows_worker_runner.pp +++ b/modules/roles_profiles/manifests/profiles/windows_worker_runner.pp @@ -11,7 +11,7 @@ case $facts['custom_win_location'] { 'datacenter': { - $ext_pkg_src_loc = lookup('windows.taskcluster.relops_az') + $ext_pkg_src_loc = "${lookup('windows.taskcluster.relops_az')}/" $provider = 'standalone' } default: { @@ -139,7 +139,7 @@ generic_worker_dir => $generic_worker_dir, desired_gw_version => $desired_gw_version, current_gw_version => $facts['custom_win_genericworker_version'], - gw_exe_source => "${ext_pkg_src_loc}/${desired_gw_version}/${gw_name}", + gw_exe_source => "${ext_pkg_src_loc}${desired_gw_version}/${gw_name}", init_file => $init, gw_exe_path => $gw_exe_path, } @@ -147,18 +147,18 @@ generic_worker_dir => $generic_worker_dir, desired_proxy_version => $desired_proxy_version, current_proxy_version => $facts['custom_win_taskcluster_proxy_version'], - proxy_exe_source => "${ext_pkg_src_loc}/${desired_proxy_version}/${proxy_name}", + proxy_exe_source => "${ext_pkg_src_loc}${desired_proxy_version}/${proxy_name}", } class { 'win_taskcluster::livelog': generic_worker_dir => $generic_worker_dir, - livelog_exe_source => "${ext_pkg_src_loc}/${livelog_version}/${livelog_name}", + livelog_exe_source => "${ext_pkg_src_loc}${livelog_version}/${livelog_name}", } class { 'win_taskcluster::worker_runner': # Runner EXE worker_runner_dir => $worker_runner_dir, desired_runner_version => $desired_rnr_version, current_runner_version => $facts['custom_win_runner_version'], - runner_exe_source => "${ext_pkg_src_loc}/${desired_rnr_version}/${runner_name}", + runner_exe_source => "${ext_pkg_src_loc}${desired_rnr_version}/${runner_name}", runner_exe_path => "${worker_runner_dir}\\start-worker.exe", runner_yml => "${worker_runner_dir}\\runner.yml", # Runner service install From 2af22bfefa9e5e1f62a01bb9c0d7b34ea73da62e Mon Sep 17 00:00:00 2001 From: Mark Cornmesser Date: Thu, 15 Jan 2026 09:00:33 -0800 Subject: [PATCH 094/105] do not run disable optional services for Azure --- .../manifests/profiles/disable_services.pp | 16 +++++++++++----- 1 file changed, 11 insertions(+), 5 deletions(-) diff --git a/modules/roles_profiles/manifests/profiles/disable_services.pp b/modules/roles_profiles/manifests/profiles/disable_services.pp index d043aaf6d..8f42b9172 100644 --- a/modules/roles_profiles/manifests/profiles/disable_services.pp +++ b/modules/roles_profiles/manifests/profiles/disable_services.pp @@ -43,18 +43,24 @@ ## Taken from https://github.com/The-Virtual-Desktop-Team/Virtual-Desktop-Optimization-Tool ## Bug 1913499 https://bugzilla.mozilla.org/show_bug.cgi?id=1913499 include win_disable_services::uninstall_appx_packages - include win_disable_services::disable_optional_services ## WIP for RELOPS-1946 - ## Not currently working. Leaving place for ref. + ## Not currently working. Leaving n place for ref. #include win_disable_services::disable_defender_smartscreen #include win_disable_services::disable_sync_from_cloud - if ($facts['custom_win_location'] == 'azure') { - include win_scheduled_tasks::kill_local_clipboard - } if $facts['custom_win_release_id'] == '2004' or '2009' { ## win11 ref with osdcloud include win_disable_services::disable_windows_defender_schtask } + case $facts['custom_win_location'] { + 'datacenter': { + include win_disable_services::disable_optional_services + } + 'azure': { + include win_scheduled_tasks::kill_local_clipboard + } + default: { + } + } } # May be needed for non-hardaware # Commented out because this will break the auto restore From 51fe3cb53f94d18ce0e576c4908085aa5e5592cf Mon Sep 17 00:00:00 2001 From: Mark Cornmesser Date: Thu, 15 Jan 2026 09:47:54 -0800 Subject: [PATCH 095/105] do not run disable optional services for Azure --- modules/roles_profiles/manifests/profiles/disable_services.pp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/modules/roles_profiles/manifests/profiles/disable_services.pp b/modules/roles_profiles/manifests/profiles/disable_services.pp index 8f42b9172..a5fc12511 100644 --- a/modules/roles_profiles/manifests/profiles/disable_services.pp +++ b/modules/roles_profiles/manifests/profiles/disable_services.pp @@ -42,7 +42,7 @@ ## Let's Uninstall Appx Packages ## Taken from https://github.com/The-Virtual-Desktop-Team/Virtual-Desktop-Optimization-Tool ## Bug 1913499 https://bugzilla.mozilla.org/show_bug.cgi?id=1913499 - include win_disable_services::uninstall_appx_packages + ########## include win_disable_services::uninstall_appx_packages ## WIP for RELOPS-1946 ## Not currently working. Leaving n place for ref. #include win_disable_services::disable_defender_smartscreen From ef5703cc96191f517a9edbb6a403fcfb1340af0f Mon Sep 17 00:00:00 2001 From: Mark Cornmesser Date: Thu, 15 Jan 2026 11:33:19 -0800 Subject: [PATCH 096/105] do not run disable optional services for Azure --- .../manifests/profiles/disable_services.pp | 14 +- .../files/appxpackages/hw-uninstall.ps1 | 334 +++++++++++ .../files/appxpackages/uninstall.ps1 | 556 +++++++++--------- .../files/appxpackages/uninstall.ps1.BAK | 320 ---------- .../manifests/uninstall_appx_packages.pp | 6 +- 5 files changed, 618 insertions(+), 612 deletions(-) create mode 100644 modules/win_disable_services/files/appxpackages/hw-uninstall.ps1 delete mode 100644 modules/win_disable_services/files/appxpackages/uninstall.ps1.BAK diff --git a/modules/roles_profiles/manifests/profiles/disable_services.pp b/modules/roles_profiles/manifests/profiles/disable_services.pp index a5fc12511..cf96e99cf 100644 --- a/modules/roles_profiles/manifests/profiles/disable_services.pp +++ b/modules/roles_profiles/manifests/profiles/disable_services.pp @@ -39,10 +39,7 @@ include win_disable_services::disable_windows_update if $facts['custom_win_purpose'] != builder { include win_disable_services::disable_wsearch - ## Let's Uninstall Appx Packages - ## Taken from https://github.com/The-Virtual-Desktop-Team/Virtual-Desktop-Optimization-Tool - ## Bug 1913499 https://bugzilla.mozilla.org/show_bug.cgi?id=1913499 - ########## include win_disable_services::uninstall_appx_packages + include win_disable_services::disable_optional_services ## WIP for RELOPS-1946 ## Not currently working. Leaving n place for ref. #include win_disable_services::disable_defender_smartscreen @@ -53,14 +50,21 @@ } case $facts['custom_win_location'] { 'datacenter': { - include win_disable_services::disable_optional_services + $apx_uninstall = 'hw-uninstall.ps1' } 'azure': { include win_scheduled_tasks::kill_local_clipboard + $apx_uninstall = 'uninstall.ps1' } default: { } } + ## Let's Uninstall Appx Packages + ## Taken from https://github.com/The-Virtual-Desktop-Team/Virtual-Desktop-Optimization-Tool + ## Bug 1913499 https://bugzilla.mozilla.org/show_bug.cgi?id=1913499 + class { 'win_disable_services::uninstall_appx_packages': + apx_uninstall => $apx_uninstall + } } # May be needed for non-hardaware # Commented out because this will break the auto restore diff --git a/modules/win_disable_services/files/appxpackages/hw-uninstall.ps1 b/modules/win_disable_services/files/appxpackages/hw-uninstall.ps1 new file mode 100644 index 000000000..42bd7dcd1 --- /dev/null +++ b/modules/win_disable_services/files/appxpackages/hw-uninstall.ps1 @@ -0,0 +1,334 @@ +function Write-Log { + param ( + [string] $message, + [ValidateSet('DEBUG','INFO','WARN','ERROR')] + [string] $severity = 'INFO', + [string] $source = 'BootStrap', + [string] $logName = 'Application' + ) + + $entryType = 'Information' + $eventId = 1 + + switch ($severity) { + 'DEBUG' { $entryType = 'SuccessAudit'; $eventId = 2; break } + 'WARN' { $entryType = 'Warning'; $eventId = 3; break } + 'ERROR' { $entryType = 'Error'; $eventId = 4; break } + default { $entryType = 'Information'; $eventId = 1; break } + } + + # Best-effort event log creation (avoid terminating failures / races) + try { + if (!([Diagnostics.EventLog]::Exists($logName)) -or + !([Diagnostics.EventLog]::SourceExists($source))) { + New-EventLog -LogName $logName -Source $source -ErrorAction SilentlyContinue | Out-Null + } + } catch { + # ignore + } + + try { + Write-EventLog -LogName $logName -Source $source ` + -EntryType $entryType -Category 0 -EventID $eventId ` + -Message $message -ErrorAction SilentlyContinue + } catch { + # ignore + } + + if ([Environment]::UserInteractive) { + $fc = @{ + 'Information' = 'White' + 'Error' = 'Red' + 'Warning' = 'DarkYellow' + 'SuccessAudit' = 'DarkGray' + }[$entryType] + Write-Host $message -ForegroundColor $fc + } +} + +# IMPORTANT: use 'Continue' so normal AppX noise doesn't hard-fail Puppet +$ErrorActionPreference = 'Continue' + +$svcName = 'AppXSvc' +$svcKeyPath = 'HKLM:\SYSTEM\CurrentControlSet\Services\AppXSvc' + +function Remove-PreinstalledAppxPackages { + [CmdletBinding()] + param() + + $apps = @{ + "Bing Search" = @{ VDIState="Unchanged"; URL="https://apps.microsoft.com/detail/9nzbf4gt040c"; Description="Web Search from Microsoft Bing provides web results and answers in Windows Search" } + "Clipchamp.Clipchamp" = @{ VDIState="Unchanged"; URL="https://apps.microsoft.com/detail/9p1j8s7ccwwt?hl=en-us&gl=US"; Description="Create videos with a few clicks" } + "Microsoft.549981C3F5F10" = @{ VDIState="Unchanged"; URL="https://apps.microsoft.com/detail/cortana/9NFFX4SZZ23L?hl=en-us&gl=US"; Description="Cortana (could not update)" } + "Microsoft.BingNews" = @{ VDIState="Unchanged"; URL="https://www.microsoft.com/en-us/p/microsoft-news/9wzdncrfhvfw"; Description="Microsoft News app" } + "Microsoft.BingWeather" = @{ VDIState="Unchanged"; URL="https://www.microsoft.com/en-us/p/msn-weather/9wzdncrfj3q2"; Description="MSN Weather app" } + ## Doesn't actually gets removed + ## Comment out for now + #"Microsoft.DesktopAppInstaller" = @{ VDIState="Unchanged"; URL="https://apps.microsoft.com/detail/9NBLGGH4NNS1"; Description="Microsoft App Installer for Windows 10 makes sideloading Windows apps easy" } + "Microsoft.GetHelp" = @{ VDIState="Unchanged"; URL="https://docs.microsoft.com/en-us/windows-hardware/customize/desktop/customize-get-help-app"; Description="App that facilitates free support for Microsoft products" } + "Microsoft.Getstarted" = @{ VDIState="Unchanged"; URL="https://www.microsoft.com/en-us/p/microsoft-tips/9wzdncrdtbjj"; Description="Windows 10 tips app" } + "Microsoft.MicrosoftOfficeHub" = @{ VDIState="Unchanged"; URL="https://www.microsoft.com/en-us/p/office/9wzdncrd29v9"; Description="Office UWP app suite" } + "Microsoft.Office.OneNote" = @{ VDIState="Unchanged"; URL="https://www.microsoft.com/en-us/p/onenote-for-windows-10/9wzdncrfhvjl"; Description="Office UWP OneNote app" } + "Microsoft.MicrosoftSolitaireCollection" = @{ VDIState="Unchanged"; URL="https://www.microsoft.com/en-us/p/microsoft-solitaire-collection/9wzdncrfhwd2"; Description="Solitaire suite of games" } + "Microsoft.MicrosoftStickyNotes" = @{ VDIState="Unchanged"; URL="https://www.microsoft.com/en-us/p/microsoft-sticky-notes/9nblggh4qghw"; Description="Note-taking app" } + "Microsoft.OutlookForWindows" = @{ VDIState="Unchanged"; URL="https://apps.microsoft.com/detail/9NRX63209R7B?hl=en-us&gl=US"; Description="New Outlook app" } + "Microsoft.MSPaint" = @{ VDIState="Unchanged"; URL="https://apps.microsoft.com/store/detail/paint-3d/9NBLGGH5FV99"; Description="Paint 3D app" } + "Microsoft.Paint" = @{ VDIState="Unchanged"; URL="https://apps.microsoft.com/detail/9PCFS5B6T72H"; Description="Classic Paint app" } + "Microsoft.People" = @{ VDIState="Unchanged"; URL="https://www.microsoft.com/en-us/p/microsoft-people/9nblggh10pg8"; Description="Contact management app" } + "Microsoft.PowerAutomateDesktop" = @{ VDIState="Unchanged"; URL="https://flow.microsoft.com/en-us/desktop/"; Description="Power Automate Desktop" } + "Microsoft.ScreenSketch" = @{ VDIState="Unchanged"; URL="https://www.microsoft.com/en-us/p/snip-sketch/9mz95kl8mr0l"; Description="Snip and Sketch app" } + "Microsoft.SkypeApp" = @{ VDIState="Unchanged"; URL="https://www.microsoft.com/en-us/p/skype/9wzdncrfj364"; Description="Skype app" } + "Microsoft.StorePurchaseApp" = @{ VDIState="Unchanged"; URL=""; Description="Store purchase app helper" } + "Microsoft.Todos" = @{ VDIState="Unchanged"; URL="https://www.microsoft.com/en-us/p/microsoft-to-do-lists-tasks-reminders/9nblggh5r558"; Description="Microsoft To Do" } + "Microsoft.WinDbg.Fast" = @{ VDIState="Unchanged"; URL="https://apps.microsoft.com/detail/9PGJGD53TN86?hl=en-us&gl=US"; Description="WinDbg" } + "Microsoft.Windows.DevHome" = @{ VDIState="Unchanged"; URL="https://learn.microsoft.com/en-us/windows/dev-home/"; Description="Dev Home dashboard" } + "Microsoft.Windows.Photos" = @{ VDIState="Unchanged"; URL="https://www.microsoft.com/en-us/p/microsoft-photos/9wzdncrfjbh4"; Description="Photos app" } + "Microsoft.WindowsAlarms" = @{ VDIState="Unchanged"; URL="https://www.microsoft.com/en-us/p/windows-alarms-clock/9wzdncrfj3pr"; Description="Alarms & Clock" } + "Microsoft.WindowsCalculator" = @{ VDIState="Unchanged"; URL="https://www.microsoft.com/en-us/p/windows-calculator/9wzdncrfhvn5"; Description="Calculator" } + "Microsoft.WindowsCamera" = @{ VDIState="Unchanged"; URL="https://www.microsoft.com/en-us/p/windows-camera/9wzdncrfjbbg"; Description="Camera" } + "microsoft.windowscommunicationsapps" = @{ VDIState="Unchanged"; URL="https://www.microsoft.com/en-us/p/mail-and-calendar/9wzdncrfhvqm"; Description="Mail & Calendar" } + "Microsoft.WindowsFeedbackHub" = @{ VDIState="Unchanged"; URL="https://www.microsoft.com/en-us/p/feedback-hub/9nblggh4r32n"; Description="Feedback Hub" } + "Microsoft.WindowsMaps" = @{ VDIState="Unchanged"; URL="https://www.microsoft.com/en-us/p/windows-maps/9wzdncrdtbvb"; Description="Maps" } + "Microsoft.WindowsNotepad" = @{ VDIState="Unchanged"; URL="https://www.microsoft.com/en-us/p/windows-notepad/9msmlrh6lzf3"; Description="Notepad (Store)" } + "Microsoft.WindowsStore" = @{ VDIState="Unchanged"; URL="https://blogs.windows.com/windowsexperience/2021/06/24/building-a-new-open-microsoft-store-on-windows-11/"; Description="Microsoft Store" } + "Microsoft.WindowsSoundRecorder" = @{ VDIState="Unchanged"; URL="https://www.microsoft.com/en-us/p/windows-voice-recorder/9wzdncrfhwkn"; Description="Voice Recorder" } + "Microsoft.WindowsTerminal" = @{ VDIState="Unchanged"; URL="https://www.microsoft.com/en-us/p/windows-terminal/9n0dx20hk701"; Description="Windows Terminal" } + "Microsoft.Winget.Platform.Source"= @{ VDIState="Unchanged"; URL="https://learn.microsoft.com/en-us/windows/package-manager/winget/"; Description="Winget source" } + "Microsoft.Xbox.TCUI" = @{ VDIState="Unchanged"; URL="https://docs.microsoft.com/en-us/gaming/xbox-live/features/general/tcui/live-tcui-overview"; Description="Xbox TCUI" } + "Microsoft.XboxIdentityProvider" = @{ VDIState="Unchanged"; URL="https://www.microsoft.com/en-us/p/xbox-identity-provider/9wzdncrd1hkw"; Description="Xbox Identity Provider" } + "Microsoft.XboxSpeechToTextOverlay" = @{ VDIState="Unchanged"; URL="https://support.xbox.com/help/account-profile/accessibility/use-game-chat-transcription"; Description="Xbox chat transcription" } + "Microsoft.YourPhone" = @{ VDIState="Unchanged"; URL="https://www.microsoft.com/en-us/p/Your-phone/9nmpj99vjbwv"; Description="Phone Link" } + "Microsoft.ZuneMusic" = @{ VDIState="Unchanged"; URL="https://www.microsoft.com/en-us/p/groove-music/9wzdncrfj3pt"; Description="Groove Music" } + "Microsoft.ZuneVideo" = @{ VDIState="Unchanged"; URL="https://www.microsoft.com/en-us/p/movies-tv/9wzdncrfj3p2"; Description="Movies & TV" } + "MicrosoftCorporationII.QuickAssist" = @{ VDIState="Unchanged"; URL="https://apps.microsoft.com/detail/9P7BP5VNWKX5?hl=en-us&gl=US"; Description="Quick Assist" } + "MicrosoftWindows.Client.WebExperience" = @{ VDIState="Unchanged"; URL=""; Description="Windows 11 Web Experience" } + "Microsoft.XboxApp" = @{ VDIState="Unchanged"; URL="https://www.microsoft.com/store/apps/9wzdncrfjbd8"; Description="Xbox Console Companion" } + "Microsoft.MixedReality.Portal" = @{ VDIState="Unchanged"; URL="https://www.microsoft.com/en-us/p/mixed-reality-portal/9ng1h8b3zc7m"; Description="Mixed Reality Portal" } + "Microsoft.Microsoft3DViewer" = @{ VDIState="Unchanged"; URL="https://www.microsoft.com/en-us/p/3d-viewer/9nblggh42ths"; Description="3D Viewer" } + "MicrosoftTeams" = @{ VDIState="Unchanged"; URL="https://apps.microsoft.com/detail/xp8bt8dw290mpq"; Description="Microsoft Teams" } + "MSTeams" = @{ VDIState="Unchanged"; URL="https://apps.microsoft.com/detail/xp8bt8dw290mpq"; Description="Microsoft Teams (alt id)" } + "Microsoft.OneDriveSync" = @{ VDIState="Unchanged"; URL="https://docs.microsoft.com/en-us/onedrive/one-drive-sync"; Description="OneDrive sync app" } + "Microsoft.Wallet" = @{ VDIState="Unchanged"; URL="https://www.microsoft.com/en-us/payments"; Description="Microsoft Pay" } + } + + foreach ($Key in $apps.Keys) { + try { + Write-Log -message ("uninstall_appx_packages :: removing AppX match: {0}" -f $Key) -severity 'DEBUG' + + # Provisioned packages (image-level) + try { + Get-AppxProvisionedPackage -Online -ErrorAction Stop | + Where-Object { $_.PackageName -like ("*{0}*" -f $Key) } | + ForEach-Object { + $pkgName = $_.PackageName + try { + Remove-AppxProvisionedPackage -Online -PackageName $pkgName -ErrorAction Stop | Out-Null + } catch { + Write-Log -message ("Remove-AppxProvisionedPackage failed for {0}: {1}" -f $pkgName, $_.Exception.Message) -severity 'WARN' + } + } + } catch { + Write-Log -message ("Get/Remove provisioned package failed for key {0}: {1}" -f $Key, $_.Exception.Message) -severity 'WARN' + } + + # Installed packages (all users) + try { + Get-AppxPackage -AllUsers -Name ("*{0}*" -f $Key) -ErrorAction SilentlyContinue | + ForEach-Object { + $full = $_.PackageFullName + try { + Remove-AppxPackage -AllUsers -Package $full -ErrorAction Stop | Out-Null + } catch { + Write-Log -message ("Remove-AppxPackage(-AllUsers) failed for {0}: {1}" -f $full, $_.Exception.Message) -severity 'WARN' + } + } + } catch { + Write-Log -message ("Get/Remove AppxPackage(-AllUsers) failed for key {0}: {1}" -f $Key, $_.Exception.Message) -severity 'WARN' + } + + # Installed packages (current user) + try { + Get-AppxPackage -Name ("*{0}*" -f $Key) -ErrorAction SilentlyContinue | + ForEach-Object { + $full = $_.PackageFullName + try { + Remove-AppxPackage -Package $full -ErrorAction Stop | Out-Null + } catch { + Write-Log -message ("Remove-AppxPackage failed for {0}: {1}" -f $full, $_.Exception.Message) -severity 'WARN' + } + } + } catch { + Write-Log -message ("Get/Remove AppxPackage failed for key {0}: {1}" -f $Key, $_.Exception.Message) -severity 'WARN' + } + } catch { + # Absolutely never let AppX errors terminate this script (Puppet signal should be AppXSvc-only) + Write-Log -message ("Remove-PreinstalledAppxPackages unexpected failure for key {0}: {1}" -f $Key, $_.Exception.ToString()) -severity 'WARN' + continue + } + } +} + +function Disable-AppXSvcCore { + [CmdletBinding()] + param() + + $svc = Get-Service -Name $svcName -ErrorAction SilentlyContinue + if ($null -ne $svc) { + if ($svc.Status -ne 'Stopped') { + Stop-Service -Name $svcName -Force -ErrorAction SilentlyContinue + } + Set-Service -Name $svcName -StartupType Disabled -ErrorAction SilentlyContinue + } + + # Extra-hard disable (best-effort): do NOT allow sc.exe exit code to poison overall script exit code + try { + & sc.exe config $svcName start= disabled | Out-Null + } catch { + # ignore + } finally { + $global:LASTEXITCODE = 0 + } + + # Registry is the source of truth for disabled start + if (Test-Path $svcKeyPath) { + New-ItemProperty -Path $svcKeyPath -Name Start -Value 4 -PropertyType DWord -Force | Out-Null + } +} + +function Ensure-AppXSvcHardeningTask { + [CmdletBinding()] + param() + + $hardeningDir = 'C:\ProgramData\AppXLock' + $hardeningFile = Join-Path $hardeningDir 'Disable-AppXSvc.ps1' + + if (-not (Test-Path $hardeningDir)) { + New-Item -ItemType Directory -Path $hardeningDir -Force | Out-Null + } + + $hardeningScript = @' +param() + +$ErrorActionPreference = "SilentlyContinue" + +$svcName = "AppXSvc" +$svcKeyPath = "HKLM:\SYSTEM\CurrentControlSet\Services\AppXSvc" + +try { + $svc = Get-Service -Name $svcName -ErrorAction SilentlyContinue + if ($null -ne $svc) { + if ($svc.Status -ne "Stopped") { + Stop-Service -Name $svcName -Force -ErrorAction SilentlyContinue + } + Set-Service -Name $svcName -StartupType Disabled -ErrorAction SilentlyContinue + } + + # Best-effort: do NOT leak sc.exe exit code + try { + & sc.exe config $svcName start= disabled | Out-Null + } catch { + # ignore + } finally { + $global:LASTEXITCODE = 0 + } + + if (Test-Path $svcKeyPath) { + New-ItemProperty -Path $svcKeyPath -Name Start -Value 4 -PropertyType DWord -Force | Out-Null + } +} catch { + # best-effort only +} +'@ + + Set-Content -Path $hardeningFile -Value $hardeningScript -Encoding UTF8 -Force + + $action = New-ScheduledTaskAction -Execute 'powershell.exe' ` + -Argument "-NoLogo -NoProfile -NonInteractive -WindowStyle Hidden -ExecutionPolicy Bypass -File `"$hardeningFile`"" + $trigger = New-ScheduledTaskTrigger -AtStartup + + $taskName = 'Hard-Disable-AppXSvc' + $taskPath = '\Hardening\' + + Unregister-ScheduledTask -TaskName $taskName -TaskPath $taskPath -Confirm:$false -ErrorAction SilentlyContinue + + Register-ScheduledTask -TaskName $taskName ` + -TaskPath $taskPath ` + -Action $action ` + -Trigger $trigger ` + -RunLevel Highest ` + -User 'SYSTEM' ` + -Force | Out-Null +} + +function Test-AppXSvcDisabled { + [CmdletBinding()] + param() + + $svc = Get-Service -Name $svcName -ErrorAction SilentlyContinue + if ($null -eq $svc) { return $true } + + # Registry is the most reliable indicator (Start=4) + $regStart = $null + try { + $regStart = (Get-ItemProperty -Path $svcKeyPath -Name Start -ErrorAction SilentlyContinue).Start + } catch { } + + $regDisabled = ($regStart -eq 4) + + # CIM is a helpful second signal (StartMode: Auto/Manual/Disabled) + $cimDisabled = $false + $cimStartMode = 'Unknown' + try { + $svcCim = Get-CimInstance Win32_Service -Filter "Name='$svcName'" -ErrorAction SilentlyContinue + if ($svcCim) { + $cimStartMode = $svcCim.StartMode + $cimDisabled = ($svcCim.StartMode -eq 'Disabled') + } + } catch { } + + if ($svc.Status -eq 'Stopped' -and ($regDisabled -or $cimDisabled)) { + return $true + } + + return $false +} + +# --- Main flow --------------------------------------------------------------- + +try { + Write-Log -message 'uninstall_appx_packages :: begin' -severity 'DEBUG' + + Write-Log -message 'uninstall_appx_packages :: Remove-PreinstalledAppxPackages' -severity 'DEBUG' + Remove-PreinstalledAppxPackages + + Write-Log -message 'uninstall_appx_packages :: Disable-AppXSvcCore' -severity 'DEBUG' + Disable-AppXSvcCore + + Write-Log -message 'uninstall_appx_packages :: Ensure-AppXSvcHardeningTask' -severity 'DEBUG' + Ensure-AppXSvcHardeningTask + + if (-not (Test-AppXSvcDisabled)) { + $svc = Get-Service -Name $svcName -ErrorAction SilentlyContinue + $status = if ($svc) { $svc.Status } else { 'Missing' } + + $regStart = $null + try { $regStart = (Get-ItemProperty -Path $svcKeyPath -Name Start -ErrorAction SilentlyContinue).Start } catch { } + $regStartStr = if ($null -ne $regStart) { $regStart } else { 'Missing' } + + $cimStartMode = 'Unknown' + try { + $svcCim = Get-CimInstance Win32_Service -Filter "Name='$svcName'" -ErrorAction SilentlyContinue + if ($svcCim) { $cimStartMode = $svcCim.StartMode } + } catch { } + + Write-Log -message ("uninstall_appx_packages :: AppXSvc is NOT disabled. Status: {0}, RegStart: {1}, CimStartMode: {2}" -f $status, $regStartStr, $cimStartMode) -severity 'ERROR' + exit 2 + } + + Write-Log -message 'uninstall_appx_packages :: complete (AppXSvc disabled)' -severity 'DEBUG' + exit 0 +} +catch { + Write-Log -message ("uninstall_appx_packages :: FATAL: {0}" -f $_.Exception.ToString()) -severity 'ERROR' + exit 1 +} diff --git a/modules/win_disable_services/files/appxpackages/uninstall.ps1 b/modules/win_disable_services/files/appxpackages/uninstall.ps1 index 42bd7dcd1..4778d3e8e 100644 --- a/modules/win_disable_services/files/appxpackages/uninstall.ps1 +++ b/modules/win_disable_services/files/appxpackages/uninstall.ps1 @@ -1,334 +1,320 @@ -function Write-Log { - param ( - [string] $message, - [ValidateSet('DEBUG','INFO','WARN','ERROR')] - [string] $severity = 'INFO', - [string] $source = 'BootStrap', - [string] $logName = 'Application' - ) - - $entryType = 'Information' - $eventId = 1 - - switch ($severity) { - 'DEBUG' { $entryType = 'SuccessAudit'; $eventId = 2; break } - 'WARN' { $entryType = 'Warning'; $eventId = 3; break } - 'ERROR' { $entryType = 'Error'; $eventId = 4; break } - default { $entryType = 'Information'; $eventId = 1; break } - } - - # Best-effort event log creation (avoid terminating failures / races) - try { - if (!([Diagnostics.EventLog]::Exists($logName)) -or - !([Diagnostics.EventLog]::SourceExists($source))) { - New-EventLog -LogName $logName -Source $source -ErrorAction SilentlyContinue | Out-Null - } - } catch { - # ignore - } - - try { - Write-EventLog -LogName $logName -Source $source ` - -EntryType $entryType -Category 0 -EventID $eventId ` - -Message $message -ErrorAction SilentlyContinue - } catch { - # ignore - } - - if ([Environment]::UserInteractive) { - $fc = @{ - 'Information' = 'White' - 'Error' = 'Red' - 'Warning' = 'DarkYellow' - 'SuccessAudit' = 'DarkGray' - }[$entryType] - Write-Host $message -ForegroundColor $fc +$apps = @{ + "Bing Search" = @{ + VDIState = "Unchanged" + URL = "https://apps.microsoft.com/detail/9nzbf4gt040c" + Description = "Web Search from Microsoft Bing provides web results and answers in Windows Search" } -} -# IMPORTANT: use 'Continue' so normal AppX noise doesn't hard-fail Puppet -$ErrorActionPreference = 'Continue' - -$svcName = 'AppXSvc' -$svcKeyPath = 'HKLM:\SYSTEM\CurrentControlSet\Services\AppXSvc' - -function Remove-PreinstalledAppxPackages { - [CmdletBinding()] - param() - - $apps = @{ - "Bing Search" = @{ VDIState="Unchanged"; URL="https://apps.microsoft.com/detail/9nzbf4gt040c"; Description="Web Search from Microsoft Bing provides web results and answers in Windows Search" } - "Clipchamp.Clipchamp" = @{ VDIState="Unchanged"; URL="https://apps.microsoft.com/detail/9p1j8s7ccwwt?hl=en-us&gl=US"; Description="Create videos with a few clicks" } - "Microsoft.549981C3F5F10" = @{ VDIState="Unchanged"; URL="https://apps.microsoft.com/detail/cortana/9NFFX4SZZ23L?hl=en-us&gl=US"; Description="Cortana (could not update)" } - "Microsoft.BingNews" = @{ VDIState="Unchanged"; URL="https://www.microsoft.com/en-us/p/microsoft-news/9wzdncrfhvfw"; Description="Microsoft News app" } - "Microsoft.BingWeather" = @{ VDIState="Unchanged"; URL="https://www.microsoft.com/en-us/p/msn-weather/9wzdncrfj3q2"; Description="MSN Weather app" } - ## Doesn't actually gets removed - ## Comment out for now - #"Microsoft.DesktopAppInstaller" = @{ VDIState="Unchanged"; URL="https://apps.microsoft.com/detail/9NBLGGH4NNS1"; Description="Microsoft App Installer for Windows 10 makes sideloading Windows apps easy" } - "Microsoft.GetHelp" = @{ VDIState="Unchanged"; URL="https://docs.microsoft.com/en-us/windows-hardware/customize/desktop/customize-get-help-app"; Description="App that facilitates free support for Microsoft products" } - "Microsoft.Getstarted" = @{ VDIState="Unchanged"; URL="https://www.microsoft.com/en-us/p/microsoft-tips/9wzdncrdtbjj"; Description="Windows 10 tips app" } - "Microsoft.MicrosoftOfficeHub" = @{ VDIState="Unchanged"; URL="https://www.microsoft.com/en-us/p/office/9wzdncrd29v9"; Description="Office UWP app suite" } - "Microsoft.Office.OneNote" = @{ VDIState="Unchanged"; URL="https://www.microsoft.com/en-us/p/onenote-for-windows-10/9wzdncrfhvjl"; Description="Office UWP OneNote app" } - "Microsoft.MicrosoftSolitaireCollection" = @{ VDIState="Unchanged"; URL="https://www.microsoft.com/en-us/p/microsoft-solitaire-collection/9wzdncrfhwd2"; Description="Solitaire suite of games" } - "Microsoft.MicrosoftStickyNotes" = @{ VDIState="Unchanged"; URL="https://www.microsoft.com/en-us/p/microsoft-sticky-notes/9nblggh4qghw"; Description="Note-taking app" } - "Microsoft.OutlookForWindows" = @{ VDIState="Unchanged"; URL="https://apps.microsoft.com/detail/9NRX63209R7B?hl=en-us&gl=US"; Description="New Outlook app" } - "Microsoft.MSPaint" = @{ VDIState="Unchanged"; URL="https://apps.microsoft.com/store/detail/paint-3d/9NBLGGH5FV99"; Description="Paint 3D app" } - "Microsoft.Paint" = @{ VDIState="Unchanged"; URL="https://apps.microsoft.com/detail/9PCFS5B6T72H"; Description="Classic Paint app" } - "Microsoft.People" = @{ VDIState="Unchanged"; URL="https://www.microsoft.com/en-us/p/microsoft-people/9nblggh10pg8"; Description="Contact management app" } - "Microsoft.PowerAutomateDesktop" = @{ VDIState="Unchanged"; URL="https://flow.microsoft.com/en-us/desktop/"; Description="Power Automate Desktop" } - "Microsoft.ScreenSketch" = @{ VDIState="Unchanged"; URL="https://www.microsoft.com/en-us/p/snip-sketch/9mz95kl8mr0l"; Description="Snip and Sketch app" } - "Microsoft.SkypeApp" = @{ VDIState="Unchanged"; URL="https://www.microsoft.com/en-us/p/skype/9wzdncrfj364"; Description="Skype app" } - "Microsoft.StorePurchaseApp" = @{ VDIState="Unchanged"; URL=""; Description="Store purchase app helper" } - "Microsoft.Todos" = @{ VDIState="Unchanged"; URL="https://www.microsoft.com/en-us/p/microsoft-to-do-lists-tasks-reminders/9nblggh5r558"; Description="Microsoft To Do" } - "Microsoft.WinDbg.Fast" = @{ VDIState="Unchanged"; URL="https://apps.microsoft.com/detail/9PGJGD53TN86?hl=en-us&gl=US"; Description="WinDbg" } - "Microsoft.Windows.DevHome" = @{ VDIState="Unchanged"; URL="https://learn.microsoft.com/en-us/windows/dev-home/"; Description="Dev Home dashboard" } - "Microsoft.Windows.Photos" = @{ VDIState="Unchanged"; URL="https://www.microsoft.com/en-us/p/microsoft-photos/9wzdncrfjbh4"; Description="Photos app" } - "Microsoft.WindowsAlarms" = @{ VDIState="Unchanged"; URL="https://www.microsoft.com/en-us/p/windows-alarms-clock/9wzdncrfj3pr"; Description="Alarms & Clock" } - "Microsoft.WindowsCalculator" = @{ VDIState="Unchanged"; URL="https://www.microsoft.com/en-us/p/windows-calculator/9wzdncrfhvn5"; Description="Calculator" } - "Microsoft.WindowsCamera" = @{ VDIState="Unchanged"; URL="https://www.microsoft.com/en-us/p/windows-camera/9wzdncrfjbbg"; Description="Camera" } - "microsoft.windowscommunicationsapps" = @{ VDIState="Unchanged"; URL="https://www.microsoft.com/en-us/p/mail-and-calendar/9wzdncrfhvqm"; Description="Mail & Calendar" } - "Microsoft.WindowsFeedbackHub" = @{ VDIState="Unchanged"; URL="https://www.microsoft.com/en-us/p/feedback-hub/9nblggh4r32n"; Description="Feedback Hub" } - "Microsoft.WindowsMaps" = @{ VDIState="Unchanged"; URL="https://www.microsoft.com/en-us/p/windows-maps/9wzdncrdtbvb"; Description="Maps" } - "Microsoft.WindowsNotepad" = @{ VDIState="Unchanged"; URL="https://www.microsoft.com/en-us/p/windows-notepad/9msmlrh6lzf3"; Description="Notepad (Store)" } - "Microsoft.WindowsStore" = @{ VDIState="Unchanged"; URL="https://blogs.windows.com/windowsexperience/2021/06/24/building-a-new-open-microsoft-store-on-windows-11/"; Description="Microsoft Store" } - "Microsoft.WindowsSoundRecorder" = @{ VDIState="Unchanged"; URL="https://www.microsoft.com/en-us/p/windows-voice-recorder/9wzdncrfhwkn"; Description="Voice Recorder" } - "Microsoft.WindowsTerminal" = @{ VDIState="Unchanged"; URL="https://www.microsoft.com/en-us/p/windows-terminal/9n0dx20hk701"; Description="Windows Terminal" } - "Microsoft.Winget.Platform.Source"= @{ VDIState="Unchanged"; URL="https://learn.microsoft.com/en-us/windows/package-manager/winget/"; Description="Winget source" } - "Microsoft.Xbox.TCUI" = @{ VDIState="Unchanged"; URL="https://docs.microsoft.com/en-us/gaming/xbox-live/features/general/tcui/live-tcui-overview"; Description="Xbox TCUI" } - "Microsoft.XboxIdentityProvider" = @{ VDIState="Unchanged"; URL="https://www.microsoft.com/en-us/p/xbox-identity-provider/9wzdncrd1hkw"; Description="Xbox Identity Provider" } - "Microsoft.XboxSpeechToTextOverlay" = @{ VDIState="Unchanged"; URL="https://support.xbox.com/help/account-profile/accessibility/use-game-chat-transcription"; Description="Xbox chat transcription" } - "Microsoft.YourPhone" = @{ VDIState="Unchanged"; URL="https://www.microsoft.com/en-us/p/Your-phone/9nmpj99vjbwv"; Description="Phone Link" } - "Microsoft.ZuneMusic" = @{ VDIState="Unchanged"; URL="https://www.microsoft.com/en-us/p/groove-music/9wzdncrfj3pt"; Description="Groove Music" } - "Microsoft.ZuneVideo" = @{ VDIState="Unchanged"; URL="https://www.microsoft.com/en-us/p/movies-tv/9wzdncrfj3p2"; Description="Movies & TV" } - "MicrosoftCorporationII.QuickAssist" = @{ VDIState="Unchanged"; URL="https://apps.microsoft.com/detail/9P7BP5VNWKX5?hl=en-us&gl=US"; Description="Quick Assist" } - "MicrosoftWindows.Client.WebExperience" = @{ VDIState="Unchanged"; URL=""; Description="Windows 11 Web Experience" } - "Microsoft.XboxApp" = @{ VDIState="Unchanged"; URL="https://www.microsoft.com/store/apps/9wzdncrfjbd8"; Description="Xbox Console Companion" } - "Microsoft.MixedReality.Portal" = @{ VDIState="Unchanged"; URL="https://www.microsoft.com/en-us/p/mixed-reality-portal/9ng1h8b3zc7m"; Description="Mixed Reality Portal" } - "Microsoft.Microsoft3DViewer" = @{ VDIState="Unchanged"; URL="https://www.microsoft.com/en-us/p/3d-viewer/9nblggh42ths"; Description="3D Viewer" } - "MicrosoftTeams" = @{ VDIState="Unchanged"; URL="https://apps.microsoft.com/detail/xp8bt8dw290mpq"; Description="Microsoft Teams" } - "MSTeams" = @{ VDIState="Unchanged"; URL="https://apps.microsoft.com/detail/xp8bt8dw290mpq"; Description="Microsoft Teams (alt id)" } - "Microsoft.OneDriveSync" = @{ VDIState="Unchanged"; URL="https://docs.microsoft.com/en-us/onedrive/one-drive-sync"; Description="OneDrive sync app" } - "Microsoft.Wallet" = @{ VDIState="Unchanged"; URL="https://www.microsoft.com/en-us/payments"; Description="Microsoft Pay" } - } - - foreach ($Key in $apps.Keys) { - try { - Write-Log -message ("uninstall_appx_packages :: removing AppX match: {0}" -f $Key) -severity 'DEBUG' - - # Provisioned packages (image-level) - try { - Get-AppxProvisionedPackage -Online -ErrorAction Stop | - Where-Object { $_.PackageName -like ("*{0}*" -f $Key) } | - ForEach-Object { - $pkgName = $_.PackageName - try { - Remove-AppxProvisionedPackage -Online -PackageName $pkgName -ErrorAction Stop | Out-Null - } catch { - Write-Log -message ("Remove-AppxProvisionedPackage failed for {0}: {1}" -f $pkgName, $_.Exception.Message) -severity 'WARN' - } - } - } catch { - Write-Log -message ("Get/Remove provisioned package failed for key {0}: {1}" -f $Key, $_.Exception.Message) -severity 'WARN' - } - - # Installed packages (all users) - try { - Get-AppxPackage -AllUsers -Name ("*{0}*" -f $Key) -ErrorAction SilentlyContinue | - ForEach-Object { - $full = $_.PackageFullName - try { - Remove-AppxPackage -AllUsers -Package $full -ErrorAction Stop | Out-Null - } catch { - Write-Log -message ("Remove-AppxPackage(-AllUsers) failed for {0}: {1}" -f $full, $_.Exception.Message) -severity 'WARN' - } - } - } catch { - Write-Log -message ("Get/Remove AppxPackage(-AllUsers) failed for key {0}: {1}" -f $Key, $_.Exception.Message) -severity 'WARN' - } - - # Installed packages (current user) - try { - Get-AppxPackage -Name ("*{0}*" -f $Key) -ErrorAction SilentlyContinue | - ForEach-Object { - $full = $_.PackageFullName - try { - Remove-AppxPackage -Package $full -ErrorAction Stop | Out-Null - } catch { - Write-Log -message ("Remove-AppxPackage failed for {0}: {1}" -f $full, $_.Exception.Message) -severity 'WARN' - } - } - } catch { - Write-Log -message ("Get/Remove AppxPackage failed for key {0}: {1}" -f $Key, $_.Exception.Message) -severity 'WARN' - } - } catch { - # Absolutely never let AppX errors terminate this script (Puppet signal should be AppXSvc-only) - Write-Log -message ("Remove-PreinstalledAppxPackages unexpected failure for key {0}: {1}" -f $Key, $_.Exception.ToString()) -severity 'WARN' - continue - } + "Clipchamp.Clipchamp" = @{ + VDIState = "Unchanged" + URL = "https://apps.microsoft.com/detail/9p1j8s7ccwwt?hl=en-us&gl=US" + Description = "Create videos with a few clicks" } -} -function Disable-AppXSvcCore { - [CmdletBinding()] - param() + "Microsoft.549981C3F5F10" = @{ + VDIState = "Unchanged" + URL = "https://apps.microsoft.com/detail/cortana/9NFFX4SZZ23L?hl=en-us&gl=US" + Description = "Cortana (could not update)" + } - $svc = Get-Service -Name $svcName -ErrorAction SilentlyContinue - if ($null -ne $svc) { - if ($svc.Status -ne 'Stopped') { - Stop-Service -Name $svcName -Force -ErrorAction SilentlyContinue - } - Set-Service -Name $svcName -StartupType Disabled -ErrorAction SilentlyContinue + "Microsoft.BingNews" = @{ + VDIState = "Unchanged" + URL = "https://www.microsoft.com/en-us/p/microsoft-news/9wzdncrfhvfw" + Description = "Microsoft News app" } - # Extra-hard disable (best-effort): do NOT allow sc.exe exit code to poison overall script exit code - try { - & sc.exe config $svcName start= disabled | Out-Null - } catch { - # ignore - } finally { - $global:LASTEXITCODE = 0 + "Microsoft.BingWeather" = @{ + VDIState = "Unchanged" + URL = "https://www.microsoft.com/en-us/p/msn-weather/9wzdncrfj3q2" + Description = "MSN Weather app" } - # Registry is the source of truth for disabled start - if (Test-Path $svcKeyPath) { - New-ItemProperty -Path $svcKeyPath -Name Start -Value 4 -PropertyType DWord -Force | Out-Null + "Microsoft.DesktopAppInstaller" = @{ + VDIState = "Unchanged" + URL = "https://apps.microsoft.com/detail/9NBLGGH4NNS1" + Description = "Microsoft App Installer for Windows 10 makes sideloading Windows apps easy" } -} -function Ensure-AppXSvcHardeningTask { - [CmdletBinding()] - param() + "Microsoft.GetHelp" = @{ + VDIState = "Unchanged" + URL = "https://docs.microsoft.com/en-us/windows-hardware/customize/desktop/customize-get-help-app" + Description = "App that facilitates free support for Microsoft products" + } - $hardeningDir = 'C:\ProgramData\AppXLock' - $hardeningFile = Join-Path $hardeningDir 'Disable-AppXSvc.ps1' + "Microsoft.Getstarted" = @{ + VDIState = "Unchanged" + URL = "https://www.microsoft.com/en-us/p/microsoft-tips/9wzdncrdtbjj" + Description = "Windows 10 tips app" + } - if (-not (Test-Path $hardeningDir)) { - New-Item -ItemType Directory -Path $hardeningDir -Force | Out-Null + "Microsoft.MicrosoftOfficeHub" = @{ + VDIState = "Unchanged" + URL = "https://www.microsoft.com/en-us/p/office/9wzdncrd29v9" + Description = "Office UWP app suite" } - $hardeningScript = @' -param() + "Microsoft.Office.OneNote" = @{ + VDIState = "Unchanged" + URL = "https://www.microsoft.com/en-us/p/onenote-for-windows-10/9wzdncrfhvjl" + Description = "Office UWP OneNote app" + } -$ErrorActionPreference = "SilentlyContinue" + "Microsoft.MicrosoftSolitaireCollection" = @{ + VDIState = "Unchanged" + URL = "https://www.microsoft.com/en-us/p/microsoft-solitaire-collection/9wzdncrfhwd2" + Description = "Solitaire suite of games" + } -$svcName = "AppXSvc" -$svcKeyPath = "HKLM:\SYSTEM\CurrentControlSet\Services\AppXSvc" + "Microsoft.MicrosoftStickyNotes" = @{ + VDIState = "Unchanged" + URL = "https://www.microsoft.com/en-us/p/microsoft-sticky-notes/9nblggh4qghw" + Description = "Note-taking app" + } -try { - $svc = Get-Service -Name $svcName -ErrorAction SilentlyContinue - if ($null -ne $svc) { - if ($svc.Status -ne "Stopped") { - Stop-Service -Name $svcName -Force -ErrorAction SilentlyContinue - } - Set-Service -Name $svcName -StartupType Disabled -ErrorAction SilentlyContinue + "Microsoft.OutlookForWindows" = @{ + VDIState = "Unchanged" + URL = "https://apps.microsoft.com/detail/9NRX63209R7B?hl=en-us&gl=US" + Description = "A best-in-class email experience that is free for anyone with Windows" } - # Best-effort: do NOT leak sc.exe exit code - try { - & sc.exe config $svcName start= disabled | Out-Null - } catch { - # ignore - } finally { - $global:LASTEXITCODE = 0 + "Microsoft.MSPaint" = @{ + VDIState = "Unchanged" + URL = "https://apps.microsoft.com/store/detail/paint-3d/9NBLGGH5FV99" + Description = "Paint 3D app (not Classic Paint app)" } - if (Test-Path $svcKeyPath) { - New-ItemProperty -Path $svcKeyPath -Name Start -Value 4 -PropertyType DWord -Force | Out-Null + "Microsoft.Paint" = @{ + VDIState = "Unchanged" + URL = "https://apps.microsoft.com/detail/9PCFS5B6T72H" + Description = "Classic Paint app" } -} catch { - # best-effort only -} -'@ - Set-Content -Path $hardeningFile -Value $hardeningScript -Encoding UTF8 -Force + "Microsoft.People" = @{ + VDIState = "Unchanged" + URL = "https://www.microsoft.com/en-us/p/microsoft-people/9nblggh10pg8" + Description = "Contact management app" + } - $action = New-ScheduledTaskAction -Execute 'powershell.exe' ` - -Argument "-NoLogo -NoProfile -NonInteractive -WindowStyle Hidden -ExecutionPolicy Bypass -File `"$hardeningFile`"" - $trigger = New-ScheduledTaskTrigger -AtStartup + "Microsoft.PowerAutomateDesktop" = @{ + VDIState = "Unchanged" + URL = "https://flow.microsoft.com/en-us/desktop/" + Description = "Power Automate Desktop app. Record desktop and web actions in a single flow" + } - $taskName = 'Hard-Disable-AppXSvc' - $taskPath = '\Hardening\' + "Microsoft.ScreenSketch" = @{ + VDIState = "Unchanged" + URL = "https://www.microsoft.com/en-us/p/snip-sketch/9mz95kl8mr0l" + Description = "Snip and Sketch app" + } - Unregister-ScheduledTask -TaskName $taskName -TaskPath $taskPath -Confirm:$false -ErrorAction SilentlyContinue + "Microsoft.SkypeApp" = @{ + VDIState = "Unchanged" + URL = "https://www.microsoft.com/en-us/p/skype/9wzdncrfj364" + Description = "Instant message, voice or video call app" + } - Register-ScheduledTask -TaskName $taskName ` - -TaskPath $taskPath ` - -Action $action ` - -Trigger $trigger ` - -RunLevel Highest ` - -User 'SYSTEM' ` - -Force | Out-Null -} + "Microsoft.StorePurchaseApp" = @{ + VDIState = "Unchanged" + URL = "" + Description = "Store purchase app helper" + } -function Test-AppXSvcDisabled { - [CmdletBinding()] - param() + "Microsoft.Todos" = @{ + VDIState = "Unchanged" + URL = "https://www.microsoft.com/en-us/p/microsoft-to-do-lists-tasks-reminders/9nblggh5r558" + Description = "Microsoft To Do makes it easy to plan your day and manage your life" + } + + "Microsoft.WinDbg.Fast" = @{ + VDIState = "Unchanged" + URL = "https://apps.microsoft.com/detail/9PGJGD53TN86?hl=en-us&gl=US" + Description = "Microsoft WinDbg" + } - $svc = Get-Service -Name $svcName -ErrorAction SilentlyContinue - if ($null -eq $svc) { return $true } + "Microsoft.Windows.DevHome" = @{ + VDIState = "Unchanged" + URL = "https://learn.microsoft.com/en-us/windows/dev-home/" + Description = "A control center providing the ability to monitor projects in your dashboard using customizable widgets and more" + } - # Registry is the most reliable indicator (Start=4) - $regStart = $null - try { - $regStart = (Get-ItemProperty -Path $svcKeyPath -Name Start -ErrorAction SilentlyContinue).Start - } catch { } + "Microsoft.Windows.Photos" = @{ + VDIState = "Unchanged" + URL = "https://www.microsoft.com/en-us/p/microsoft-photos/9wzdncrfjbh4" + Description = "Photo and video editor" + } - $regDisabled = ($regStart -eq 4) + "Microsoft.WindowsAlarms" = @{ + VDIState = "Unchanged" + URL = "https://www.microsoft.com/en-us/p/windows-alarms-clock/9wzdncrfj3pr" + Description = "A combination app of alarm clock, world clock, timer, and stopwatch." + } - # CIM is a helpful second signal (StartMode: Auto/Manual/Disabled) - $cimDisabled = $false - $cimStartMode = 'Unknown' - try { - $svcCim = Get-CimInstance Win32_Service -Filter "Name='$svcName'" -ErrorAction SilentlyContinue - if ($svcCim) { - $cimStartMode = $svcCim.StartMode - $cimDisabled = ($svcCim.StartMode -eq 'Disabled') - } - } catch { } + "Microsoft.WindowsCalculator" = @{ + VDIState = "Unchanged" + URL = "https://www.microsoft.com/en-us/p/windows-calculator/9wzdncrfhvn5" + Description = "Microsoft Calculator app" + } - if ($svc.Status -eq 'Stopped' -and ($regDisabled -or $cimDisabled)) { - return $true + "Microsoft.WindowsCamera" = @{ + VDIState = "Unchanged" + URL = "https://www.microsoft.com/en-us/p/windows-camera/9wzdncrfjbbg" + Description = "Camera app to manage photos and video" } - return $false -} + "microsoft.windowscommunicationsapps" = @{ + VDIState = "Unchanged" + URL = "https://www.microsoft.com/en-us/p/mail-and-calendar/9wzdncrfhvqm" + Description = "Mail & Calendar apps" + } + + "Microsoft.WindowsFeedbackHub" = @{ + VDIState = "Unchanged" + URL = "https://www.microsoft.com/en-us/p/feedback-hub/9nblggh4r32n" + Description = "App to provide Feedback on Windows and apps to Microsoft" + } + + "Microsoft.WindowsMaps" = @{ + VDIState = "Unchanged" + URL = "https://www.microsoft.com/en-us/p/windows-maps/9wzdncrdtbvb" + Description = "Microsoft Maps app" + } + + "Microsoft.WindowsNotepad" = @{ + VDIState = "Unchanged" + URL = "https://www.microsoft.com/en-us/p/windows-notepad/9msmlrh6lzf3" + Description = "Fast, simple text editor for plain text documents and source code files." + } -# --- Main flow --------------------------------------------------------------- + "Microsoft.WindowsStore" = @{ + VDIState = "Unchanged" + URL = "https://blogs.windows.com/windowsexperience/2021/06/24/building-a-new-open-microsoft-store-on-windows-11/" + Description = "Windows Store app" + } + + "Microsoft.WindowsSoundRecorder" = @{ + VDIState = "Unchanged" + URL = "https://www.microsoft.com/en-us/p/windows-voice-recorder/9wzdncrfhwkn" + Description = "(Voice recorder)" + } + + "Microsoft.WindowsTerminal" = @{ + VDIState = "Unchanged" + URL = "https://www.microsoft.com/en-us/p/windows-terminal/9n0dx20hk701" + Description = "A terminal app featuring tabs, panes, Unicode, UTF-8 character support, and a GPU text rendering engine." + } + + "Microsoft.Winget.Platform.Source" = @{ + VDIState = "Unchanged" + URL = "https://learn.microsoft.com/en-us/windows/package-manager/winget/" + Description = "The Winget tool enables users to manage applications on Win10 and Win11 devices. This tool is the client interface to the Windows Package Manager service" + } + + "Microsoft.Xbox.TCUI" = @{ + VDIState = "Unchanged" + URL = "https://docs.microsoft.com/en-us/gaming/xbox-live/features/general/tcui/live-tcui-overview" + Description = "XBox Title Callable UI (TCUI) enables your game code to call pre-defined user interface displays" + } -try { - Write-Log -message 'uninstall_appx_packages :: begin' -severity 'DEBUG' + "Microsoft.XboxIdentityProvider" = @{ + VDIState = "Unchanged" + URL = "https://www.microsoft.com/en-us/p/xbox-identity-provider/9wzdncrd1hkw" + Description = "A system app that enables PC games to connect to Xbox Live." + } - Write-Log -message 'uninstall_appx_packages :: Remove-PreinstalledAppxPackages' -severity 'DEBUG' - Remove-PreinstalledAppxPackages + "Microsoft.XboxSpeechToTextOverlay" = @{ + VDIState = "Unchanged" + URL = "https://support.xbox.com/help/account-profile/accessibility/use-game-chat-transcription" + Description = "Xbox game transcription overlay" + } - Write-Log -message 'uninstall_appx_packages :: Disable-AppXSvcCore' -severity 'DEBUG' - Disable-AppXSvcCore + "Microsoft.YourPhone" = @{ + VDIState = "Unchanged" + URL = "https://www.microsoft.com/en-us/p/Your-phone/9nmpj99vjbwv" + Description = "Android phone to PC device interface app" + } - Write-Log -message 'uninstall_appx_packages :: Ensure-AppXSvcHardeningTask' -severity 'DEBUG' - Ensure-AppXSvcHardeningTask + "Microsoft.ZuneMusic" = @{ + VDIState = "Unchanged" + URL = "https://www.microsoft.com/en-us/p/groove-music/9wzdncrfj3pt" + Description = "Groove Music app" + } - if (-not (Test-AppXSvcDisabled)) { - $svc = Get-Service -Name $svcName -ErrorAction SilentlyContinue - $status = if ($svc) { $svc.Status } else { 'Missing' } + "Microsoft.ZuneVideo" = @{ + VDIState = "Unchanged" + URL = "https://www.microsoft.com/en-us/p/movies-tv/9wzdncrfj3p2" + Description = "Movies and TV app" + } - $regStart = $null - try { $regStart = (Get-ItemProperty -Path $svcKeyPath -Name Start -ErrorAction SilentlyContinue).Start } catch { } - $regStartStr = if ($null -ne $regStart) { $regStart } else { 'Missing' } + "MicrosoftCorporationII.QuickAssist" = @{ + VDIState = "Unchanged" + URL = "https://apps.microsoft.com/detail/9P7BP5VNWKX5?hl=en-us&gl=US" + Description = "Microsoft remote help app" + } - $cimStartMode = 'Unknown' - try { - $svcCim = Get-CimInstance Win32_Service -Filter "Name='$svcName'" -ErrorAction SilentlyContinue - if ($svcCim) { $cimStartMode = $svcCim.StartMode } - } catch { } + "MicrosoftWindows.Client.WebExperience" = @{ + VDIState = "Unchanged" + URL = "" + Description = "Windows 11 Internet information widget" + } - Write-Log -message ("uninstall_appx_packages :: AppXSvc is NOT disabled. Status: {0}, RegStart: {1}, CimStartMode: {2}" -f $status, $regStartStr, $cimStartMode) -severity 'ERROR' - exit 2 + "Microsoft.XboxApp" = @{ + VDIState = "Unchanged" + URL = "https://www.microsoft.com/store/apps/9wzdncrfjbd8" + Description = "Xbox 'Console Companion' app (games, friends, etc.)" } - Write-Log -message 'uninstall_appx_packages :: complete (AppXSvc disabled)' -severity 'DEBUG' - exit 0 + "Microsoft.MixedReality.Portal" = @{ + VDIState = "Unchanged" + URL = "https://www.microsoft.com/en-us/p/mixed-reality-portal/9ng1h8b3zc7m" + Description = "The app that facilitates Windows Mixed Reality setup, and serves as the command center for mixed reality experiences" + } + + "Microsoft.Microsoft3DViewer" = @{ + VDIState = "Unchanged" + URL = "https://www.microsoft.com/en-us/p/3d-viewer/9nblggh42ths" + Description = "App to view common 3D file types" + } + + "MicrosoftTeams" = @{ + VDIState = "Unchanged" + URL = "https://apps.microsoft.com/detail/xp8bt8dw290mpq" + Description = "Microsoft communication platform" + } + + "MSTeams" = @{ + VDIState = "Unchanged" + URL = "https://apps.microsoft.com/detail/xp8bt8dw290mpq" + Description = "Microsoft communication platform" + } + + "Microsoft.OneDriveSync" = @{ + VDIState = "Unchanged" + URL = "https://docs.microsoft.com/en-us/onedrive/one-drive-sync" + Description = "Microsoft OneDrive sync app (included in Office 2016 or later)" + } + + "Microsoft.Wallet" = @{ + VDIState = "Unchanged" + URL = "https://www.microsoft.com/en-us/payments" + Description = "(Microsoft Pay) for Edge browser on certain devices" + } } -catch { - Write-Log -message ("uninstall_appx_packages :: FATAL: {0}" -f $_.Exception.ToString()) -severity 'ERROR' - exit 1 + +foreach ($Key in $apps.Keys) { + $Item = $apps[$Key] + + Write-Host "Removing Provisioned Package $Key" + Get-AppxProvisionedPackage -Online | + Where-Object { $_.PackageName -like ("*{0}*" -f $Key) } | + Remove-AppxProvisionedPackage -Online -ErrorAction SilentlyContinue | + Out-Null + + Write-Host "Attempting to remove [All Users] $Key - $($Item.Description)" + Get-AppxPackage -AllUsers -Name ("*{0}*" -f $Key) | + Remove-AppxPackage -AllUsers -ErrorAction SilentlyContinue + + Write-Host "Attempting to remove $Key - $($Item.Description)" + Get-AppxPackage -Name ("*{0}*" -f $Key) | + Remove-AppxPackage -ErrorAction SilentlyContinue | + Out-Null } diff --git a/modules/win_disable_services/files/appxpackages/uninstall.ps1.BAK b/modules/win_disable_services/files/appxpackages/uninstall.ps1.BAK deleted file mode 100644 index 4778d3e8e..000000000 --- a/modules/win_disable_services/files/appxpackages/uninstall.ps1.BAK +++ /dev/null @@ -1,320 +0,0 @@ -$apps = @{ - "Bing Search" = @{ - VDIState = "Unchanged" - URL = "https://apps.microsoft.com/detail/9nzbf4gt040c" - Description = "Web Search from Microsoft Bing provides web results and answers in Windows Search" - } - - "Clipchamp.Clipchamp" = @{ - VDIState = "Unchanged" - URL = "https://apps.microsoft.com/detail/9p1j8s7ccwwt?hl=en-us&gl=US" - Description = "Create videos with a few clicks" - } - - "Microsoft.549981C3F5F10" = @{ - VDIState = "Unchanged" - URL = "https://apps.microsoft.com/detail/cortana/9NFFX4SZZ23L?hl=en-us&gl=US" - Description = "Cortana (could not update)" - } - - "Microsoft.BingNews" = @{ - VDIState = "Unchanged" - URL = "https://www.microsoft.com/en-us/p/microsoft-news/9wzdncrfhvfw" - Description = "Microsoft News app" - } - - "Microsoft.BingWeather" = @{ - VDIState = "Unchanged" - URL = "https://www.microsoft.com/en-us/p/msn-weather/9wzdncrfj3q2" - Description = "MSN Weather app" - } - - "Microsoft.DesktopAppInstaller" = @{ - VDIState = "Unchanged" - URL = "https://apps.microsoft.com/detail/9NBLGGH4NNS1" - Description = "Microsoft App Installer for Windows 10 makes sideloading Windows apps easy" - } - - "Microsoft.GetHelp" = @{ - VDIState = "Unchanged" - URL = "https://docs.microsoft.com/en-us/windows-hardware/customize/desktop/customize-get-help-app" - Description = "App that facilitates free support for Microsoft products" - } - - "Microsoft.Getstarted" = @{ - VDIState = "Unchanged" - URL = "https://www.microsoft.com/en-us/p/microsoft-tips/9wzdncrdtbjj" - Description = "Windows 10 tips app" - } - - "Microsoft.MicrosoftOfficeHub" = @{ - VDIState = "Unchanged" - URL = "https://www.microsoft.com/en-us/p/office/9wzdncrd29v9" - Description = "Office UWP app suite" - } - - "Microsoft.Office.OneNote" = @{ - VDIState = "Unchanged" - URL = "https://www.microsoft.com/en-us/p/onenote-for-windows-10/9wzdncrfhvjl" - Description = "Office UWP OneNote app" - } - - "Microsoft.MicrosoftSolitaireCollection" = @{ - VDIState = "Unchanged" - URL = "https://www.microsoft.com/en-us/p/microsoft-solitaire-collection/9wzdncrfhwd2" - Description = "Solitaire suite of games" - } - - "Microsoft.MicrosoftStickyNotes" = @{ - VDIState = "Unchanged" - URL = "https://www.microsoft.com/en-us/p/microsoft-sticky-notes/9nblggh4qghw" - Description = "Note-taking app" - } - - "Microsoft.OutlookForWindows" = @{ - VDIState = "Unchanged" - URL = "https://apps.microsoft.com/detail/9NRX63209R7B?hl=en-us&gl=US" - Description = "A best-in-class email experience that is free for anyone with Windows" - } - - "Microsoft.MSPaint" = @{ - VDIState = "Unchanged" - URL = "https://apps.microsoft.com/store/detail/paint-3d/9NBLGGH5FV99" - Description = "Paint 3D app (not Classic Paint app)" - } - - "Microsoft.Paint" = @{ - VDIState = "Unchanged" - URL = "https://apps.microsoft.com/detail/9PCFS5B6T72H" - Description = "Classic Paint app" - } - - "Microsoft.People" = @{ - VDIState = "Unchanged" - URL = "https://www.microsoft.com/en-us/p/microsoft-people/9nblggh10pg8" - Description = "Contact management app" - } - - "Microsoft.PowerAutomateDesktop" = @{ - VDIState = "Unchanged" - URL = "https://flow.microsoft.com/en-us/desktop/" - Description = "Power Automate Desktop app. Record desktop and web actions in a single flow" - } - - "Microsoft.ScreenSketch" = @{ - VDIState = "Unchanged" - URL = "https://www.microsoft.com/en-us/p/snip-sketch/9mz95kl8mr0l" - Description = "Snip and Sketch app" - } - - "Microsoft.SkypeApp" = @{ - VDIState = "Unchanged" - URL = "https://www.microsoft.com/en-us/p/skype/9wzdncrfj364" - Description = "Instant message, voice or video call app" - } - - "Microsoft.StorePurchaseApp" = @{ - VDIState = "Unchanged" - URL = "" - Description = "Store purchase app helper" - } - - "Microsoft.Todos" = @{ - VDIState = "Unchanged" - URL = "https://www.microsoft.com/en-us/p/microsoft-to-do-lists-tasks-reminders/9nblggh5r558" - Description = "Microsoft To Do makes it easy to plan your day and manage your life" - } - - "Microsoft.WinDbg.Fast" = @{ - VDIState = "Unchanged" - URL = "https://apps.microsoft.com/detail/9PGJGD53TN86?hl=en-us&gl=US" - Description = "Microsoft WinDbg" - } - - "Microsoft.Windows.DevHome" = @{ - VDIState = "Unchanged" - URL = "https://learn.microsoft.com/en-us/windows/dev-home/" - Description = "A control center providing the ability to monitor projects in your dashboard using customizable widgets and more" - } - - "Microsoft.Windows.Photos" = @{ - VDIState = "Unchanged" - URL = "https://www.microsoft.com/en-us/p/microsoft-photos/9wzdncrfjbh4" - Description = "Photo and video editor" - } - - "Microsoft.WindowsAlarms" = @{ - VDIState = "Unchanged" - URL = "https://www.microsoft.com/en-us/p/windows-alarms-clock/9wzdncrfj3pr" - Description = "A combination app of alarm clock, world clock, timer, and stopwatch." - } - - "Microsoft.WindowsCalculator" = @{ - VDIState = "Unchanged" - URL = "https://www.microsoft.com/en-us/p/windows-calculator/9wzdncrfhvn5" - Description = "Microsoft Calculator app" - } - - "Microsoft.WindowsCamera" = @{ - VDIState = "Unchanged" - URL = "https://www.microsoft.com/en-us/p/windows-camera/9wzdncrfjbbg" - Description = "Camera app to manage photos and video" - } - - "microsoft.windowscommunicationsapps" = @{ - VDIState = "Unchanged" - URL = "https://www.microsoft.com/en-us/p/mail-and-calendar/9wzdncrfhvqm" - Description = "Mail & Calendar apps" - } - - "Microsoft.WindowsFeedbackHub" = @{ - VDIState = "Unchanged" - URL = "https://www.microsoft.com/en-us/p/feedback-hub/9nblggh4r32n" - Description = "App to provide Feedback on Windows and apps to Microsoft" - } - - "Microsoft.WindowsMaps" = @{ - VDIState = "Unchanged" - URL = "https://www.microsoft.com/en-us/p/windows-maps/9wzdncrdtbvb" - Description = "Microsoft Maps app" - } - - "Microsoft.WindowsNotepad" = @{ - VDIState = "Unchanged" - URL = "https://www.microsoft.com/en-us/p/windows-notepad/9msmlrh6lzf3" - Description = "Fast, simple text editor for plain text documents and source code files." - } - - "Microsoft.WindowsStore" = @{ - VDIState = "Unchanged" - URL = "https://blogs.windows.com/windowsexperience/2021/06/24/building-a-new-open-microsoft-store-on-windows-11/" - Description = "Windows Store app" - } - - "Microsoft.WindowsSoundRecorder" = @{ - VDIState = "Unchanged" - URL = "https://www.microsoft.com/en-us/p/windows-voice-recorder/9wzdncrfhwkn" - Description = "(Voice recorder)" - } - - "Microsoft.WindowsTerminal" = @{ - VDIState = "Unchanged" - URL = "https://www.microsoft.com/en-us/p/windows-terminal/9n0dx20hk701" - Description = "A terminal app featuring tabs, panes, Unicode, UTF-8 character support, and a GPU text rendering engine." - } - - "Microsoft.Winget.Platform.Source" = @{ - VDIState = "Unchanged" - URL = "https://learn.microsoft.com/en-us/windows/package-manager/winget/" - Description = "The Winget tool enables users to manage applications on Win10 and Win11 devices. This tool is the client interface to the Windows Package Manager service" - } - - "Microsoft.Xbox.TCUI" = @{ - VDIState = "Unchanged" - URL = "https://docs.microsoft.com/en-us/gaming/xbox-live/features/general/tcui/live-tcui-overview" - Description = "XBox Title Callable UI (TCUI) enables your game code to call pre-defined user interface displays" - } - - "Microsoft.XboxIdentityProvider" = @{ - VDIState = "Unchanged" - URL = "https://www.microsoft.com/en-us/p/xbox-identity-provider/9wzdncrd1hkw" - Description = "A system app that enables PC games to connect to Xbox Live." - } - - "Microsoft.XboxSpeechToTextOverlay" = @{ - VDIState = "Unchanged" - URL = "https://support.xbox.com/help/account-profile/accessibility/use-game-chat-transcription" - Description = "Xbox game transcription overlay" - } - - "Microsoft.YourPhone" = @{ - VDIState = "Unchanged" - URL = "https://www.microsoft.com/en-us/p/Your-phone/9nmpj99vjbwv" - Description = "Android phone to PC device interface app" - } - - "Microsoft.ZuneMusic" = @{ - VDIState = "Unchanged" - URL = "https://www.microsoft.com/en-us/p/groove-music/9wzdncrfj3pt" - Description = "Groove Music app" - } - - "Microsoft.ZuneVideo" = @{ - VDIState = "Unchanged" - URL = "https://www.microsoft.com/en-us/p/movies-tv/9wzdncrfj3p2" - Description = "Movies and TV app" - } - - "MicrosoftCorporationII.QuickAssist" = @{ - VDIState = "Unchanged" - URL = "https://apps.microsoft.com/detail/9P7BP5VNWKX5?hl=en-us&gl=US" - Description = "Microsoft remote help app" - } - - "MicrosoftWindows.Client.WebExperience" = @{ - VDIState = "Unchanged" - URL = "" - Description = "Windows 11 Internet information widget" - } - - "Microsoft.XboxApp" = @{ - VDIState = "Unchanged" - URL = "https://www.microsoft.com/store/apps/9wzdncrfjbd8" - Description = "Xbox 'Console Companion' app (games, friends, etc.)" - } - - "Microsoft.MixedReality.Portal" = @{ - VDIState = "Unchanged" - URL = "https://www.microsoft.com/en-us/p/mixed-reality-portal/9ng1h8b3zc7m" - Description = "The app that facilitates Windows Mixed Reality setup, and serves as the command center for mixed reality experiences" - } - - "Microsoft.Microsoft3DViewer" = @{ - VDIState = "Unchanged" - URL = "https://www.microsoft.com/en-us/p/3d-viewer/9nblggh42ths" - Description = "App to view common 3D file types" - } - - "MicrosoftTeams" = @{ - VDIState = "Unchanged" - URL = "https://apps.microsoft.com/detail/xp8bt8dw290mpq" - Description = "Microsoft communication platform" - } - - "MSTeams" = @{ - VDIState = "Unchanged" - URL = "https://apps.microsoft.com/detail/xp8bt8dw290mpq" - Description = "Microsoft communication platform" - } - - "Microsoft.OneDriveSync" = @{ - VDIState = "Unchanged" - URL = "https://docs.microsoft.com/en-us/onedrive/one-drive-sync" - Description = "Microsoft OneDrive sync app (included in Office 2016 or later)" - } - - "Microsoft.Wallet" = @{ - VDIState = "Unchanged" - URL = "https://www.microsoft.com/en-us/payments" - Description = "(Microsoft Pay) for Edge browser on certain devices" - } -} - -foreach ($Key in $apps.Keys) { - $Item = $apps[$Key] - - Write-Host "Removing Provisioned Package $Key" - Get-AppxProvisionedPackage -Online | - Where-Object { $_.PackageName -like ("*{0}*" -f $Key) } | - Remove-AppxProvisionedPackage -Online -ErrorAction SilentlyContinue | - Out-Null - - Write-Host "Attempting to remove [All Users] $Key - $($Item.Description)" - Get-AppxPackage -AllUsers -Name ("*{0}*" -f $Key) | - Remove-AppxPackage -AllUsers -ErrorAction SilentlyContinue - - Write-Host "Attempting to remove $Key - $($Item.Description)" - Get-AppxPackage -Name ("*{0}*" -f $Key) | - Remove-AppxPackage -ErrorAction SilentlyContinue | - Out-Null -} diff --git a/modules/win_disable_services/manifests/uninstall_appx_packages.pp b/modules/win_disable_services/manifests/uninstall_appx_packages.pp index 3a9c85cfd..cc6fa66bd 100644 --- a/modules/win_disable_services/manifests/uninstall_appx_packages.pp +++ b/modules/win_disable_services/manifests/uninstall_appx_packages.pp @@ -1,12 +1,14 @@ # This class is responsible for disabling AppX packages on Windows. -class win_disable_services::uninstall_appx_packages { +class win_disable_services::uninstall_appx_packages ( + $apx_uninstall +){ $ronin_base = $facts['custom_win_roninprogramdata'] $script_path = "${ronin_base}\\win_uninstall_appx_packages.ps1" file { $script_path: ensure => file, - content => file('win_disable_services/appxpackages/uninstall.ps1'), + content => file("win_disable_services/appxpackages/${apx_uninstall}"), } include win_disable_services::disable_ms_edge From 39a69e6a6135c9a7be85f6b1b9f90180ac619a31 Mon Sep 17 00:00:00 2001 From: Mark Cornmesser Date: Thu, 15 Jan 2026 15:14:20 -0800 Subject: [PATCH 097/105] do not run disable optional services for Azure --- modules/roles_profiles/manifests/profiles/disable_services.pp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/modules/roles_profiles/manifests/profiles/disable_services.pp b/modules/roles_profiles/manifests/profiles/disable_services.pp index cf96e99cf..73f78c97f 100644 --- a/modules/roles_profiles/manifests/profiles/disable_services.pp +++ b/modules/roles_profiles/manifests/profiles/disable_services.pp @@ -39,7 +39,6 @@ include win_disable_services::disable_windows_update if $facts['custom_win_purpose'] != builder { include win_disable_services::disable_wsearch - include win_disable_services::disable_optional_services ## WIP for RELOPS-1946 ## Not currently working. Leaving n place for ref. #include win_disable_services::disable_defender_smartscreen @@ -51,6 +50,7 @@ case $facts['custom_win_location'] { 'datacenter': { $apx_uninstall = 'hw-uninstall.ps1' + include win_disable_services::disable_optional_services } 'azure': { include win_scheduled_tasks::kill_local_clipboard From 8e10d4c8ba09e7f4b9a5007c1593f99402715983 Mon Sep 17 00:00:00 2001 From: Mark Cornmesser Date: Thu, 15 Jan 2026 16:36:26 -0800 Subject: [PATCH 098/105] do not run disable edge services Azure --- modules/roles_profiles/manifests/profiles/disable_services.pp | 1 + .../win_disable_services/manifests/uninstall_appx_packages.pp | 2 -- 2 files changed, 1 insertion(+), 2 deletions(-) diff --git a/modules/roles_profiles/manifests/profiles/disable_services.pp b/modules/roles_profiles/manifests/profiles/disable_services.pp index 73f78c97f..049183373 100644 --- a/modules/roles_profiles/manifests/profiles/disable_services.pp +++ b/modules/roles_profiles/manifests/profiles/disable_services.pp @@ -51,6 +51,7 @@ 'datacenter': { $apx_uninstall = 'hw-uninstall.ps1' include win_disable_services::disable_optional_services + include win_disable_services::disable_ms_edge } 'azure': { include win_scheduled_tasks::kill_local_clipboard diff --git a/modules/win_disable_services/manifests/uninstall_appx_packages.pp b/modules/win_disable_services/manifests/uninstall_appx_packages.pp index cc6fa66bd..ceea6d285 100644 --- a/modules/win_disable_services/manifests/uninstall_appx_packages.pp +++ b/modules/win_disable_services/manifests/uninstall_appx_packages.pp @@ -11,8 +11,6 @@ content => file("win_disable_services/appxpackages/${apx_uninstall}"), } - include win_disable_services::disable_ms_edge - exec { 'disable_appx_packages': # Call the script file from PowerShell provider command => "& '${script_path}'", From 96510aaa61118f1930835e96bb28d7cb9bb3e420 Mon Sep 17 00:00:00 2001 From: Mark Cornmesser Date: Fri, 16 Jan 2026 08:48:34 -0800 Subject: [PATCH 099/105] revert hw gw ver --- data/os/Windows.yaml | 2 +- .../manifests/profiles/windows_worker_runner.pp | 14 ++++---------- 2 files changed, 5 insertions(+), 11 deletions(-) diff --git a/data/os/Windows.yaml b/data/os/Windows.yaml index d9999b7e8..e8c72fe17 100644 --- a/data/os/Windows.yaml +++ b/data/os/Windows.yaml @@ -56,7 +56,7 @@ windows: relops_s3: "https://s3-us-west-2.amazonaws.com/ronin-puppet-package-repo/Windows/taskcluster" download_url: "https://github.com/taskcluster/taskcluster/releases/download" version: "95.1.1" - hw_version: "93.1.4" + hw_version: "91.1.0" generic-worker: name: amd64: "generic-worker-multiuser-windows-amd64" diff --git a/modules/roles_profiles/manifests/profiles/windows_worker_runner.pp b/modules/roles_profiles/manifests/profiles/windows_worker_runner.pp index 52b663285..2284a628b 100644 --- a/modules/roles_profiles/manifests/profiles/windows_worker_runner.pp +++ b/modules/roles_profiles/manifests/profiles/windows_worker_runner.pp @@ -13,20 +13,14 @@ 'datacenter': { $ext_pkg_src_loc = "${lookup('windows.taskcluster.relops_az')}/" $provider = 'standalone' + $taskcluster_version = + lookup(['win-worker.variant.taskcluster.version', 'windows.taskcluster.hw_version']) } default: { $ext_pkg_src_loc = "${lookup('windows.taskcluster.download_url')}/v" $provider = lookup('windows.taskcluster.worker_runner.provider') - } - } - case $facts['custom_win_location'] { - 'datacenter': { - $taskcluster_version = - lookup(['win-worker.variant.taskcluster.version', 'windows.taskcluster.hw_version']) - } - default: { - $taskcluster_version = - lookup(['win-worker.variant.taskcluster.version', 'windows.taskcluster.version']) + $taskcluster_version = + lookup(['win-worker.variant.taskcluster.version', 'windows.taskcluster.version']) } } case $facts['custom_win_os_arch'] { From e2cfdb7fa02d50eefb7267d0142a009fbbf88415 Mon Sep 17 00:00:00 2001 From: Mark Cornmesser Date: Fri, 16 Jan 2026 10:50:00 -0800 Subject: [PATCH 100/105] clean up --- modules/win_scheduled_tasks/files/at_task_user_logon.ps1 | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/modules/win_scheduled_tasks/files/at_task_user_logon.ps1 b/modules/win_scheduled_tasks/files/at_task_user_logon.ps1 index fb1f69325..b9c06fca1 100644 --- a/modules/win_scheduled_tasks/files/at_task_user_logon.ps1 +++ b/modules/win_scheduled_tasks/files/at_task_user_logon.ps1 @@ -592,8 +592,9 @@ switch ($os_version) { Remove-OneDriveScheduledTasks Disable-OneDriveBackupPopup Remove-EdgeScheduledTasks - Disable-SyncFromCloud - Disable-SmartScreenStoreApps + ## Not currently functioning + #Disable-SyncFromCloud + #Disable-SmartScreenStoreApps } "win_2022" { ## Disable Server Manager Dashboard From 2386d71b32e0d13af1843592648b0cc2687d6b88 Mon Sep 17 00:00:00 2001 From: Mark Cornmesser Date: Fri, 16 Jan 2026 13:04:45 -0800 Subject: [PATCH 101/105] clean up --- .../files/at_task_user_logon.ps1 | 33 +++++++++++++++---- 1 file changed, 26 insertions(+), 7 deletions(-) diff --git a/modules/win_scheduled_tasks/files/at_task_user_logon.ps1 b/modules/win_scheduled_tasks/files/at_task_user_logon.ps1 index b9c06fca1..34a43ef4e 100644 --- a/modules/win_scheduled_tasks/files/at_task_user_logon.ps1 +++ b/modules/win_scheduled_tasks/files/at_task_user_logon.ps1 @@ -563,6 +563,23 @@ else { $os_version = $null } +$worker_location = $null +try { + $image_provisioner = Get-ItemPropertyValue -Path 'HKLM:\SOFTWARE\Mozilla\ronin_puppet' -Name 'image_provisioner' -ErrorAction Stop +} catch { + Write-Log -message ("Unable to read HKLM:\SOFTWARE\Mozilla\ronin_puppet\image_provisioner: {0}" -f $_.Exception.Message) -severity 'ERROR' + exit 1 +} + +if ($image_provisioner -match '(?i)mdc1') { + $worker_location = 'MDC1 hardware' +} elseif ($image_provisioner -match '(?i)azure') { + $worker_location = 'azure vm' +} else { + Write-Log -message ("Location can't be determined (image_provisioner='{0}')" -f $image_provisioner) -severity 'ERROR' + exit 1 +} + ## Wait until explorer is set in the registry and then suppress notifications for firewall while ($true) { $explorer = Get-ItemProperty -Path "HKCU:\Software\Microsoft\Windows\CurrentVersion\Explorer" -ErrorAction SilentlyContinue @@ -588,13 +605,15 @@ switch ($os_version) { "win_11_2009" { Write-Log -Message ('{0} :: {1} - {2:o}' -f $($MyInvocation.MyCommand.Name), "Setting scrollbars to always show in task-user-init.ps1", (Get-Date).ToUniversalTime()) -severity 'DEBUG' New-ItemProperty -Path 'HKCU:\Control Panel\Accessibility' -Name 'DynamicScrollbars' -Value 0 -Force - Disable-PerUserUwpServices - Remove-OneDriveScheduledTasks - Disable-OneDriveBackupPopup - Remove-EdgeScheduledTasks - ## Not currently functioning - #Disable-SyncFromCloud - #Disable-SmartScreenStoreApps + if ($worker_location -eq 'MDC1 hardware') { + Disable-PerUserUwpServices + Remove-OneDriveScheduledTasks + Disable-OneDriveBackupPopup + Remove-EdgeScheduledTasks + ## Not currently functioning + #Disable-SyncFromCloud + #Disable-SmartScreenStoreApps + } } "win_2022" { ## Disable Server Manager Dashboard From d780af8d3af96f69a4503d28c8bb471a57e5f29f Mon Sep 17 00:00:00 2001 From: Mark Cornmesser Date: Fri, 16 Jan 2026 14:16:14 -0800 Subject: [PATCH 102/105] revert azure TC version --- data/os/Windows.yaml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/data/os/Windows.yaml b/data/os/Windows.yaml index e8c72fe17..3085addbf 100644 --- a/data/os/Windows.yaml +++ b/data/os/Windows.yaml @@ -55,7 +55,7 @@ windows: relops_az: "https://roninpuppetassets.blob.core.windows.net/binaries/taskcluster" relops_s3: "https://s3-us-west-2.amazonaws.com/ronin-puppet-package-repo/Windows/taskcluster" download_url: "https://github.com/taskcluster/taskcluster/releases/download" - version: "95.1.1" + version: "93.1.4" hw_version: "91.1.0" generic-worker: name: From 82865dbb7befca248487888b93aedf61db550950 Mon Sep 17 00:00:00 2001 From: Mark Cornmesser Date: Fri, 16 Jan 2026 15:09:02 -0800 Subject: [PATCH 103/105] try apx untinstall twice --- .../win_disable_services/manifests/uninstall_appx_packages.pp | 1 + 1 file changed, 1 insertion(+) diff --git a/modules/win_disable_services/manifests/uninstall_appx_packages.pp b/modules/win_disable_services/manifests/uninstall_appx_packages.pp index ceea6d285..063ddbfee 100644 --- a/modules/win_disable_services/manifests/uninstall_appx_packages.pp +++ b/modules/win_disable_services/manifests/uninstall_appx_packages.pp @@ -19,5 +19,6 @@ logoutput => true, returns => [0], require => File[$script_path], + tries => 1, } } From 18d738aba8525015348fc1af7d2b22559625431d Mon Sep 17 00:00:00 2001 From: Mark Cornmesser Date: Fri, 16 Jan 2026 16:38:51 -0800 Subject: [PATCH 104/105] troubleshooting --- modules/roles_profiles/manifests/profiles/disable_services.pp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/modules/roles_profiles/manifests/profiles/disable_services.pp b/modules/roles_profiles/manifests/profiles/disable_services.pp index 049183373..fd0524d33 100644 --- a/modules/roles_profiles/manifests/profiles/disable_services.pp +++ b/modules/roles_profiles/manifests/profiles/disable_services.pp @@ -51,7 +51,7 @@ 'datacenter': { $apx_uninstall = 'hw-uninstall.ps1' include win_disable_services::disable_optional_services - include win_disable_services::disable_ms_edge + #include win_disable_services::disable_ms_edge } 'azure': { include win_scheduled_tasks::kill_local_clipboard From 82a53d0b6621b6dbbdd7d6e6e39ab9c9ca877702 Mon Sep 17 00:00:00 2001 From: Mark Cornmesser Date: Fri, 16 Jan 2026 19:58:38 -0800 Subject: [PATCH 105/105] troubleshooting --- .../roles_profiles/manifests/profiles/disable_services.pp | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/modules/roles_profiles/manifests/profiles/disable_services.pp b/modules/roles_profiles/manifests/profiles/disable_services.pp index fd0524d33..1617def02 100644 --- a/modules/roles_profiles/manifests/profiles/disable_services.pp +++ b/modules/roles_profiles/manifests/profiles/disable_services.pp @@ -51,7 +51,6 @@ 'datacenter': { $apx_uninstall = 'hw-uninstall.ps1' include win_disable_services::disable_optional_services - #include win_disable_services::disable_ms_edge } 'azure': { include win_scheduled_tasks::kill_local_clipboard @@ -66,6 +65,10 @@ class { 'win_disable_services::uninstall_appx_packages': apx_uninstall => $apx_uninstall } + ## must be ran after apx uninstall + if ($facts['custom_win_location'] == 'datacenter') { + include win_disable_services::disable_ms_edge + } } # May be needed for non-hardaware # Commented out because this will break the auto restore