Deploying and uninstalling the Coro Agent via Atera

This guide describes how to deploy and uninstall the Coro Agent from your endpoint devices through the Atera remote monitoring and management (RMM) platform.

Deploying the Coro Agent

To deploy Coro to endpoint devices via the Atera RMM platform, you need to:

  1. Obtain the Coro deployment script .
  2. Add the Coro deployment script to Atera .
  3. Deploy Coro .

Prerequisites

Before you begin this guide, make sure you have:

  • An active Coro subscription
  • Coro Agent version 2.5.60.1 (3.1) or later installed on your device
  • An Atera administration account
  • Access to the Atera RMM platform
  • Devices listed and ready for Coro deployment in the Atera RMM platform

Obtaining the Coro deployment script

Coro provides the following Windows PowerShell deploy script to enable organizations to install the Coro Agent on their Windows endpoint devices using Atera RMM:

Expand for more details
Copy
Copied
#Please add Coro installation URL and msi package name below (in between quotes "")

$url = "Please add Coro installation URL here and don't delete the quotes"
$newFilename = "Please add the name of Coro msi package here from the url, without deleting the quotes. For example, CoroInstaller_1b16c978-cd39-49bf-8809-7b4e87227e4e.msi"

#Variables

$softwareName = "Coro"
$logFilePath = "C:\Windows\Temp\CoroInstallerlog.txt"

#Display OS version

try {

Write-Host ""
Write-Host ""
$operatingSystem = Get-CimInstance -ClassName Win32_OperatingSystem
$osVersion = $operatingSystem.Version
$osEdition = $operatingSystem.Caption
$osArchitecture = $operatingSystem.OSArchitecture
$OSVersion = "$osEdition $osArchitecture $osVersion"
Write-Host "$OSVersion"

    } catch {
}

#Define msi file location

$msiFilePath = "C:\Windows\Temp\$newFilename"

#Download Coro installer

Write-Host ""
Write-Host "Downloading $newFilename file"
Write-Host "This might take some time, depending on download speed"

$webClient = New-Object System.Net.WebClient

try {
    
    $webClient.DownloadFile($url, $msiFilePath)
    Write-Host "Done! The file placed in C:\Windows\Temp" -ForegroundColor Green

} catch {

    Write-Host "Error when downloading. Error message: $($_.Exception.Message)" -ForegroundColor Cyan
    Write-Host "Please contact Support and send a screenshot of this output" -ForegroundColor Cyan
    Start-Sleep -Seconds 5
    exit 1
}

$webClient.Dispose()

#Install the downloaded file

try {
        Write-Host ""
        Write-Host "Installing $softwareName"
        $coroInstall = Start-Process msiexec.exe -PassThru -Wait -ArgumentList "/i `"$msiFilePath`" /qn /L*V `"$logFilePath`""				
        $exitCode = $coroInstall.ExitCode
                                
        if ($exitCode -eq 0) {
                
        Write-Host "Done!" -ForegroundColor Green
        Start-Sleep -Seconds 1
        $success = $true

        } elseif ($exitCode -eq 1619) {
            
        Write-Host "Installation failed because of value of msiFilePath variable" -ForegroundColor Cyan
        Write-Host "Error code: $exitCode" -ForegroundColor Cyan
        Write-Host "Please contact Support and send $logFilePath log file along with a screenshot of this output" -ForegroundColor Cyan
        Remove-Item -Path $msiFilePath -Force -Confirm:$false
        Start-Sleep -Seconds 10
            
        exit 1
        
        } elseif ($exitCode -eq 1639) {
            
        Write-Host "Installation failed because of incorrect argument(s) (-ArgumentList in coroInstall variable)" -ForegroundColor Cyan
        Write-Host "Error code: $exitCode" -ForegroundColor Cyan
        Write-Host "Please contact Support and send a screenshot of this output" -ForegroundColor Cyan
        Remove-Item -Path $msiFilePath -Force -Confirm:$false
        Start-Sleep -Seconds 10
            
        exit 1
        
        } else {

        Write-Host "Installation failed, error code: $exitCode" -ForegroundColor Cyan
        Write-Host "Please contact Support and send $logFilePath log file along with a screenshot of this output" -ForegroundColor Cyan
        Remove-Item -Path $msiFilePath -Force -Confirm:$false
        Start-Sleep -Seconds 10
        exit 1
        
        }
            
    } catch { }
        
#Display success message

if ($success -eq $true) {

Remove-Item -Path $logFilePath -Force -Confirm:$false
Remove-Item -Path $msiFilePath -Force -Confirm:$false

Write-Host ""
Write-Host "Deleting installation and log files as these are no longer required"
Write-Host "All done, $softwareName is now installed"  -ForegroundColor Green
Start-Sleep -Seconds 5

} else { }

In this script, replace the following markers with real values:

  • $url : The download URL for the latest version of the Coro Agent installer for Windows, obtained from the Coro console. For details, see Deploying Coro on windows endpoints .
  • $newFilename : The unique installer .msi filename embedded in the download URL.

Atera/NinjaOne deployment script variables

For example, if the download URL is:

https://s3.amazonaws.com/client-repo.coro.net/beta/win/releases/2.0.412.1/CoroInstaller.msi?response-content-disposition=attachment%3B%20filename%3DCoroInstaller_123abc-456def-789abc.msi&AWSAccessKeyId=AKIA5XP6&Signature=y4V3Tq2dU9mE%3D&Expires=2005954595

