Bigbug
If you have another RMM to run it from, I've had tremendous luck with this script:
<#
.SYNOPSIS
Tactical RMM Agent Repair Script — self‏-contained and whitelabeled.
.DESCRIPTION
Detects, repairs, reinstalls, or installs the Tactical RMM Windows agent.
Preserves existing configurations, manages Defender exclusions, validates network, and logs to local files.
.PARAMETER trmmapikey
**Required.** API key for agent lookup and configuration via Tactical RMM API.
.PARAMETER ForceReinstall
Switch. When used, uninstalls any existing agent and performs a fresh install.
.PARAMETER ENABLE_POWER
Switch. Enables power control features in the agent installer.
.PARAMETER ENABLE_RDP
Switch. Enables RDP monitoring/control features in the agent installer.
.PARAMETER ENABLE_PING
Switch. Enables ICMP ping monitoring in the agent installer.
.PARAMETER AGENT_TYPE
Defaults to "workstation". Use "server" or other types supported by your Tactical RMM deployment.
.EXAMPLE
# Repair if needed; do not reinstall if healthy
.\Repair-RMM.ps1 -trmmapikey "YOUR_API_KEY"
.EXAMPLE
# Force reinstall with all optional features enabled
.\Repair-RMM.ps1 -trmmapikey "YOUR_API_KEY" -ForceReinstall -ENABLE_POWER -ENABLE_RDP -ENABLE_PING
.NOTES
• Log files are stored per-day under: C:\tools\logs\tactical-rmm-repair-YYYY-MM-DD.log
• Temporary installers are downloaded to: C:\tools\installers
• Backups (if any logic added later) under: C:\tools\backups
• Ensure PowerShell is run **as Administrator** for service control, Defender settings, and folder creation.
• Required network access: the download URL host must be reachable via HTTPS/443.
• Defender exclusions are added for:
- C:\Program Files\TacticalAgent\
- C:\ProgramData\TacticalRMM\
- C:\tools\
• Logs to console and file; critical failures exit with code 1.
.VERSION
2.0 (2025‏‑06‏‑24) — enriched usage notes and examples.
#>
param (
[string]$trmmapikey,
[switch]$ForceReinstall,
[switch]$ENABLE_POWER,
[switch]$ENABLE_RDP,
[switch]$ENABLE_PING,
[string]$AGENT_TYPE = "workstation"
)
$API_URL = "https://api.yourrmm.com"
$DOWNLOAD_URL = "https://agents.tacticalrmm.com/api/v2/agents/?version=2.9.0&arch=amd64&token=YOUR_TOKEN&plat=windows&api=yourrmm.com"
$DEFAULT_CLIENT_ID = "1"
$DEFAULT_SITE_ID = "1"
$BASE_FOLDER = "C:\tools"
$LOG_PATH = "$BASE_FOLDER\logs"
function Write-Log {
param($message, $level="INFO")
$ts = Get-Date -Format "yyyy-MM-dd HH:mm:ss"
$entry = "[$ts] [$level] $message"
Write-Output $entry
if (-not (Test-Path $LOG_PATH)) { New-Item -ItemType Directory -Path $LOG_PATH -Force | Out-Null }
$logFile = "$LOG_PATH\tactical-rmm-repair-$(Get-Date -Format 'yyyy-MM-dd').log"
$entry | Out-File -FilePath $logFile -Append -Encoding UTF8
}
function Initialize-Folders {
$paths = @("$LOG_PATH","$BASE_FOLDER\installers","$BASE_FOLDER\backups")
foreach ($p in $paths) {
if (-not (Test-Path $p)) {
New-Item -ItemType Directory -Path $p -Force | Out-Null
Write-Log "Created folder: $p"
}
}
}
function Validate-ApiKey {
if (-not $trmmapikey -or $trmmapikey.Trim() -eq "") {
Write-Log "API key (-trmmapikey) is required" "ERROR"
throw "Missing API key"
}
Write-Log "API key validated"
}
function Get-AgentInfo {
param($token)
Write-Log "Querying RMM API for agent info..."
try {
$hdr = @{ "X-API-KEY" = $token; "Content-Type" = "application/json" }
$resp = Invoke-RestMethod -Uri "$API_URL/agents/" -Headers $hdr -Method GET -TimeoutSec 30
$host = $env:COMPUTERNAME
$match = $resp | Where-Object { $_.hostname -eq $host }
if ($match) {
Write-Log "Found agent in API: $host"
return @{ ClientId = $match.client; SiteId = $match.site; Found = $true; AgentId = $match.agent_id }
} else {
Write-Log "Agent not found in API" "WARNING"
return @{ ClientId = $DEFAULT_CLIENT_ID; SiteId = $DEFAULT_SITE_ID; Found = $false; AgentId = $null }
}
} catch {
Write-Log "API lookup failed: $_" "WARNING"
return @{ ClientId = $DEFAULT_CLIENT_ID; SiteId = $DEFAULT_SITE_ID; Found = $false; AgentId = $null }
}
}
function Check-Health {
Write-Log "Checking TacticalRMM service health..."
$svc = Get-Service -Name tacticalrmm -ErrorAction SilentlyContinue
if (-not $svc) { Write-Log "Service not found" "WARNING"; return $false }
Write-Log "Service status: $($svc.Status)"
if ($svc.Status -eq 'Running') {
$proc = Get-Process -Name tacticalrmm -ErrorAction SilentlyContinue
if ($proc) { Write-Log "Agent running", "SUCCESS"; return $true }
Write-Log "Service running but process missing", "WARNING"; return $false
}
if ($svc.Status -eq 'Stopped') {
Try {
Start-Service tacticalrmm -ErrorAction Stop
Start-Sleep -Seconds 10
if ((Get-Service tacticalrmm).Status -eq 'Running') {
Write-Log "Successfully started", "SUCCESS"; return $true
}
} catch {
Write-Log "Failed to start service: $_" "ERROR"; return $false
}
}
return $false
}
function Remove-Agent {
Write-Log "Removing existing TacticalRMM installation..."
Try {
Stop-Service tacticalrmm -Force -ErrorAction SilentlyContinue
Get-Process tacticalrmm -ErrorAction SilentlyContinue | Stop-Process -Force
sc.exe delete tacticalrmm | Out-Null
Remove-Item "C:\Program Files\TacticalAgent" -Recurse -Force -ErrorAction SilentlyContinue
Remove-Item "C:\ProgramData\TacticalRMM" -Recurse -Force -ErrorAction SilentlyContinue
Write-Log "Removal complete", "SUCCESS"
} catch {
Write-Log "Removal error: $_" "ERROR"
throw
}
}
function Add-DefenderExclusions {
Write-Log "Configuring Defender exclusions..."
Try {
if ((Get-MpComputerStatus).AntivirusEnabled) {
Add-MpPreference -ExclusionPath 'C:\Program Files\TacticalAgent\*'
Add-MpPreference -ExclusionPath 'C:\ProgramData\TacticalRMM\*'
Add-MpPreference -ExclusionPath "$BASE_FOLDER\*"
Write-Log "Exclusions added", "SUCCESS"
}
} catch {
Write-Log "Defender exclusion failed: $_" "WARNING"
}
}
function Test-Connectivity {
param($h)
Write-Log "Testing connectivity to $h..."
for ($i=1; $i -le 3; $i++) {
if ((Test-NetConnection $h -Port 443).TcpTestSucceeded) {
Write-Log "Connected to $h", "SUCCESS"; return $true
}
Start-Sleep -Seconds 5
}
Write-Log "Connectivity to $h failed", "ERROR"; return $false
}
function Install-Agent {
param($cid, $sid, $tok)
Write-Log "Installing TacticalRMM agent..."
try {
[Net.ServicePointManager]::SecurityProtocol = [Net.SecurityProtocolType]::Tls12
$h = ([Uri]$DOWNLOAD_URL).Host
if (-not (Test-Connectivity -h $h)) { throw "Cannot reach $h" }
Add-DefenderExclusions
Initialize-Folders
$out = "$BASE_FOLDER\installers"
$exe = "$out\tactical-install.exe"
Write-Log "Downloading agent installer..."
Invoke-WebRequest -Uri $DOWNLOAD_URL -OutFile $exe -UseBasicParsing
if (-not (Test-Path $exe)) { throw "Download failed" }
Start-Process $exe -ArgumentList '/VERYSILENT','/SUPPRESSMSGBOXES' -Wait -PassThru | Out-Null
Start-Sleep 5
$agentExe = "C:\Program Files\TacticalAgent\tacticalrmm.exe"
if (-not (Test-Path $agentExe)) { throw "Agent executable missing" }
$args = @('-m','install','--api',$API_URL,'--client-id',$cid,'--site-id',$sid,'--agent-type',$AGENT_TYPE,'--auth',$tok)
if ($ENABLE_POWER) { $args += '--power' }
if ($ENABLE_RDP) { $args += '--rdp' }
if ($ENABLE_PING) { $args += '--ping' }
Start-Process $agentExe -ArgumentList $args -Wait -PassThru | Out-Null
Start-Sleep 10
if (Check-Health) {
Write-Log "Installation successful", "SUCCESS"
return $true
}
throw "Agent not healthy after install"
} catch {
Write-Log "Install error: $_" "ERROR"
throw
}
}
try {
Write-Log "=== Script started ==="
Initialize-Folders
Validate-ApiKey
$info = Get-AgentInfo -token $trmmapikey
$healthy = Check-Health
if ($healthy -and -not $ForceReinstall) {
Write-Log "Agent healthy; no action taken", "SUCCESS"
exit 0
}
if ($ForceReinstall -or -not $healthy) {
if ($healthy) {
Write-Log "Force reinstall requested" "INFO"
} else {
Write-Log "Agent not healthy; reinstalling" "INFO"
}
Remove-Agent
$info = Get-AgentInfo -token $trmmapikey
Install-Agent -cid $info.ClientId -sid $info.SiteId -tok $trmmapikey
Write-Log "=== Completed successfully ===", "SUCCESS"
exit 0
}
} catch {
Write-Log "Script failed: $_" "ERROR"
exit 1
}