Deploying and uninstalling the Coro Agent with Windows Server GPO

This guide explains how to deploy and uninstall the Coro Agent on your Windows endpoint devices using the Windows Server Group Policy Object (GPO) manager.

Important

Coro recommends creating a new GPO specifically designed for deploying the Coro Agent.

Deploying the Coro Agent using a new deployment GPO

To create a new deployment GPO:

  1. From your Windows server device, access the Group Policy Management console (select Windows Key + R , enter gpmc.msc , and select OK ).
  2. Create a new GPO and provide a suitable name.
    note

    The GPO name must not exceed the Windows 260 character path limit and must not contain special characters.

  3. Link the GPO to the domain or the dedicated organizational unit (OU) containing the target workstations for Coro deployment.

    After creating and linking the new GPO, make a note of the ID of the policy (double-click the GPO and select the Details tab):

    Default Domain Policy

  4. Obtain a Windows PowerShell deployment script configured for your workspace as follows:
    Expand for more details
    Copy
    Copied
    #Please add Coro installation URL below (in between quotes "")
    
    $url = "please paste Coro download URL here, but don't delete the quotes"
    
    ###NO NEED TO AMEND ANYTHING BELOW THIS LINE###
    
    #Elevate the script, if not elevated
    
    $elevated = ([Security.Principal.WindowsPrincipal] [Security.Principal.WindowsIdentity]::GetCurrent()).IsInRole([Security.Principal.WindowsBuiltInRole]"Administrator")
    
    if (-not $elevated) {
        
        try {
        
            Write-Host "This Powershell instance is not elevated. Elevating now..."
            $args = "-ExecutionPolicy Bypass", "-File `"" + $myinvocation.MyCommand.Path + "`" " + $myinvocation.UnboundArguments
            Start-Process powershell -Verb runAs -ArgumentList $args
            exit
        
        } catch {
        
            Write-Host "Error while trying to elevate: $($_.Exception.Message) (Error code: $($_.Exception.HResult))" -ForegroundColor Cyan
            Write-Host""
            Write-Host"The script requires elevated permissions, please run it as Administrator" -ForegroundColor Cyan
            Start-Sleep -Seconds 3
            exit 1
        }
    
    } else {
    
        Write-Host ""
        Write-Host "This instance is now elevated, proceeding to the next step"
        Write-Host ""
    }
    
    #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 {
    }
    
    #Extract file name from the URL
    
    $filename = [System.IO.Path]::GetFileName([System.Uri]$url)
    
    if ($filename -match 'CoroInstaller_(.*?)\.msi') {
    
        $newFilename = "CoroInstaller_$($matches[1]).msi"
        $msiFilePath = "C:\Windows\Temp\$newFilename"
    
        } else {
    
        Write-Host ""
        Write-Host "Could not trim the URL" -ForegroundColor Cyan
        Write-Host "Please contact Support and send a screenshot of this output" -ForegroundColor Cyan
        Start-Sleep -Seconds 5
        exit 1
    }
    
    #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 .

    Standard deployment script variables

    For example:

    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

    Standard deployment script variables populated

    Important

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

    note

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

    Save this script as a PowerShell file on the Windows server device hosting your Active Directory and GPO, in the following location:

    Copy
    Copied
    \\[your domain]\sysvol\[your domain]\Policies\{ID of GPO obtained in Step 2 above}\MACHINE\Scripts\Startup  
    note

    If do not have sufficient permissions to save files to this location, save the script to:

    Copy
    Copied
    C:\Windows\SYSVOL\domain\Policies\{ID of GPO obtained in Step 2 above}\Machine\Scripts\Startup
  5. In the Group Policy Management Editor , right-click the newly created group policy object and select Edit :

    Group Policy Object edit

  6. Go to Computer Configuration > Policies > Windows Settings > Scripts(Startup/Shutdown) :

    Startup Properties dialog

  7. Double-click Startup :

    Startup

    The Startup Properties dialog appears.

  8. Select the PowerShell Scripts tab and then select Add :

    Startup Properties

    The Add a Script dialog appears.

  9. Select Browse :

    Add a Script

  10. Go to the location where you saved the PowerShell script file and then select Open :

    Selecting the Coro PowerShell file

  11. Select OK :

    Selecting the Coro PowerShell file

    The file is added to the PowerShell Scripts tab in the Windows PowerShell Startup Scripts for Local Computer section of the Startup Properties dialog.

  12. Select Apply and then select OK :

    Selecting the Coro PowerShell file

    The settings are saved, and the Startup Properties dialog closes.

  13. From the same GPO settings, go to Computer Configuration > Policies > Administrative Templates > System > Scripts .
  14. Double-click Specify maximum wait time for Group Policy scripts :

    Set a wait time for Group Policy scripts

    The Specify maximum wait time for Group Policy scripts settings dialog appears. This setting sets the maximum duration allowed for all scripts to finish execution.

  15. Configure the settings as follows:
    • Select Enabled .
    • In the Options section enter the desired number of Seconds for the wait time:

    Set a wait time for Group Policy scripts

    note

    Consider the number of startup items when setting the wait time. Typically, a wait time between 60-120 seconds is recommended.

  16. Select OK to save your changes and then close the Group Policy Management Editor .
  17. Select your GPO from the Group Policy Management console and then select the Delegation tab:

    The GPO Delegation tab

  18. Select Add :

    The GPO Delegation tab

    The Select User, Computer, or Group dialog appears.

  19. Select Object Types :

    The GPO Delegation tab

  20. Select Computers and then select OK :

    The GPO Delegation tab

  21. Enter Domain computers into the Enter the object name to select field and then select OK :

    The GPO Delegation tab

    The Add Group or User dialog appears:

  22. Select Read from the Permissions dropdown and then select OK :

    The GPO Delegation tab

    A Domain Computers entry is added to the Delegation section:

    The GPO Delegation tab

Applying the new GPO to all Organizational Unit workstations

Important

Coro strongly recommends creating a dedicated OU in your Active Directory for all workstations intended for Coro deployment. This is necessary because the Group Policy Management console does not display the default Computers and Users OU in Active Directory:

Organizational Unit

After you create the OU, link the new policy to it to ensure that the policy applies to all workstations:

Organizational Unit

note

Depending on your environment and specific configuration, you can also link this new GPO to the entire domain.

After you have linked the new policy to the OU perform the following steps to apply the GPO to all workstations in the OU:

  1. Go to the Scope tab of the newly created GPO:

    The GPO Scope tab

  2. Select Add from the Security Filtering section:

    The GPO Scope tab

  3. Select Computers and then select OK :

    The GPO Delegation tab

  4. Enter Domain computers into the Enter the object name to select field and then select OK :

    The GPO Delegation tab

    The GPO is applied to all workstations in the OU which are linked to the newly created policy:

    Domain computers

    note

    If you want to deploy Coro to selected workstations without creating a dedicated OU, or if you want to use an existing OU other than the default Computers OU, you must add the individual workstations to the Security Filtering section, rather than Domain Computers:

    Individual workstations

    Important

    Coro strongly recommends that you create a dedicated OU in your Active Directory for all workstations intended for Coro deployment, instead of adding individual workstations to the policy.

  5. Reboot your endpoint devices at least twice to ensure that the group policy changes take effect. Alternatively, execute the command gpupdate /force in a Command Prompt to apply the policy; in this case, only one reboot is necessary.

Troubleshooting

If the policy fails to apply:

  1. Go to the Group Policy Results module in the Group Policy Management console.
  2. Run the wizard against the workstation in question (right-click the Group Policy Results item and then select Group Policy Results Wizard .)
  3. Verify that the policy is applied to the workstation:

    Group Policy Results

If the policy is successfully applied:

  • The policy instructs the workstation to download and install the Coro agent. The time this takes can vary based on internet speed, and deployment progress may not be immediately visible.
  • Deployment might also be affected by any existing internet restrictions. Wait 15-20 minutes to allow the installation to complete before starting any troubleshooting.

If the policy does not take effect after several reboots and a waiting period:

  • Determine if other restrictive policies might be interfering with policy application. You can check which policies are affecting the workstation by adding it to the Group Policy Results module in the Group Policy Management console.
  • Policy application might fail if Windows Firewall settings block communication between the device and the domain controller. If so, temporarily disable Windows Firewall, reboot the device, and check if this resolves the issue.

Uninstalling the Coro Agent with Windows Server GPO

Important

Coro recommends creating a new GPO specifically designed for uninstalling the Coro Agent.

You can follow the same steps described in Deploying the Coro Agent to uninstall the Coro Agent from your Windows endpoint devices through Windows Server Group Policy Object (GPO) manager. You can obtain a Windows PowerShell uninstall script as follows:

Expand for more details
Copy
Copied
#Elevate the script, if not elevated

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

if (-not $elevated) {
    
    try {
    
        Write-Host "This Powershell instance is not elevated. Elevating now..."
        $args = "-ExecutionPolicy Bypass", "-File `"" + $myinvocation.MyCommand.Path + "`" " + $myinvocation.UnboundArguments
        Start-Process powershell -Verb runAs -ArgumentList $args
        exit
    
    } catch {
    
        Write-Host "Error while trying to elevate: $($_.Exception.Message) (Error code: $($_.Exception.HResult))" -ForegroundColor Cyan
        Write-Host""
        Write-Host"The script requires elevated permissions, please run it as Administrator" -ForegroundColor Cyan
        Start-Sleep -Seconds 3
        exit 1
    }

} else {

    Write-Host ""
    Write-Host "This instance is now elevated, proceeding to the next step"
    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...)"