The installer filename (shown in bold) is then used within the shell script as per the following example:

$newFilename = CoroInstaller_123abc-456def-789abc.msi

Atera/NinjaOne deployment script variables

Important

Make sure you do not delete the quotations when replacing the placeholder text for $url and $msiFilePath.

note

If you manage multiple workspaces you must create a copy of the standard Coro deployment script and repeat this process for each workspace.

Adding the Coro deployment script to Atera

To add your Coro deployment script to the Atera RMM platform, perform the following steps:

  1. Sign in to the Atera RMM platform using an administrator account.
  2. Select New , and then select Script :

    Atera new script

    The Create script dialog appears.

  3. Enter the following new script information:
    Field Description
    Script Name Enter a suitable script name, for example, "Coro_Deployment".
    File type Select ".ps1".
    Script Description Enter a suitable script description, for example, "This script deploys the Coro Agent on specified devices."

    Atera new script information

  4. Expand More script properties , and then enter the following additional script information:
    Field Description
    Category Leave blank.
    Max script run time (minutes) Enter "10".
    Arguments Leave blank.
    Run as Select System.

    Atera new script additional information

  5. Copy and paste your Coro deployment script into the Script editor :

    Script editor

  6. Select Create :

    Create

    Atera creates the deployment script, and it appears on the My Scripts tab on the Scripts page, ready for deployment:

    My scripts

Deploying Coro

To deploy the Coro Agent on selected endpoint devices using the deployment script, perform the following steps:

  1. Sign in to the Atera RMM platform using an administrator account.
  2. Go to Devices :

    Devices

    A list of all devices appears.

  3. Select the checkbox next to each device on which you want to deploy the Coro Agent, and then select Run Script :

    Select devices

    The Run script on devices dialog appears:

    Run script

  4. From the My Scripts tab, select Run , located next to the Coro deployment script:

    Run script

    The deployment script executes and a notification appears:

    Script executed

  5. To monitor the progress of the script deployment, go to Reports > Classic Reports > Recent Processes :

    Recent Processes

    The Current Status displays "In Progress":

    Current Status

    The Coro Agent is deployed on the selected devices.

    After script deployment, the Current Status changes to "Ended".

  6. Hover over ? to view the script deployment result:

    Completed

    A result of 1 Completed confirms successful deployment.

Uninstalling the Coro Agent

Important

Make sure you disable Tamper Protection in your Coro Workspace before attempting to uninstall Coro.

To uninstall Coro from endpoint devices via the Atera RMM platform, you need to:

  1. Obtain the Coro uninstall script .
  2. Add the uninstall script to Atera .
  3. Uninstall the Coro Agent .

Prerequisites

Before you begin this guide, make sure you have:

  • An active Coro subscription
  • An Atera administration account
  • Access to the Atera RMM platform

Obtaining the Coro uninstall script

Coro provides the following Windows PowerShell uninstall script to enable organizations to remove the Coro Agent from their Windows endpoint devices using Atera RMM:

Expand for more details
Copy
Copied
########################

# IMPORTANT #

# This script requires elevated privileges (Run PowerShell as Admin) to work.
# If you are deploying it via GPO or any other RMM, they will already run it in elevated mode, unless specifically configured otherwise.
# However, if you run it locally as a user, you must make sure your PowerShell instance is elevated (Run PowerShell as Admin), otherwise the script will fail.

# This script can be used both locally and with GPO or any other RMM that support PowerShell. However, some specific RMMs only support limited PowerShell commands, so this script might not work on these. In this case, please contact Coro support for help. 

##########################################################
#### BYPASS SWITCH #######################################
##########################################################

#This script will always attempt to uninstall Coro using native methods (MSI package) and will only resort to a manual uninstall if the native methods fail
#However, in some specific scenarios, it might be required to skip the native method and instruct the script to directly execute a manual uninstall (for example, when we need to uninstall Coro version 2.0.42.1 if it fails to update to the latest version)
#For those cases, set the value of the variable below to $true. This will instruct the script to skip native uninstall methods and immediately proceed with the manual uninstall. 
#The script will still check for Tamper Protection status because if it is enabled, we can only uninstall Coro in Safe Mode.
#If that's the case, simply run the script in Safe Mode (with or without the switch below as it is not triggering in Safe Mode), and it will uninstall Coro manually.

$skipNativeUninstall = $false #Use only when asked to do so by Support: set this variable to $true to skip native uninstall methods.  

###########################################################
##### NO NEED TO AMEND ANYTHING ELSE BELOW THIS LINE ######
###########################################################

#Checking for elevated permissions

$isElevated = [Security.Principal.WindowsPrincipal]::new([Security.Principal.WindowsIdentity]::GetCurrent()).IsInRole([Security.Principal.WindowsBuiltInRole]::Administrator)

$isUserContext = -not ([Environment]::UserInteractive -and $isElevated)

if (-not $isElevated -and $isUserContext) {

    Write-Host ""
	Write-Host "This script is not running in elevated mode. Please run Powershell as Administrator and execute this script." -ForegroundColor Cyan
	Write-Host "The script will now terminate as it cannot run without elevated permissions." -ForegroundColor Cyan
    
	Start-Sleep -Seconds 7 
	exit 1
	
} else {
    
    Write-Host "This instance is elevated, proceeding to the next step" -ForegroundColor Green
    Write-Host ""
}

#Display OS version

