Skip to main content

Practical Use Cases for ConnectWiseAutomateAgent

Practical PowerShell examples for ConnectWiseAutomateAgent beyond basic installation. Covers new hire provisioning, compliance reporting, disaster recovery, version audits, multi-tenant deployment, proxy management, migrations, and department branding.

What This Covers

The ConnectWiseAutomateAgent module handles more than agent installation. It exposes functions for health checks, configuration management, proxy settings, branding, and uninstallation – all scriptable, all composable with standard PowerShell tooling.

This post walks through practical examples: onboarding, compliance reporting, DR testing, version audits, multi-tenant deployment, proxy changes, migrations, network testing, health monitoring, and department branding. Each one is a pattern you can adapt to your environment.


New Hire Provisioning

Scenario: Your client onboards new employees weekly. Each workstation needs an RMM (Remote Monitoring and Management) agent installed, configured, and reporting to the correct location.

The manual version: HR notifies IT, IT provisions the machine, IT manually installs the agent, and the agent eventually shows up in Automate.

Scripted version:

# Integrated onboarding script
param(
    [string]$EmployeeName,
    [string]$Department
)

# Determine LocationID based on department
$locationMap = @{
    'Sales' = 100
    'Engineering' = 101
    'Support' = 102
    'Management' = 103
}
$locationID = $locationMap[$Department]

# Provision new computer (your existing process)
$computer = New-ADComputer -Name "WKS-$EmployeeName" -Path "OU=$Department,DC=company,DC=com" -PassThru

# Wait for computer to come online
do {
    Start-Sleep -Seconds 30
} until (Test-Connection -ComputerName $computer.Name -Count 1 -Quiet)

# Install RMM agent
Invoke-Command -ComputerName $computer.Name -ScriptBlock {
    Install-Module ConnectWiseAutomateAgent -Force
    Install-CWAA -Server 'https://automate.msp.com' `
                 -InstallerToken $using:token `
                 -LocationID $using:locationID `
                 -Hide `
                 -Rename "Company IT Services"
}

# Verify
Start-Sleep 30
$agentInfo = Invoke-Command -ComputerName $computer.Name -ScriptBlock {
    Get-CWAAInfo
}

# Update ticket/notification
Send-MailMessage -To "[email protected]" `
                 -Subject "New Hire Setup Complete: $EmployeeName" `
                 -Body "Computer: $($computer.Name)`nAgent ID: $($agentInfo.ID)`nLocation: $Department"

Result: Fully automated provisioning from AD computer creation to RMM monitoring in minutes.


Compliance Reporting

Scenario: Monthly compliance reports require knowing which machines have RMM agents and which don’t.

Scripted version:

# Monthly compliance check
$allComputers = Get-ADComputer -Filter * -SearchBase "DC=company,DC=com"
$complianceReport = @()

foreach ($computer in $allComputers) {
    try {
        $agentInfo = Invoke-Command -ComputerName $computer.Name -ScriptBlock {
            Get-CWAAInfo
        } -ErrorAction Stop

        $complianceReport += [PSCustomObject]@{
            ComputerName = $computer.Name
            HasAgent = $true
            AgentID = $agentInfo.ID
            LastContact = $agentInfo.LastSuccessfulContact
            Version = $agentInfo.Version
            Compliant = $true
        }
    }
    catch {
        $complianceReport += [PSCustomObject]@{
            ComputerName = $computer.Name
            HasAgent = $false
            AgentID = 'N/A'
            LastContact = 'N/A'
            Version = 'N/A'
            Compliant = $false
        }
    }
}

# Generate report
$complianceReport | Export-Csv "Compliance-$(Get-Date -Format 'yyyy-MM').csv" -NoTypeInformation