$packageToDelete = "Coro*"
$softwareName = "Coro"

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

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

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

$valueReg64 = $registryResult64.UninstallString

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

if ($match.Success) {

    $uninstallStringReg64 = $match.Value

} else { }

try {

    $packageResult = Get-Package | Where-Object { $_.Name -like $packageToDelete }

    } catch {
}

try {

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

    if ($wmiResult -ne $null) {

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

    } else {

    }
    
    } catch {
    
}

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

#Check if Coro is installed

function Check-Installed {
    
    Write-Host "[$outputTimestamp] Detecting $softwareName"

    $installed = $false	

    if ($registryResult32 -or $registryResult64 -or $packageResult -or $wmiResult) {

        $installed = $true

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

    } elseif (Test-Path "C:\Program Files\Coro Cyber Security Ltd\Coro\user\Coro.exe") {

        $installed = $true

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

        Write-Host "$outputSpace $softwareName is not installed. The script will terminate now." -ForegroundColor Cyan
        Start-Sleep -Seconds 5
        exit 1
    }

    return $installed
}

$installed = Check-Installed

#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 DarkYellow

}

#Check for potential corruption

if ($installed -eq "true" -and $safeMode -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 ($installed -eq "true" -and $safeMode -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 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 Could not start Coro Agent1 and Coro Agent2 services" -ForegroundColor Cyan
            Write-Host ""
            Write-Host "$outputSpace Please boot Windows into Safe Mode and re-run this script again" -ForegroundColor Cyan
            Write-Host ""
            Start-Sleep -Seconds 3
            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 Could not start Coro Agent1 service" -ForegroundColor Cyan
            Write-Host ""
            Write-Host "$outputSpace Please boot Windows into Safe Mode and re-run this script again" -ForegroundColor Cyan
            Write-Host ""
            Start-Sleep -Seconds 3
            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 Could not start Coro Agent2 service" -ForegroundColor Cyan
            Write-Host ""
            Write-Host "$outputSpace Please boot Windows into Safe Mode and re-run this script again" -ForegroundColor Cyan
            Write-Host ""
            Start-Sleep -Seconds 3
            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 ($installed -eq "true" -and $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 "Tamper Protection is enabled. It needs to be disabled for Coro to uninstall" -ForegroundColor Cyan
    Write-Host ""
    Write-Host "Please do the following to disable it:"
    Write-Host ""
    Write-Host "1. Login to your Coro Workpsace and navigate to Control Panel - Devices - Settings section."
    $text = "2. Untick the Tamper Protection box. It will push the changes to the machine in question as per Heartbeat interval time.`r`n   The Heartbeat interval time is located just above the Tamper Protection box and the default value is 7 minutes."
    Write-Host $text
    Write-Host "3. Retry the script afterwards."
    Write-Host ""
    Write-Host "In addition to the steps above, please also check the status of Coro Agent on the machine in question."
    Write-Host "If it shows 'Protection disabled by Admin' message, you will also need to complete the steps below:"
    Write-Host ""
    Write-Host "1. Login to your Coro Workspace and navigate to Control Panel - Endpoint Security - NGAV section."
    Write-Host "2. Make sure both 'Real-Time Malware' and 'Ransomware Protection and Advanced Threat Control' boxes are ticked."
    Write-Host "3. If they are already ticked, make sure the device in question is added to the label under Advanced Threat Control section."
    Write-Host "4. After that, please navigate to Control Panel - Activity Log section."
    Write-Host "5. Find the entry that says 'Endpoint Protection for (The Name of The Device in Question) has been disabled'"
    Write-Host "6. Click to Undo button to revert the changes. Please contact Support if the Undo button is greyed out." 
    Write-Host "7. Wait for it to push the changes as per Heartbeat interval time."
    Write-Host "8. Once pushed, the status of the Coro Agent on the machine in question will change to 'Protected'." 
    Write-Host "9. Retry the script afterwards."
    Write-Host ""
    Write-Host "Please contact Support if you require any assistance with this"
    Write-Host ""
    Write-Host "The script will now terminate as it cannot proceed when Tamper Protection is enabled" -ForegroundColor Cyan
    Start-Sleep -Seconds 30
    exit 1

} else {
    
    Write-Host "$outputSpace Disabled" -ForegroundColor Green
}
}	else {
    
}

#Detect and stop Coro services

if ($installed -eq "true") {

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

$services = Get-Service -DisplayName "$packageToDelete"

if ($services) {
    
    $failedServices = @()
    
    foreach ($service in $services) {

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

        if($err) {

            $failedServices += [PSCustomObject]@{
                Name = $service.Name 
                Error = $err[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 $softwareName services" -ForegroundColor Cyan
    Write-Host "$outputSpace The script will carry on" 
}
}	else {
    
}	

#Uninstall Coro

if ($installed -eq "true") {
    
    Write-Host "[$outputTimestamp] Uninstalling $softwareName"
    
    try {
    
        if ($wmiValue -eq $true -and $safeMode -eq $false) {
        
            Write-Host "$outputSpace ...using uninstalledWmi method"

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

                    Write-Host "$outputSpace uninstalledWmi method failed as arguments (/qn) are wrong but the script will carry on"  -ForegroundColor Cyan
                    
                } elseif ($exitCodeWmi -eq 1618){	

                    Write-Host "$outputSpace $softwareName cannot be uninstalled because another installation is in progress"  -ForegroundColor Cyan
                    Write-Host "$outputSpace Complete that installation or reboot your machine and execute this script again"  -ForegroundColor Cyan
                    Write-Host "$outputSpace The script will now terminate as it cannot uninstall $softwareName"  -ForegroundColor Cyan
                    Start-Sleep -Seconds 5
                    exit 1
                
                } elseif ($exitCodeWmi -eq 1614) {
    
                    Write-Host "$outputSpace $softwareName cannot be uninstalled because another installation is in progress"  -ForegroundColor Cyan
                    Write-Host "$outputSpace Complete that installation or reboot your machine and execute this script again"  -ForegroundColor Cyan
                    Write-Host "$outputSpace The script will now terminate as it cannot uninstall $softwareName"  -ForegroundColor Cyan
                    Start-Sleep -Seconds 5
                    exit 1
                
                } 	elseif ($exitCodeWmi -eq 1720) {
    
                    Write-Host "$outputSpace uninstalledWmi: There is a problem with the Windows Installer package but the script will attempt to carry on"  -ForegroundColor Cyan
                
                } 	elseif ($exitCodeWmi -eq 1619) {
    
                    Write-Host "$outputSpace uninstalledWmi: The installation package could not be opened but the script will attempt to carry on"  -ForegroundColor Cyan
                
                } else {

                    Write-Host "$outputSpace uninstalledWmi method didn't work: $exitCodeWmi" -ForegroundColor Cyan
                    Write-Host "$outputSpace But the script will try the next uninstall method" -ForegroundColor Cyan
                }
            
            } catch { }
        
        } else { }
        
        } catch { }
        
        try {	
        
        if ($wmiMethodSuccess -ne $true -and $safeMode -eq $false) {
        
            try {
                
            Write-Host "$outputSpace ...trying to uninstall using uninstalledReg64 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
                    $reboot = $true
                    $uninstalledReg64MethodSuccess = $true
                
                } elseif ($ExitCodeReg64 -eq 1619) {
                    
                    Write-Host "$outputSpace uninstallStringReg64 not found but the script will carry on" -ForegroundColor Cyan
                
                } elseif ($ExitCodeReg64 -eq 1639){	

                    Write-Host "$outputSpace uninstalledReg64 method failed as arguments (/qn) are wrong. The script will carry on"  -ForegroundColor Cyan
                        
                } elseif ($ExitCodeReg64 -eq 1618){	

                    Write-Host "$outputSpace $softwareName cannot be uninstalled because another installation is in progress"  -ForegroundColor Cyan
                    Write-Host "$outputSpace Complete that installation or reboot your machine and execute this script again"  -ForegroundColor Cyan
                    Write-Host "$outputSpace The script will now terminate as it cannot uninstall $softwareName"  -ForegroundColor Cyan
                    Start-Sleep -Seconds 5
                    exit 1
                
                } elseif ($ExitCodeReg64 -eq 1614) {
    
                    Write-Host "$outputSpace $softwareName cannot be uninstalled because another installation is in progress"  -ForegroundColor Cyan
                    Write-Host "$outputSpace Complete that installation or reboot your machine and execute this script again"  -ForegroundColor Cyan
                    Write-Host "$outputSpace The script will now terminate as it cannot uninstall $softwareName"  -ForegroundColor Cyan
                    Start-Sleep -Seconds 5
                    exit 1
                
                } 	elseif ($ExitCodeReg64 -eq 1720) {
    
                    Write-Host "$outputSpace uninstalledReg64: There is a problem with the Windows Installer package. The script will carry on"  -ForegroundColor Cyan
                
                } 	elseif ($ExitCodeReg64 -eq 1619) {
    
                    Write-Host "$outputSpace uninstalledReg64: The installation package could not be opened. The script will carry on"  -ForegroundColor Cyan
                
                } else {

                    Write-Host "$outputSpace uninstalledReg64 method didn't work: $ExitCodeReg64" -ForegroundColor Cyan
                    Write-Host "$outputSpace But the script will try the next uninstall method" -ForegroundColor Cyan
                }
            
            } catch { }
        } 
        
    } catch { }

    try {	
        
        if ($wmiMethodSuccess -ne $true -and $uninstalledReg64MethodSuccess -ne $true) {

            Write-Host "$outputSpace ...using alternative uninstall method"

            #Kill Coro process from Task Manager

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

            #Delete Coro entries from HKLM:\System\CurrentControlSet\Services hive

            $name = "*Coro*"

            Get-ChildItem "HKLM:\System\CurrentControlSet\Services" | ForEach-Object {

            if ($_.PSChildName -like $name) {

            Remove-Item -Path "Registry::HKEY_LOCAL_MACHINE\System\CurrentControlSet\Services\$($_.PSChildName)" -Recurse -Force -ErrorAction SilentlyContinue
            
                }
            }

            #Delete Coro entries from HKLM:\SOFTWARE\Classes\Installer\Products hive

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

            if(($values1.PSObject.Properties | Where-Object { $_.Value -match $softwareName })) {
            
            Remove-Item -Path "Registry::HKEY_LOCAL_MACHINE\SOFTWARE\Classes\Installer\Products\$($_.PSChildName)" -Recurse -Force -ErrorAction SilentlyContinue
        
                } 
            }

            #Delete Coro entries from HKLM:\SOFTWARE\Microsoft\Windows\CurrentVersion\Uninstall hive

            Get-ChildItem "HKLM:\SOFTWARE\Microsoft\Windows\CurrentVersion\Uninstall" | ForEach-Object {
    
            $values2 = Get-ItemProperty -Path "Registry::HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows\CurrentVersion\Uninstall\$($_.PSChildName)"

            if(($values2.PSObject.Properties | Where-Object { $_.Value -match $softwareName })) {
            
            Remove-Item -Path "Registry::HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows\CurrentVersion\Uninstall\$($_.PSChildName)" -Recurse -Force -ErrorAction SilentlyContinue
        
                } 
            }

            #Delete specific entries and files/folders

            Remove-Item -Path "Registry::HKLM\HKCU:\SOFTWARE\Coro Cyber Security Ltd" -Force -Recurse -ErrorAction SilentlyContinue

            $folder1 = "C:\Program Files\Coro Cyber Security Ltd"
            Remove-Item $folder1 -Recurse -Force -ErrorAction SilentlyContinue

            $folder2 = "C:\ProgramData\CoroAgent1SRV"
            Remove-Item $folder2 -Recurse -Force -ErrorAction SilentlyContinue

            $folder3 = "C:\ProgramData\CoroAgent2SRV"
            Remove-Item $folder3 -Recurse -Force -ErrorAction SilentlyContinue

            $folder4 = "C:\ProgramData\CoroInstaller"
            Remove-Item $folder4 -Recurse -Force -ErrorAction SilentlyContinue

            $file1 = "C:\Windows\System32\drivers\CoroWPDFilter.sys"
            Remove-Item $file1 -Recurse -Force -ErrorAction SilentlyContinue
            
            $file2 = "C:\Windows\System32\drivers\corodriver.sys"
            Remove-Item $file1 -Recurse -Force -ErrorAction SilentlyContinue

            $Reg = "Registry::HKEY_LOCAL_MACHINE\SOFTWARE"
            Get-ChildItem "$Reg" | 
            ForEach-Object { if ($_ -match "Coro*") { Remove-Item -Path "Registry::$_" -Recurse -ErrorAction SilentlyContinue} }

            Write-Host "$outputSpace Done!" -ForegroundColor Green
            $reboot = $true

        } else { }

            } catch {}

} 

#Remove leftovers

if ($reboot -eq $true) {

Write-Host "[$outputTimestamp] Removing leftovers"
Start-Sleep -Seconds 1

$registryPath1= "Registry::HKLM\SYSTEM\CurrentControlSet\Services\corodriver"
$registryPath2 = "Registry::HKLM\SOFTWARE\Bitdefender"
$registryPath3 = "Registry::HKLM\SOFTWARE\Coro Cyber Security Ltd"
$directoryPath1 = "C:\ProgramData\CoroInstaller"
$directoryPath2 = "%localappdata%\Coro"
$directoryPath3 = "C:\Program Files\Coro Cyber Security Ltd"
$filepath1 = "C:\Windows\System32\drivers\corodriver.sys"
$filepath2 = "C:\Windows\System32\drivers\CoroWPDFilter.sys"

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

    Remove-Item -Path $filepath1 -Force -Recurse -ErrorAction SilentlyContinue
    
    $A = "true"

} else {
    
}

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

    Remove-Item -Path $filepath2 -Force -Recurse -ErrorAction SilentlyContinue
    
    $B = "true"

} else {
    
}

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

    Remove-Item -Path $directoryPath1 -Force -Recurse -ErrorAction SilentlyContinue
    
    $C = "true"

} else {
    
}

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

    Remove-Item -Path $directoryPath2 -Force -Recurse -ErrorAction SilentlyContinue
    
    $D = "true"

} else {
    
}

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

    Remove-Item -Path $directoryPath3 -Force -Recurse -ErrorAction SilentlyContinue
    
    $E = "true"

} else {
    
}