try {

$operatingSystem = Get-CimInstance -ClassName Win32_OperatingSystem
$osVersion = $operatingSystem.Version
$osEdition = $operatingSystem.Caption
$osArchitecture = $operatingSystem.OSArchitecture
$OSVersion = "$osEdition $osArchitecture $osVersion"
Write-Host "$OSVersion"
Write-Host ""

	} catch {
}

#Set variables

$global:outputTimestamp = Get-Date -Format "dd-MM-yyyy HH:mm"
$global:outputSpace = " " * 18

Write-Host "[$outputTimestamp] Configuring variables (might take some time...)"

$tamperPath = "HKLM:\SOFTWARE\Coro Cyber Security Ltd\Coro"
$tamperValue = "SelfProtected"
$coroVersion = "Version"

$uninstallPath32 = "HKLM:\Software\Wow6432Node\Microsoft\Windows\CurrentVersion\Uninstall\*"
$registryResult32 = Get-ItemProperty -Path $uninstallPath32 | Where-Object { $_.DisplayName -like "Coro*" }

$uninstallPath64 = "HKLM:\Software\Microsoft\Windows\CurrentVersion\Uninstall\*"
$registryResult64 = Get-ItemProperty -Path $uninstallPath64 | Where-Object { $_.DisplayName -like "Coro*" }

$valueReg64 = $registryResult64.UninstallString

$match = [regex]::Match($valueReg64, '\{[^}]+\}')

if ($match.Success) {

    $uninstallStringReg64 = $match.Value

} else { }

try {

    $packageResult = Get-Package | Where-Object { $_.Name -like "Coro*" }

	} catch {
}
   
try {

    $wmiResult = Get-WmiObject -Class Win32_Product | Where-Object { $_.Name -like "Coro*" }

    if ($wmiResult -ne $null) {

		$wmiIdentifyingNumber = $wmiResult.IdentifyingNumber
        $wmiValue = $true

    } else {

		$wmiValue = $false

	}
	
	} catch {
	
		$wmiValue = $false
}

Write-Host "$outputSpace Done!" -ForegroundColor Green

#Detecting Safe Mode

Write-Host "[$outputTimestamp] Checking if the OS is running in Safe Mode"

$safeMode = $false

try {

	$safeModeDetector = (gwmi win32_computersystem -Property BootupState).BootupState

	if ($safeModeDetector -ne "Normal boot") {

	$safeMode = $true		

	} else {

	$safeMode = $false

	}

} catch {

		Write-Warning "Error checking safe mode: $_"
	}


if ($safeMode -eq $false) {

  Write-Host "$outputSpace Not in Safe Mode" -ForegroundColor Green

} else {

  Write-Host "$outputSpace Safe Mode detected" -ForegroundColor Yellow

}

#Check for potential corruption

if ($safeMode -eq $false -and $skipNativeUninstall -eq $false) {

	Write-Host "[$outputTimestamp] Checking Coro's integrity"

	$registryValue = Get-ItemProperty -Path $tamperPath -Name $tamperValue -ErrorAction SilentlyContinue

		if ($registryValue -and $registryValue.$tamperValue -eq "true") {
    
		$TamperProtectionON = $true

		} else {
    
		$TamperProtectionON = $false 
	
	} }	else {}