# Email non-compliant systems
$nonCompliant = $complianceReport | Where-Object { -not $_.Compliant }
if ($nonCompliant) {
    $body = $nonCompliant | ConvertTo-Html | Out-String
    Send-MailMessage -To "compliance@company.com" `
                     -Subject "RMM Compliance Alert: $($nonCompliant.Count) systems need attention" `
                     -Body $body `
                     -BodyAsHtml
}

Result: Automated monthly compliance reporting with alerts for non-compliant systems.


Disaster Recovery Testing

Scenario: Quarterly DR tests require removing and reinstalling agents to verify you can recover from a complete loss.

Scripted version:

# DR Test: Backup, remove, and restore agent configurations
param([string[]]$TestComputers)

foreach ($computer in $TestComputers) {
    Write-Host "Testing DR for $computer..." -ForegroundColor Cyan

    Invoke-Command -ComputerName $computer -ScriptBlock {
        # Backup current configuration
        $backup = New-CWAABackup
        $backup | Export-Clixml "C:\Temp\AgentBackup-$(Get-Date -Format 'yyyyMMdd').xml"

        # Simulate disaster - remove agent
        Uninstall-CWAA -Force

        # Wait
        Start-Sleep 10

        # Restore from backup
        $restoredSettings = Import-Clixml "C:\Temp\AgentBackup-$(Get-Date -Format 'yyyyMMdd').xml"

        Install-CWAA -Server $restoredSettings.Server `
                     -LocationID $restoredSettings.LocationID `
                     -InstallerToken $using:token

        # Verify
        $newInfo = Get-CWAAInfo
        if ($newInfo.ID -and $newInfo.LocationID -eq $restoredSettings.LocationID) {
            Write-Host "DR Test PASSED for $env:COMPUTERNAME" -ForegroundColor Green
        }
        else {
            Write-Host "DR Test FAILED for $env:COMPUTERNAME" -ForegroundColor Red
        }
    }
}

Result: Automated DR testing with verification that agents can be restored to correct configurations.


Agent Version Audit and Update

Scenario: A vulnerability is found in agent version 11.1.2345. You need to find and update all affected agents.

Scripted version:

# Find and update vulnerable agents
$vulnerableVersion = '11.1.2345'
$computers = Get-ADComputer -Filter * | Select-Object -ExpandProperty Name

$affectedSystems = $computers | ForEach-Object -Parallel {
    try {
        $info = Invoke-Command -ComputerName $_ -ScriptBlock {
            Get-CWAAInfo
        } -ErrorAction Stop

        if ($info.Version -eq $using:vulnerableVersion) {
            [PSCustomObject]@{
                Computer = $_
                CurrentVersion = $info.Version
                NeedsUpdate = $true
            }
        }
    }
    catch {
        # Skip offline/inaccessible machines
    }
} -ThrottleLimit 20

# Report affected systems
Write-Host "Found $($affectedSystems.Count) systems with vulnerable version" -ForegroundColor Yellow
$affectedSystems | Export-Csv "VulnerableAgents.csv" -NoTypeInformation

# Update all affected systems
$affectedSystems | ForEach-Object -Parallel {
    Invoke-Command -ComputerName $_.Computer -ScriptBlock {
        Import-Module ConnectWiseAutomateAgent
        Update-CWAA
    }
} -ThrottleLimit 10

Write-Host "Updates deployed to $($affectedSystems.Count) systems" -ForegroundColor Green

Result: Rapid identification and patching of vulnerable agents across entire infrastructure.


Multi-Tenant Client Segregation

Scenario: You’re an MSP managing 50+ clients. Each client’s agents need to land in the correct location with the right display name.

Scripted version:

# Client configuration database
$clientConfig = @(
    @{ ClientName = 'Acme Corp'; LocationID = 100; Server = 'https://automate.msp.com'; Token = 'token1'; DisplayName = 'Acme IT Services' }
    @{ ClientName = 'Globex Inc'; LocationID = 200; Server = 'https://automate.msp.com'; Token = 'token2'; DisplayName = 'Globex Monitoring' }
    @{ ClientName = 'Initech LLC'; LocationID = 300; Server = 'https://automate.msp.com'; Token = 'token3'; DisplayName = 'Initech IT Support' }
)

# Deploy based on client
function Deploy-ClientAgent {
    param(
        [string]$ComputerName,
        [string]$ClientName
    )

    $config = $clientConfig | Where-Object { $_.ClientName -eq $ClientName } | Select-Object -First 1

    if (-not $config) {
        Write-Error "Client $ClientName not found in configuration"
        return
    }

    Invoke-Command -ComputerName $ComputerName -ScriptBlock {
        Install-CWAA -Server $using:config.Server `
                     -InstallerToken $using:config.Token `
                     -LocationID $using:config.LocationID `
                     -Rename $using:config.DisplayName `
                     -Hide
    }

    Write-Host "Deployed agent for $ClientName to $ComputerName" -ForegroundColor Green
}

# Usage
Deploy-ClientAgent -ComputerName "ACME-WKS001" -ClientName "Acme Corp"

Result: Standardized, error-free agent deployment with proper client segregation and branding.


Proxy Configuration Management

Scenario: A client changes their proxy server. You need to update all 300 agents.

Scripted version:

# Update proxy on all agents
param(
    [string]$NewProxyURL = "http://newproxy.client.com:8080",
    [string]$ClientLocationID = 100
)

# Get all computers for this client
$computers = Invoke-RestMethod -Uri "https://automate.msp.com/api/computers?locationId=$ClientLocationID"

# Update proxy on each
$results = $computers | ForEach-Object -Parallel {
    $computer = $_.ComputerName

    try {
        Invoke-Command -ComputerName $computer -ScriptBlock {
            Import-Module ConnectWiseAutomateAgent
            Set-CWAAProxy -ProxyServerURL $using:NewProxyURL
            Restart-CWAA
        }

        [PSCustomObject]@{
            Computer = $computer
            Status = 'Updated'
        }
    }
    catch {
        [PSCustomObject]@{
            Computer = $computer
            Status = "Failed: $($_.Exception.Message)"
        }
    }
} -ThrottleLimit 25

# Report
$results | Export-Csv "ProxyUpdate-Results.csv" -NoTypeInformation
Write-Host "Updated proxy on $(($results | Where-Object Status -eq 'Updated').Count) computers" -ForegroundColor Green

Result: Instant proxy configuration change across entire client infrastructure.


Pre-Migration Agent Removal

Scenario: You’re migrating a client to a different RMM. You need clean agent removal from 400 endpoints, with verification that nothing is left behind.

Scripted version:

# Mass agent removal with verification
$computers = Get-ADComputer -Filter * -SearchBase "OU=Client,DC=domain,DC=com"

$removalResults = $computers | ForEach-Object -Parallel {
    $computer = $_.Name

    try {
        Invoke-Command -ComputerName $computer -ScriptBlock {
            Import-Module ConnectWiseAutomateAgent
            Uninstall-CWAA -Force

            # Verify removal
            Start-Sleep 10
            $service = Get-Service LTService -ErrorAction SilentlyContinue
            if ($service) {
                throw "Service still present after uninstall"
            }

            # Verify registry cleaned
            $reg = Get-ItemProperty "HKLM:\SOFTWARE\LabTech\Service" -ErrorAction SilentlyContinue
            if ($reg) {
                throw "Registry keys still present"
            }
        }

        [PSCustomObject]@{
            Computer = $computer
            Status = 'Removed'
            Message = 'Agent fully removed and verified'
        }
    }
    catch {
        [PSCustomObject]@{
            Computer = $computer
            Status = 'Failed'
            Message = $_.Exception.Message
        }
    }
} -ThrottleLimit 15

# Report
$removalResults | Export-Csv "AgentRemoval-$(Get-Date -Format 'yyyyMMdd').csv" -NoTypeInformation
$successful = ($removalResults | Where-Object Status -eq 'Removed').Count
Write-Host "Successfully removed agents from $successful / $($computers.Count) computers" -ForegroundColor Green

Result: Clean, verified removal of agents from entire client infrastructure.


Network Segmentation Testing

Scenario: You’re testing firewall rules for a new office and need to verify RMM connectivity from the test subnet before deploying agents.

Scripted version:

# Network connectivity verification script
param(
    [string[]]$TestComputers,
    [string]$Server = "https://automate.msp.com"
)

$testResults = foreach ($computer in $TestComputers) {
    Invoke-Command -ComputerName $computer -ScriptBlock {
        Import-Module ConnectWiseAutomateAgent

        # Test all required ports (output is string-based, not objects)
        $portOutput = Test-CWAAPort -Server $using:Server
        $failedPorts = $portOutput | Where-Object { $_ -match 'Connection failed' }

        [PSCustomObject]@{
            Computer = $env:COMPUTERNAME
            Subnet = (Get-NetIPAddress -AddressFamily IPv4 | Where-Object { $_.InterfaceAlias -notmatch 'Loopback' } | Select-Object -First 1).IPAddress
            PortTestOutput = ($portOutput -join "`n")
            AllPortsOpen = ($failedPorts.Count -eq 0)
        }
    }
}