if (Test-Path -Path $registryPath1) {

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

    $F = "true"

} else {

}

if (Test-Path -Path $registryPath2) {

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

    $G = "true"

} else {

}

if (Test-Path -Path $registryPath3) {

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

    $H = "true"

} else {

}

if ($A -or $B -or $C -or $D -or $E -or $F -or $G -or $H) {
    
    Write-Host "$outputSpace Done!" -ForegroundColor Green

} else {
    
    Write-Host "$outputSpace No leftovers found" -ForegroundColor Green
}

} else {
    
}

#Display an interactive reboot prompt with an option to reboot or cancel

##if ($reboot -eq $true) {

##Write-Host "All done, please reboot your machine now to complete the procedure" -ForegroundColor Green

##[void] [System.Reflection.Assembly]::LoadWithPartialName("System.Drawing") 
##[void] [System.Reflection.Assembly]::LoadWithPartialName("System.Windows.Forms") 

##$objForm = New-Object System.Windows.Forms.Form 
##$objForm.ControlBox = $False
##$objForm.minimumSize = New-Object System.Drawing.Size(300,180) 
##$objForm.maximumSize = New-Object System.Drawing.Size(300,180) 
##$objForm.Text = "Cleanup completed"
##$objForm.Size = New-Object System.Drawing.Size(300,100) 
##$objForm.StartPosition = "CenterScreen"
##$objForm.FormBorderStyle = "FixedSingle"