if ($safeMode -eq $false -and $skipNativeUninstall -eq $false) {

	if ($TamperProtectionON -eq $true) {

    $service1 = Get-Service "CoroAgent1SRV"
    $service2 = Get-Service "CoroAgent2SRV"
	
    if ($service1.Status -eq "Running" -and $service2.Status -eq "Running") {
        
		Write-Host "$outputSpace Done!" -ForegroundColor Green 

    } else {

		Write-Host "$outputSpace Core Coro services are not running. Attempting to start them..." -ForegroundColor DarkYellow

		sc.exe config $service1 start=auto 2>1 1>2 | Out-Null
		sc.exe config $service2 start=auto 2>1 1>2 | Out-Null	
   
        Start-Service $service1, $service2 -ErrorAction SilentlyContinue -WarningAction SilentlyContinue 2>1 1>2 | Out-Null -ErrorAction SilentlyContinue
        
        Start-Sleep -Seconds 3 

        if ($service1.Status -eq "Running" -and $service2.Status -eq "Running") {
       
		Write-Host "$outputSpace Done!" -ForegroundColor Green
        
		} else {
          
			sc.exe config $service1 start=auto 2>1 1>2 | Out-Null
			sc.exe config $service2 start=auto 2>1 1>2 | Out-Null

            Start-Service $service1, $service2 -ErrorAction SilentlyContinue -WarningAction SilentlyContinue 2>1 1>2 | Out-Null -ErrorAction SilentlyContinue
            
            Start-Sleep -Seconds 3
            
            if ($service1.Status -ne "Running" -and $service2.Status -ne "Running") {
                
			Write-Host "$outputSpace A potential integrity corruption is detected." -ForegroundColor Cyan
			Write-Host ""
			Write-Host "$outputSpace Tamper Protection: ON | Coro Agent1 and Coro Agent2 services: Stopped." -ForegroundColor Cyan
			Write-Host "$outputSpace The script could not start Coro Agent1 and Coro Agent2 services." -ForegroundColor Cyan
			Write-Host ""
			Write-Host "$outputSpace This means Tamper Protection won't disable on this device if disabled from the Workspace." -ForegroundColor Cyan
			Write-Host "$outputSpace As Coro cannot be uninstalled when Tamper Protection is on, please boot Windows" -ForegroundColor Cyan
			Write-Host "$outputSpace into the Safe Mode and re-run this script again to bypass Tamper Protection and uninstall Coro." -ForegroundColor Cyan
			Write-Host ""
			Write-Host "$outputSpace Please contact Support if you require any assistance with this." -ForegroundColor Cyan
			Write-Host "$outputSpace The script will terminate now." -ForegroundColor Cyan
			Start-Sleep -Seconds 5
			exit 1

            } elseif ($service1.Status -ne "Running" -and $service2.Status -eq "Running") {
              
			Write-Host "$outputSpace A potential integrity corruption is detected." -ForegroundColor Cyan
			Write-Host ""
			Write-Host "$outputSpace Tamper Protection: ON | Coro Agent1 service: Stopped." -ForegroundColor Cyan
			Write-Host "$outputSpace The script could not start Coro Agent1 service." -ForegroundColor Cyan
			Write-Host ""
			Write-Host "$outputSpace This means Tamper Protection won't disable on this device if disabled from the Workspace." -ForegroundColor Cyan
			Write-Host "$outputSpace As Coro cannot be uninstalled when Tamper Protection is on, please boot Windows" -ForegroundColor Cyan
			Write-Host "$outputSpace into the Safe Mode and re-run this script again to bypass Tamper Protection and uninstall Coro." -ForegroundColor Cyan
			Write-Host ""
			Write-Host "$outputSpace Please contact Support if you require any assistance with this." -ForegroundColor Cyan
			Write-Host "$outputSpace The script will terminate now." -ForegroundColor Cyan
			Start-Sleep -Seconds 5
			exit 1
            
			} elseif ($service1.Status -eq "Running" -and $service2.Status -ne "Running") {
                
			Write-Host "$outputSpace A potential integrity corruption is detected." -ForegroundColor Cyan
			Write-Host ""
			Write-Host "$outputSpace Tamper Protection: ON | Coro Agent2 service: Stopped." -ForegroundColor Cyan
			Write-Host "$outputSpace The script could not start Coro Agent2 service." -ForegroundColor Cyan
			Write-Host ""
			Write-Host "$outputSpace This means Tamper Protection won't disable on this device if disabled from the Workspace." -ForegroundColor Cyan
			Write-Host "$outputSpace As Coro cannot be uninstalled when Tamper Protection is on, please boot Windows" -ForegroundColor Cyan
			Write-Host "$outputSpace into the Safe Mode and re-run this script again to bypass Tamper Protection and uninstall Coro." -ForegroundColor Cyan
			Write-Host ""
			Write-Host "$outputSpace Please contact Support if you require any assistance with this." -ForegroundColor Cyan
			Write-Host "$outputSpace The script will terminate now." -ForegroundColor Cyan
			Start-Sleep -Seconds 5
			exit 1
            
			} else {
       
			Write-Host "$outputSpace Done!" -ForegroundColor Green
			Start-Sleep -Seconds 1
        
			}
        }
    }        
	} else {

		Write-Host "$outputSpace Done!" -ForegroundColor Green
	}

} else {}

#Check Tamper Protection status

if ($safeMode -eq $false) {

Write-Host "[$outputTimestamp] Detecting Tamper Protection status"

$registryValue1 = Get-ItemProperty -Path $tamperPath -Name $tamperValue -ErrorAction SilentlyContinue

if ($registryValue1 -and $registryValue1.$tamperValue -eq "true") {
    
	Write-Host ""
	Write-Host "$outputSpace Tamper Protection is enabled. Coro cannot uninstall when Tamper protection is enabled." -ForegroundColor Cyan
	Write-Host "$outputSpace Please disable the Tamper Protection from Coro Workspace, wait 10-15 minutes and retry the script." -ForegroundColor Cyan
	Write-Host ""
	Write-Host "$outputSpace If your Coro agent is corrupted and doesn't communicate with the Workspace, please run" -ForegroundColor Cyan
	Write-Host "$outputSpace this script in Safe Mode to uninstall." -ForegroundColor Cyan
	Write-Host ""
	Write-Host "$outputSpace Please contact Support if you require any assistance with this." -ForegroundColor Cyan
	Write-Host ""
	Write-Host "$outputSpace The script will now terminate as it cannot uninstall Coro when Tamper Protection is enabled." -ForegroundColor Cyan
	Start-Sleep -Seconds 20
	exit 1

} else {
    
	Write-Host "$outputSpace Tamper Protection is disabled" -ForegroundColor Green
}
}	else {
	
}

#Check Coro version

$version42 = $false

