<# .SYNOPSIS Removes CentraStage/Datto RMM agent from Windows machines. .DESCRIPTION This script safely uninstalls the CentraStage/Datto RMM agent by: - Stopping all CentraStage services - Running the uninstaller - Cleaning up residual files and registry entries - Removing scheduled tasks .PARAMETER Force Skip confirmation prompts .EXAMPLE .\Remove-CentraStage.ps1 Removes CentraStage with confirmation prompts .EXAMPLE .\Remove-CentraStage.ps1 -Force Removes CentraStage without confirmation .NOTES Author: ClaudeTools Requires: Administrator privileges Last Updated: 2026-01-23 #> [CmdletBinding()] param( [switch]$Force ) #Requires -RunAsAdministrator # ASCII markers only - no emojis function Write-Status { param( [string]$Message, [ValidateSet('INFO', 'SUCCESS', 'WARNING', 'ERROR')] [string]$Level = 'INFO' ) $timestamp = Get-Date -Format 'yyyy-MM-dd HH:mm:ss' $color = switch ($Level) { 'INFO' { 'Cyan' } 'SUCCESS' { 'Green' } 'WARNING' { 'Yellow' } 'ERROR' { 'Red' } } Write-Host "[$timestamp] [$Level] $Message" -ForegroundColor $color } # Check if running as administrator if (-not ([Security.Principal.WindowsPrincipal][Security.Principal.WindowsIdentity]::GetCurrent()).IsInRole([Security.Principal.WindowsBuiltInRole]::Administrator)) { Write-Status "This script must be run as Administrator" -Level ERROR exit 1 } Write-Status "Starting CentraStage/Datto RMM removal process" -Level INFO # Confirmation prompt if (-not $Force) { $confirm = Read-Host "This will remove CentraStage/Datto RMM from this machine. Continue? (Y/N)" if ($confirm -ne 'Y' -and $confirm -ne 'y') { Write-Status "Operation cancelled by user" -Level WARNING exit 0 } } # Define CentraStage service names $services = @( 'CagService', 'CentraStage', 'CagService*', 'Datto RMM' ) # Define installation paths $installPaths = @( "${env:ProgramFiles}\CentraStage", "${env:ProgramFiles(x86)}\CentraStage", "${env:ProgramFiles}\SYSTEMMONITOR", "${env:ProgramFiles(x86)}\SYSTEMMONITOR" ) # Define registry paths $registryPaths = @( 'HKLM:\SOFTWARE\CentraStage', 'HKLM:\SOFTWARE\WOW6432Node\CentraStage', 'HKLM:\SYSTEM\CurrentControlSet\Services\CagService', 'HKLM:\SYSTEM\CurrentControlSet\Services\CentraStage' ) # Stop all CentraStage services Write-Status "Stopping CentraStage services..." -Level INFO foreach ($serviceName in $services) { try { $matchingServices = Get-Service -Name $serviceName -ErrorAction SilentlyContinue foreach ($service in $matchingServices) { if ($service.Status -eq 'Running') { Write-Status "Stopping service: $($service.Name)" -Level INFO Stop-Service -Name $service.Name -Force -ErrorAction Stop Write-Status "Service stopped: $($service.Name)" -Level SUCCESS } } } catch { Write-Status "Could not stop service $serviceName: $_" -Level WARNING } } # Find and run uninstaller Write-Status "Looking for CentraStage uninstaller..." -Level INFO $uninstallers = @() # Check registry for uninstaller $uninstallKeys = @( 'HKLM:\SOFTWARE\Microsoft\Windows\CurrentVersion\Uninstall\*', 'HKLM:\SOFTWARE\WOW6432Node\Microsoft\Windows\CurrentVersion\Uninstall\*' ) foreach ($key in $uninstallKeys) { Get-ItemProperty $key -ErrorAction SilentlyContinue | Where-Object { $_.DisplayName -like '*CentraStage*' -or $_.DisplayName -like '*Datto RMM*' } | ForEach-Object { if ($_.UninstallString) { $uninstallers += $_.UninstallString Write-Status "Found uninstaller: $($_.DisplayName)" -Level INFO } } } # Check common installation paths for uninstaller foreach ($path in $installPaths) { $uninstallExe = Join-Path $path "uninstall.exe" if (Test-Path $uninstallExe) { $uninstallers += $uninstallExe Write-Status "Found uninstaller at: $uninstallExe" -Level INFO } } # Run uninstallers if ($uninstallers.Count -gt 0) { foreach ($uninstaller in $uninstallers) { try { Write-Status "Running uninstaller: $uninstaller" -Level INFO # Parse uninstall string if ($uninstaller -match '^"([^"]+)"(.*)$') { $exe = $matches[1] $args = $matches[2].Trim() } else { $exe = $uninstaller $args = "" } # Add silent parameters $silentArgs = "/S /VERYSILENT /SUPPRESSMSGBOXES /NORESTART" if ($args) { $args = "$args $silentArgs" } else { $args = $silentArgs } $process = Start-Process -FilePath $exe -ArgumentList $args -Wait -PassThru -NoNewWindow if ($process.ExitCode -eq 0) { Write-Status "Uninstaller completed successfully" -Level SUCCESS } else { Write-Status "Uninstaller exited with code: $($process.ExitCode)" -Level WARNING } } catch { Write-Status "Error running uninstaller: $_" -Level ERROR } } } else { Write-Status "No uninstaller found in registry or standard paths" -Level WARNING } # Remove services Write-Status "Removing CentraStage services..." -Level INFO foreach ($serviceName in $services) { try { $matchingServices = Get-Service -Name $serviceName -ErrorAction SilentlyContinue foreach ($service in $matchingServices) { Write-Status "Removing service: $($service.Name)" -Level INFO sc.exe delete $service.Name | Out-Null Write-Status "Service removed: $($service.Name)" -Level SUCCESS } } catch { Write-Status "Could not remove service $serviceName: $_" -Level WARNING } } # Remove installation directories Write-Status "Removing installation directories..." -Level INFO foreach ($path in $installPaths) { if (Test-Path $path) { try { Write-Status "Removing directory: $path" -Level INFO Remove-Item -Path $path -Recurse -Force -ErrorAction Stop Write-Status "Directory removed: $path" -Level SUCCESS } catch { Write-Status "Could not remove directory $path: $_" -Level WARNING } } } # Remove registry entries Write-Status "Removing registry entries..." -Level INFO foreach ($regPath in $registryPaths) { if (Test-Path $regPath) { try { Write-Status "Removing registry key: $regPath" -Level INFO Remove-Item -Path $regPath -Recurse -Force -ErrorAction Stop Write-Status "Registry key removed: $regPath" -Level SUCCESS } catch { Write-Status "Could not remove registry key $regPath: $_" -Level WARNING } } } # Remove scheduled tasks Write-Status "Removing CentraStage scheduled tasks..." -Level INFO try { $tasks = Get-ScheduledTask -TaskPath '\' -ErrorAction SilentlyContinue | Where-Object { $_.TaskName -like '*CentraStage*' -or $_.TaskName -like '*Datto*' -or $_.TaskName -like '*Cag*' } foreach ($task in $tasks) { Write-Status "Removing scheduled task: $($task.TaskName)" -Level INFO Unregister-ScheduledTask -TaskName $task.TaskName -Confirm:$false -ErrorAction Stop Write-Status "Scheduled task removed: $($task.TaskName)" -Level SUCCESS } } catch { Write-Status "Error removing scheduled tasks: $_" -Level WARNING } # Final verification Write-Status "Verifying removal..." -Level INFO $remainingServices = Get-Service -Name 'Cag*','*CentraStage*','*Datto*' -ErrorAction SilentlyContinue $remainingPaths = $installPaths | Where-Object { Test-Path $_ } $remainingRegistry = $registryPaths | Where-Object { Test-Path $_ } if ($remainingServices.Count -eq 0 -and $remainingPaths.Count -eq 0 -and $remainingRegistry.Count -eq 0) { Write-Status "CentraStage/Datto RMM successfully removed!" -Level SUCCESS Write-Status "A system restart is recommended" -Level INFO } else { Write-Status "Removal completed with warnings:" -Level WARNING if ($remainingServices.Count -gt 0) { Write-Status " - $($remainingServices.Count) service(s) still present" -Level WARNING } if ($remainingPaths.Count -gt 0) { Write-Status " - $($remainingPaths.Count) directory/directories still present" -Level WARNING } if ($remainingRegistry.Count -gt 0) { Write-Status " - $($remainingRegistry.Count) registry key(s) still present" -Level WARNING } } # Ask about restart if (-not $Force) { $restart = Read-Host "Would you like to restart the computer now? (Y/N)" if ($restart -eq 'Y' -or $restart -eq 'y') { Write-Status "Restarting computer in 10 seconds..." -Level WARNING shutdown /r /t 10 /c "Restarting after CentraStage removal" } } Write-Status "CentraStage removal script completed" -Level INFO