##$objForm.KeyPreview = $True
##$objForm.Add_KeyDown({if ($_.KeyCode -eq "Escape") 
##{$objForm.Close()}})

##$RButton = New-Object System.Windows.Forms.Button
##$RButton.Location = New-Object System.Drawing.Size(50,100)
##$RButton.Size = New-Object System.Drawing.Size(75,25)
##$RButton.Text = "Reboot now"
##$RButton.Add_Click({Restart-Computer -Force})
##$objForm.Controls.Add($RButton)

##$CancelButton = New-Object System.Windows.Forms.Button
##$CancelButton.Location = New-Object System.Drawing.Size(150,100)
##$CancelButton.Size = New-Object System.Drawing.Size(75,25)
##$CancelButton.Text = "Later"
##$CancelButton.Add_Click({$objForm.Close()})
##$objForm.Controls.Add($CancelButton)

##$objLabel = New-Object System.Windows.Forms.Label
##$objLabel.Location = New-Object System.Drawing.Size(10,20) 
##$objLabel.Size = New-Object System.Drawing.Size(280,120)
##$objLabel.Text = "$softwareName has been succesfully uninstalled. Please reboot now to complete the cleanup"
##$objForm.Controls.Add($objLabel) 

##$objForm.Topmost = $True

##$objForm.Add_Shown({$objForm.Activate()})
##[void] $objForm.ShowDialog()

##} else {


#Display the results
    
if ($reboot -eq $true) {

Write-Host ""
Write-Host "All done. Please reboot your machine to complete the procedure"  -ForegroundColor Green

} else {

Write-Host ""
Write-Host "There were issues removing $softwareName. Please contact Support" -ForegroundColor Cyan

}

##}

Start-Sleep -Seconds 5