if ($safeMode -eq $false -and $skipNativeUninstall -eq $false) {

	Write-Host "[$outputTimestamp] Obtaining Coro version number"

	if (Test-Path $tamperPath) {

    $versionValue = Get-ItemProperty -Path $tamperPath -Name "Version" -ErrorAction SilentlyContinue

      if ($versionValue) {

        if ($versionValue.$valueName -eq "2.0.42.1") {

			$version42 = $true

            Write-Host "$outputSpace Version 2.0.42.1 detected. This version cannot be uninstalled in traditional way." -ForegroundColor Cyan
			Write-Host "$outputSpace Please download the latest Stable version of Coro from the Workspace, install it and retry this script again." -ForegroundColor Cyan
			Write-Host "$outputSpace If you are unable to install Coro due to corruption, please either run this script in Safe Mode" -ForegroundColor Cyan
			Write-Host "$outputSpace or set the value of `$skipNativeUninstall to `$true in this script and re-run the script." -ForegroundColor Cyan
			Write-Host ""
			Write-Host "$outputSpace Please contact Support first and show this message." -ForegroundColor Cyan
			Write-Host ""
			Write-Host "$outputSpace The script will terminate now." -ForegroundColor Cyan
			Start-Sleep -Seconds 30
			exit 1

        } else {

			$version42 = $false
			Write-Host "$outputSpace Done! Coro version: $($versionValue.Version)" -ForegroundColor Green
        }

    } else {

        $version42 = $false
		Write-Output "Version value not found. This might be because Coro is either uninstalled or corrupted." -ForegroundColor Cyan
	}

	} else {

	$version42 = $false
	Write-Host "$outputSpace Version not found. This might be because Coro was previously removed." -ForegroundColor Cyan
	
	}

} else {}

#Detect and stop Coro services

Write-Host "[$outputTimestamp] Detecting and stopping Coro services"

$services = Get-Service -DisplayName "Coro*"

if ($services) {
    
    $failedServices = @()
    
    foreach ($service in $services) {
        
        if ($service.Name -eq "CoroProtectedService") {
            continue
        }

        $service | Stop-Service -Force -WarningAction SilentlyContinue -ErrorVariable err 2>&1 | Out-Null

        if ($err) {

            Start-Sleep -Seconds 5
            $service | Stop-Service -Force -WarningAction SilentlyContinue -ErrorVariable retryErr 2>&1 | Out-Null
            
            if ($retryErr) {
                $failedServices += [PSCustomObject]@{
                    Name = $service.Name 
                    Error = $retryErr[0].Exception.Message
                } 
            }
        }
    }

    if ($failedServices) {
        foreach ($fail in $failedServices) {

            Write-Host "$outputSpace $($fail.Error)" -ForegroundColor Red 
        }
    
	} else {

        Write-Host "$outputSpace Done!" -ForegroundColor Green
    }

} else {

    Write-Host "$outputSpace Couldn't detect Coro services." -ForegroundColor Cyan
    Write-Host "$outputSpace But the script will carry on." -ForegroundColor Green
}

#Uninstall Coro

	Write-Host "[$outputTimestamp] Uninstalling Coro"

	$uninstalled = $false

<#
if ($safeMode -eq $false -and $skipNativeUninstall -eq $false -and $version42 -eq $false) {

	try {
    
		if ($wmiValue -eq $true) {
        
			Write-Host "$outputSpace Uninstalling Coro using the first method."

			try {
            			
				$uninstalledWmi = Start-Process msiexec.exe -PassThru -Wait -ArgumentList "/x $wmiIdentifyingNumber /qn"
				$exitCodeWmi = $uninstalledWmi.ExitCode
                				
				if ($exitCodeWmi -eq 0) {
                
					$uninstalled = $true
					Write-Host "$outputSpace Done!" -ForegroundColor Green
                
				} elseif ($exitCodeWmi -eq 1619) {
					
					$uninstalled = $false
					Write-Host "$outputSpace wmiIdentifyingNumber not found but the script will carry on." -ForegroundColor Cyan
				
				} elseif ($exitCodeWmi -eq 1639){	

					$uninstalled = $false
					Write-Host "$outputSpace uninstalledWmi: failed as arguments (/qn) are wrong. But the script will carry on."  -ForegroundColor Cyan
					
				} elseif ($exitCodeWmi -eq 1720) {
    
					$uninstalled = $false
					Write-Host "$outputSpace uninstalledWmi: There is a problem with the Windows Installer package but the script will carry on."  -ForegroundColor Cyan
		
				} 	elseif ($exitCodeWmi -eq 1619) {
    
					$uninstalled = $false
					Write-Host "$outputSpace uninstalledWmi: The installation package could not be opened but the script will carry on."  -ForegroundColor Cyan

				} else {

					$uninstalled = $false
					Write-Host "$outputSpace The first method didn't work. Error code: $exitCodeWmi" -ForegroundColor Cyan
					Write-Host "$outputSpace But the script will try the next uninstall method." -ForegroundColor Cyan
				}
            
			} catch { } 
		}
        
		} catch { }	
} 
#>
		
if ($registryResult64 -and $uninstalled -eq $false) {

	try {	
		
		if ($safeMode -eq $false -and $skipNativeUninstall -eq $false -and $version42 -eq $false) {
        
			try {
				
			Write-Host "$outputSpace Uninstalling Coro using the second method."
			
			$uninstalledReg64 = Start-Process msiexec.exe -PassThru -Wait -ArgumentList "/x $uninstallStringReg64 /qn"
			$ExitCodeReg64 = $uninstalledReg64.ExitCode
			
			if ($ExitCodeReg64 -eq 0) {
                
					Write-Host "$outputSpace Done!" -ForegroundColor Green

					$uninstalled = $true
                
				} elseif ($ExitCodeReg64 -eq 1619) {
					
					Write-Host "$outputSpace uninstallStringReg64 not found but the script will carry on." -ForegroundColor Cyan
					$uninstalled = $false

				} elseif ($ExitCodeReg64 -eq 1639){	

					Write-Host "$outputSpace The second method failed as arguments (/qn) are wrong. The script will carry on."  -ForegroundColor Cyan
					$uninstalled = $false
						
				} elseif ($ExitCodeReg64 -eq 1720) {
    
					Write-Host "$outputSpace uninstalledReg64: There is a problem with the Windows Installer package. The script will carry on."  -ForegroundColor Cyan
					$uninstalled = $false
				
				} 	elseif ($ExitCodeReg64 -eq 1619) {
    
					Write-Host "$outputSpace uninstalledReg64: The installation package could not be opened. The script will carry on."  -ForegroundColor Cyan
					$uninstalled = $false
				
				} else {

					Write-Host "$outputSpace The second method didn't work. Error code: $ExitCodeReg64" -ForegroundColor Cyan
					Write-Host "$outputSpace But the script will try the next uninstall method." -ForegroundColor Cyan
					$uninstalled = $false
				}
            
			} catch { 

				$uninstalled = $false
			}
        
		} else {

		$uninstalled = $false

		}
		
	} catch { 

	$uninstalled = $false
	
	}

} else {

	$uninstalled = $true
}