# Report
$testResults | Format-Table -AutoSize
$failures = $testResults | Where-Object { -not $_.AllPortsOpen }

if ($failures) {
    Write-Host "`nFirewall issues detected on $($failures.Count) computers:" -ForegroundColor Red
    $failures | Format-Table Computer, Subnet, PortTestOutput
}
else {
    Write-Host "All network connectivity tests passed!" -ForegroundColor Green
}

Result: Automated firewall rule verification before agent deployment.


Fleet Health Monitoring

Scenario: You want a daily sweep of all agents that catches issues and attempts basic remediation, with a report of what it found.

If you’re looking for per-endpoint self-healing that runs as a scheduled task on each machine, see Self-Healing Agents. That post covers Repair-CWAA, escalation logic, and the health check task in detail.

This pattern is different – it’s a centralized sweep you run from a management server against your whole fleet.

Scripted version:

# Daily agent health check with auto-remediation
# Run as scheduled task at 6 AM daily

$computers = Get-ADComputer -Filter * | Select-Object -ExpandProperty Name
$issues = @()

foreach ($computer in $computers) {
    try {
        $health = Invoke-Command -ComputerName $computer -ScriptBlock {
            Import-Module ConnectWiseAutomateAgent

            $info = Get-CWAAInfo
            $services = Get-Service LTService, LTSvcMon

            # Check for issues
            $problems = @()

            # Issue 1: Services stopped
            if ($services.Status -contains 'Stopped') {
                Restart-CWAA
                $problems += "Services were stopped - restarted"
            }

            # Issue 2: Old last contact (> 1 hour)
            $lastContact = [datetime]$info.LastSuccessfulContact
            if ((Get-Date) - $lastContact -gt [timespan]::FromHours(1)) {
                Invoke-CWAACommand -Command "Send Status"
                $problems += "Stale last contact - forced status update"
            }

            # Issue 3: Critical errors in logs
            $errors = Get-CWAAError | Select-Object -Last 100 | Where-Object { $_ -match "CRITICAL|FATAL" }
            if ($errors) {
                $problems += "Critical errors in log: $($errors.Count) entries"
            }

            if ($problems.Count -gt 0) {
                [PSCustomObject]@{
                    Computer = $env:COMPUTERNAME
                    Issues = $problems -join '; '
                    Remediated = $true
                }
            }
        }

        if ($health) {
            $issues += $health
        }
    }
    catch {
        $issues += [PSCustomObject]@{
            Computer = $computer
            Issues = "Unable to connect: $($_.Exception.Message)"
            Remediated = $false
        }
    }
}