if ($uninstalled -eq $false) {

Write-Host "$outputSpace Uninstalling Coro using the third method" -ForegroundColor Yellow

} else {

Write-Host "$outputSpace Coro is uninstalled." -ForegroundColor Green
Write-Host "[$outputTimestamp] Removing leftovers"

}

#Remove Coro and its leftovers

try {

	taskkill /IM coro-notifications.exe /F > $null 2>&1
	taskkill /IM coro.exe /F > $null 2>&1

	} catch {}

####

$registryPath1 = "HKLM:\SYSTEM\CurrentControlSet\Services" 

	Get-ChildItem -Path $registryPath1 | ForEach-Object {

	if ($_.PSChildName -like "Coro*") {

	Remove-Item -Path "$registryPath1\$($_.PSChildName)" -Force -Recurse -ErrorAction SilentlyContinue
		
	}
}

####

$registryPath2 = "HKLM:\SOFTWARE\Bitdefender"

	if (Test-Path -Path $registryPath2) {

    Remove-Item -Path $registryPath2 -Force -Recurse -ErrorAction SilentlyContinue
} 

####

$registryPath3 = "HKLM:\SOFTWARE\Coro Cyber Security Ltd"

	if (Test-Path -Path $registryPath3) {

    Remove-Item -Path $registryPath3 -Force -Recurse -ErrorAction SilentlyContinue
}

####

#### Please note that if the user doesn't have permissions to run Powershell and it requires an admit to enter their credentials, then the Powershell script will essentialy
#### look into admin's HKCU hive, so user's HKCU hive entries will not be deleted. In this case, it might be required to delete the entry below manually as the user. This is not #### the case when user just selects Run Powershell as Administrator and elevates the Powershell with their own user account, without entering admin credentials.
#### This is also irrelevant when the script is deployed via GPO/RMM as it is deployed on system level

$registryPath4 = "HKCU:\SOFTWARE\Microsoft\Installer\Products"

if (Test-Path $registryPath4) {

		Get-ChildItem $registryPath4 | ForEach-Object {
    
		$property = Get-ItemProperty -Path "$registryPath4\$($_.PSChildName)"

		if(($property.PSObject.Properties | Where-Object { $_.Value -match "Coro" })) {
			
		Remove-Item -Path "$registryPath4\$($_.PSChildName)" -Force -Recurse -ErrorAction SilentlyContinue
	
		} 
	}
}

####

$registryPath5 = "HKLM:\SOFTWARE\Microsoft\Windows\CurrentVersion\Installer\Folders"

if (Test-Path -Path $registryPath5) {

	if ($wmiValue -eq $true) {

		$registryItems = Get-ItemProperty -Path $registryPath5

		foreach ($property in $registryItems.PSObject.Properties) {
        
        if ("$($property.Name)" -like "*$wmiIdentifyingNumber*") {

            try {

            Remove-ItemProperty -Path $registryPath5 -Name $property.Name -Force -ErrorAction SilentlyContinue

            } catch {}
        }
    }
	}
}

####

$registryPath6 = "HKLM:\SOFTWARE\Microsoft\Windows\CurrentVersion\Installer\Managed"

if (Test-Path -Path $registryPath6) {

    if ($wmiValue -eq $true) {

        $hivekeys = Get-ChildItem -Path $registryPath6 -Recurse

        foreach ($hivekey in $hivekeys) {

            if ($hivekey.PSChildName -like "*$wmiIdentifyingNumber*") {
          
                if (Test-Path -Path $hivekey.PSPath) {
          
					try {
                    
						Remove-Item -Path $hivekey.PSPath -Force -Recurse -ErrorAction SilentlyContinue
                    
					} catch { }
                }
            
			} else {
            
                $hivekeyValues = Get-ItemProperty -Path $hivekey.PSPath
           
				foreach ($value in $hivekeyValues.PSObject.Properties) {
                    if ($value.Value -is [string] -and $value.Value -like "*$wmiIdentifyingNumber*") {
                
                        if (Test-Path -Path $hivekey.PSPath) {
                
						try {
                        
							Remove-Item -Path $hivekey.PSPath -Force -Recurse -ErrorAction SilentlyContinue
                            
							} catch { }
                        }
                        
						break 
                    }
                }
            }
        }
    }
}

####

$registryPath7 = "HKLM:\SOFTWARE\Classes\Installer\Products"
			
	Get-ChildItem -Path $registryPath7 | ForEach-Object {
    
	$values1 = Get-ItemProperty -Path "$registryPath7\$($_.PSChildName)"

	if(($values1.PSObject.Properties | Where-Object { $_.Value -match "Coro" })) {
			
	Remove-Item -Path "$registryPath7\$($_.PSChildName)" -Force -Recurse -ErrorAction SilentlyContinue
		
	} 
}

####

$registryPath8 = "HKLM:\SOFTWARE\Microsoft\Windows\CurrentVersion\Uninstall"

	Get-ChildItem -Path $registryPath8 | ForEach-Object {
    
	$values2 = Get-ItemProperty -Path "$registryPath8\$($_.PSChildName)"

	if(($values2.PSObject.Properties | Where-Object { $_.Value -match "Coro" })) {
			
	Remove-Item -Path "$registryPath8\$($_.PSChildName)" -Force -Recurse -ErrorAction SilentlyContinue
	
	} 
}

####

$registryPath9 = "HKLM:\SOFTWARE"

	Get-ChildItem -Path $registryPath9 | ForEach-Object { 
        
	if ($_.Name -match "Coro*") { 

    Remove-Item -Path $_.PSPath -Force -Recurse -ErrorAction SilentlyContinue 
	
	}
}

####

$registryPath10 = "HKCU:\SOFTWARE"

	Get-ChildItem -Path $registryPath10  | ForEach-Object { 
        
	if ($_.Name -like "Coro*") { 

    Remove-Item -Path $_.PSPath -Force -Recurse -ErrorAction SilentlyContinue 
		
	}
}

####

$registryPath11 = "HKLM:\SOFTWARE\Microsoft\Windows\CurrentVersion\Installer\Folders"

    if (Test-Path -Path $registryPath11) {

	$registryNewItems = Get-ItemProperty -Path $registryPath11

    foreach ($property in $registryNewItems.PSObject.Properties) {
        
			if ("$($property.Name)" -like "*Coro*") {

			try {

			Remove-ItemProperty -Path $registryPath11 -Name $property.Name -Force -ErrorAction SilentlyContinue

			} catch {}
		}
	}
}

####

$registryPath12 = "HKLM:\SOFTWARE\Classes\Installer\Products"

if (Test-Path -Path $registryPath12) {
	
	if ($wmiValue -eq $true) {

	Get-ChildItem -Path $registryPath12 | ForEach-Object {
    
	$values12 = Get-ItemProperty -Path "$registryPath12\$($_.PSChildName)"

		if(($values12.PSObject.Properties | Where-Object { $_.Value -like "*$wmiIdentifyingNumber*" })) {
			
		Remove-Item -Path "$registryPath12\$($_.PSChildName)" -Force -Recurse -ErrorAction SilentlyContinue
		
		} 
	}
	}
}

####

$registryPath13 = "HKLM:\SOFTWARE\Microsoft\Windows\CurrentVersion\Uninstall"

if (Test-Path -Path $registryPath13) {	

	if ($wmiValue -eq $true) {

	Get-ChildItem -Path $registryPath13 | ForEach-Object {
    
	$values11 = Get-ItemProperty -Path "$registryPath13\$($_.PSChildName)"

		if(($values11.PSObject.Properties | Where-Object { $_.Value -like "*$wmiIdentifyingNumber*" })) {
			
		Remove-Item -Path "$registryPath13\$($_.PSChildName)" -Force -Recurse -ErrorAction SilentlyContinue
		
		} 
	}
	}
}

####

$registryPath14 = "HKLM:\SYSTEM\Setup\FirstBoot\Services" 

	if (Test-Path -Path $registryPath14) {

	Get-ChildItem -Path $registryPath14 | ForEach-Object {

	if ($_.PSChildName -like "Coro*") {

	Remove-Item -Path "$registryPath14\$($_.PSChildName)" -Force -Recurse -ErrorAction SilentlyContinue
		
		}
	}
}

####

$registryPath15 = "HKLM:\SOFTWARE\Microsoft\Windows\CurrentVersion\Installer\UserData\S-1-5-18\Components"

	if (Test-Path -Path $registryPath15) {

	Get-ChildItem -Path $registryPath15 | ForEach-Object {
    
	$values15 = Get-ItemProperty -Path "$registryPath15\$($_.PSChildName)"

		if(($values15.PSObject.Properties | Where-Object { $_.Value -like "*Coro*" })) {
			
		Remove-Item -Path "$registryPath15\$($_.PSChildName)" -Force -Recurse -ErrorAction SilentlyContinue
		
		} 
	}
}

####

$registryPath16 = "HKLM:\SOFTWARE\Microsoft\Windows\CurrentVersion\Installer\UserData\S-1-5-18\Products"

if (Test-Path -Path $registryPath16) {

    if ($wmiValue -eq $true) {

        $newhivekeys = Get-ChildItem -Path $registryPath16 -Recurse

        foreach ($newhivekey in $newhivekeys) {

            if (-not (Test-Path -Path $newhivekey.PSPath)) {

                continue
            }

            if ($newhivekey.PSChildName -like "*$wmiIdentifyingNumber*") {

                try {

                    Remove-Item -Path $newhivekey.PSPath -Force -Recurse -ErrorAction SilentlyContinue

                } catch { }
            
            } else {

                $newhivekeyValues = Get-ItemProperty -Path $newhivekey.PSPath
                $shouldDeleteParent = $false  

                foreach ($valuepo in $newhivekeyValues.PSObject.Properties) {

                    if ($valuepo.Value -is [string] -and $valuepo.Value -like "*$wmiIdentifyingNumber*") {

                        $shouldDeleteParent = $true
                        break 
                    }
                }

                if ($shouldDeleteParent) {

                    $parentKeyPath = Split-Path -Path $newhivekey.PSPath -Parent

                    if (Test-Path -Path $parentKeyPath) {

                        try {

                            Remove-Item -Path $parentKeyPath -Force -Recurse -ErrorAction SilentlyContinue

                        } catch {

                        }
                    }
                }
            }
        }
    }
}