# Send daily report
if ($issues.Count -gt 0) {
    $htmlReport = $issues | ConvertTo-Html -Title "Daily Agent Health Report" | Out-String

    Send-MailMessage -To "[email protected]" `
                     -From "[email protected]" `
                     -Subject "Daily Agent Health Report: $($issues.Count) issues found" `
                     -Body $htmlReport `
                     -BodyAsHtml `
                     -SmtpServer "smtp.msp.com"

    $issues | Export-Csv "HealthReport-$(Get-Date -Format 'yyyyMMdd').csv" -NoTypeInformation
}

Result: Proactive monitoring and auto-remediation of common agent issues before they become tickets.


Department-Based Agent Branding

Scenario: A large enterprise wants different agent display names per department for charge-back reporting.

Scripted version:

# Department-based agent naming
$departmentMap = @{
    'OU=Sales' = 'Sales Department IT'
    'OU=Engineering' = 'Engineering Services'
    'OU=HR' = 'Human Resources IT'
    'OU=Finance' = 'Finance Department IT'
}

$computers = Get-ADComputer -Filter * -Properties DistinguishedName

foreach ($computer in $computers) {
    # Determine department from DN
    $department = $departmentMap.Keys | Where-Object { $computer.DistinguishedName -match $_ } | Select-Object -First 1
    $displayName = $departmentMap[$department]

    if ($displayName) {
        Invoke-Command -ComputerName $computer.Name -ScriptBlock {
            Import-Module ConnectWiseAutomateAgent
            Rename-CWAAAddRemove -Name $using:displayName
        }

        Write-Host "Updated $($computer.Name) to '$displayName'" -ForegroundColor Green
    }
}

Result: Automated agent branding based on organizational structure for accurate charge-back.


Patterns Worth Noting

A few things show up across most of these examples:

  • Parallel executionForEach-Object -Parallel keeps things fast when you’re hitting hundreds of machines
  • Error handling – every script accounts for machines being offline or unreachable
  • Reporting – CSV exports and email notifications so you have a record of what happened
  • Verification – confirm the action worked, don’t assume it did
  • Composability – module functions combine naturally with AD, email, and your existing tooling

Here’s a starter template if you want to build your own:

# Template for custom use cases
param([string[]]$Computers)

$results = $Computers | ForEach-Object -Parallel {
    try {
        Invoke-Command -ComputerName $_ -ScriptBlock {
            Import-Module ConnectWiseAutomateAgent

            # Your logic here
            # - Get-CWAAInfo
            # - Set-CWAAProxy
            # - Restart-CWAA
            # - etc.
        }

        # Success
        [PSCustomObject]@{
            Computer = $_
            Status = 'Success'
        }
    }
    catch {
        # Failure
        [PSCustomObject]@{
            Computer = $_
            Status = 'Failed'
            Error = $_.Exception.Message
        }
    }
} -ThrottleLimit 20

# Report results
$results | Export-Csv "Results.csv" -NoTypeInformation

Getting started:

Install-Module ConnectWiseAutomateAgent

Full function reference and examples: GitHub Repository

Comments