####

$filepath1 = "C:\Windows\System32\drivers\corodriver.sys"

if (Test-Path -Path $filepath1 -PathType Leaf) {

    Remove-Item -Path $filepath1 -Force -ErrorAction SilentlyContinue
} 

####

$filepath2 = "C:\Windows\System32\drivers\CoroWPDFilter.sys"

if (Test-Path -Path $filepath2 -PathType Leaf) {

    Remove-Item -Path $filepath2 -Force -ErrorAction SilentlyContinue
} 

####

$directoryPath1 = "C:\ProgramData\CoroInstaller"

if (Test-Path -Path $directoryPath1 -PathType Container) {

    Remove-Item -Path $directoryPath1 -Force -Recurse -ErrorAction SilentlyContinue
}

####

$directoryPath2 = "$env:localappdata\Coro"

if (Test-Path -Path $directoryPath2 -PathType Container) {

    Remove-Item -Path $directoryPath2 -Force -Recurse -ErrorAction SilentlyContinue
} 

####

$directoryPath3 = "C:\Program Files\Coro Cyber Security Ltd"

if (Test-Path -Path $directoryPath3 -PathType Container) {

    Remove-Item -Path $directoryPath3 -Force -Recurse -ErrorAction SilentlyContinue  
}

####

$directoryPath4 = "C:\ProgramData\CoroAgent1SRV"

	if (Test-Path -Path $directoryPath4 -PathType Container) {

	Remove-Item $directoryPath4 -Force -Recurse -ErrorAction SilentlyContinue
		
} 

####

$directoryPath5 = "C:\ProgramData\CoroAgent2SRV"

	if (Test-Path -Path $directoryPath5 -PathType Container ) {

	Remove-Item $directoryPath5 -Force -Recurse -ErrorAction SilentlyContinue
			
} 

Write-Host "$outputSpace Done!" -ForegroundColor Green
Write-Host ""
Write-Host "All done. Please reboot your machine to complete the procedure."  -ForegroundColor Green
Start-Sleep -Seconds 7

Adding the uninstall script to Atera

To add the Coro uninstall script to the Atera RMM platform, perform the following steps:

  1. Sign into the Atera RMM platform using an administrator account.
  2. Select New , and then select Script :

    Atera new script

    The Create script dialog appears.

  3. Enter the following new script information:
    Field Description
    Script Name Enter a suitable script name, for example, "Coro_Uninstall".
    File type Select ".ps1".
    Script Description Enter a suitable script description, for example, "This script removes the Coro Agent from specified devices."

    Atera new script information

  4. Expand More script properties , and then enter the following additional script information:
    Field Description
    Category Leave blank.
    Max script run time (minutes) Enter "10".
    Arguments Leave blank.
    Run as Select System.

    Atera new script additional information

  5. Copy and paste your Coro uninstall script into the Script editor :

    Script editor

  6. Select Create :

    Create

    Atera creates the uninstall script, and it appears on the My Scripts tab on the Scripts page ready for deployment:

    My scripts

Uninstalling Coro

To uninstall the Coro Agent from selected endpoint devices using the uninstall script, perform the following steps:

  1. Sign into the Atera RMM platform using an administrator account.
  2. Go to Devices :

    Devices

    A list of all devices appears.

  3. From the My Scripts tab, select the checkbox next to each device from which you want to uninstall the Coro Agent, and then select Run Script :

    Select devices

    The Run script on devices dialog appears:

    Run script

  4. Select Run , located next to the Coro uninstall script:

    Run script

    The uninstall script executes and a notification appears:

    Script executed

  5. To monitor the progress of the script deployment, go to Reports > Classic Reports > Recent Processes :

    Recent Processes

    The Current Status displays "In Progress":

    Current Status

    The Coro Agent is removed from the selected devices.

    After script deployment, the Current Status changes to "Ended".

  6. Hover over ? to view the script deployment result:

    Completed

    A result of 1 Completed confirms successful deployment.

Known issues

  • You receive the following error when executing a Powershell script from the Atera RMM platform: 'powershell.exe' is not recognized as an internal or external command, operable program or batch file .

    Make sure that the path to the PowerShell executable file is included in the Windows Path environment variable.

    To include the path to the PowerShell executable file in the Windows Path environment variable:

    1. From the Windows search bar enter system environment variables .
    2. Select Edit the system environment variables :

      System environment variables

    3. In the System Properties window select Environment Variables... :

      Environment variables

    4. From the System variables section select the Path variable, and then select Edit... :

      System variables

    5. From the Edit environment variable dialog select New :

      Edit environment variable

    6. Enter the directory path to your Powershell installation. For example: C:\Windows\System32\WindowsPowerShell\v1.0\ :

      New environment variable

    7. Select OK .

    The path to the PowerShell executable file is added to the Windows System variables list.