Skip to content

Instantly share code, notes, and snippets.

@asheroto
Last active May 20, 2026 14:47
Show Gist options
  • Select an option

  • Save asheroto/4b1313fc41b3801a1362d421ff577406 to your computer and use it in GitHub Desktop.

Select an option

Save asheroto/4b1313fc41b3801a1362d421ff577406 to your computer and use it in GitHub Desktop.
Forcefully removes Webroot Endpoint Protection.
#Requires -RunAsAdministrator
<#
.SYNOPSIS
Force removes Webroot SecureAnywhere remnants.
.DESCRIPTION
Designed to be run in Safe Mode. Performs process termination, uninstall attempt,
service removal, registry cleanup, and filesystem cleanup with existence checks.
#>
#region Guardrails
function Test-IsAdmin {
$CurrentUser = [Security.Principal.WindowsPrincipal] [Security.Principal.WindowsIdentity]::GetCurrent()
return $CurrentUser.IsInRole([Security.Principal.WindowsBuiltInRole]::Administrator)
}
function Test-IsSafeMode {
return (Get-ItemProperty -Path "HKLM:\SYSTEM\CurrentControlSet\Control\SafeBoot\Option" -ErrorAction SilentlyContinue) -ne $null
}
if (-not (Test-IsAdmin)) {
Write-Output "ERROR: Script must be run as Administrator."
exit 1
}
if (-not (Test-IsSafeMode)) {
Write-Output "WARNING: System is not in Safe Mode. Cleanup may be incomplete."
}
#endregion
#region Helper Functions
function Remove-RegistryKey {
param ([string]$Path)
if (Test-Path $Path) {
Write-Output "Removing registry key: $Path"
Remove-Item -Path $Path -Recurse -Force -ErrorAction SilentlyContinue
}
}
function Remove-Folder {
param ([string]$Path)
if (Test-Path $Path) {
Write-Output "Removing folder: $Path"
Remove-Item -Path $Path -Recurse -Force -ErrorAction SilentlyContinue
}
}
function Remove-ServiceSafe {
param ([string]$Name)
$Service = Get-WmiObject -Class Win32_Service -Filter "Name='$Name'" -ErrorAction SilentlyContinue
if ($null -ne $Service) {
Write-Output "Disabling service: $Name"
Set-Service -Name $Name -StartupType Disabled -ErrorAction SilentlyContinue
Write-Output "Stopping service: $Name"
Stop-Service -Name $Name -Force -ErrorAction SilentlyContinue
Write-Output "Deleting service via sc.exe: $Name"
sc.exe delete $Name | Out-Null
}
$SvcRegPath = "HKLM:\SYSTEM\CurrentControlSet\Services\$Name"
if (Test-Path $SvcRegPath) {
Write-Output "Removing remaining service registry key: $SvcRegPath"
Remove-Item -Path $SvcRegPath -Recurse -Force -ErrorAction SilentlyContinue
}
}
#endregion
#region Kill Processes First
$Processes = @("WRSA","WRSVC","WRCore","WRSkyClient")
foreach ($Proc in $Processes) {
Get-Process -Name $Proc -ErrorAction SilentlyContinue | ForEach-Object {
Write-Output "Killing process: $($_.Name)"
$_.Kill()
}
}
#endregion
#region Attempt Official Uninstall
$WrsaPaths = @(
"$Env:ProgramFiles\Webroot\WRSA.exe",
"$Env:ProgramFiles(x86)\Webroot\WRSA.exe"
)
foreach ($Wrsa in $WrsaPaths) {
if (Test-Path $Wrsa) {
Write-Output "Attempting uninstall via: $Wrsa"
Start-Process -FilePath $Wrsa -ArgumentList "-uninstall -quiet" -Wait -ErrorAction SilentlyContinue
}
}
#endregion
#region Services
$ServiceNames = @(
"WRSVC",
"WRCoreService",
"WRkrn",
"WRBoot",
"wrUrlFlt",
"WRSkyClient"
)
foreach ($ServiceName in $ServiceNames) {
Remove-ServiceSafe -Name $ServiceName
}
#endregion
#region Registry Cleanup
$ControlSets = Get-ChildItem "HKLM:\SYSTEM" | Where-Object { $_.Name -like "*ControlSet*" }
$RegKeys = @(
"HKLM:\SOFTWARE\WRData",
"HKLM:\SOFTWARE\WRMIDData",
"HKLM:\SOFTWARE\WRCore",
"HKLM:\SOFTWARE\webroot",
"HKLM:\SOFTWARE\WOW6432Node\WRData",
"HKLM:\SOFTWARE\WOW6432Node\WRMIDData",
"HKLM:\SOFTWARE\WOW6432Node\WRCore",
"HKLM:\SOFTWARE\WOW6432Node\webroot",
"HKLM:\SOFTWARE\Microsoft\Windows\CurrentVersion\Uninstall\WRUNINST",
"HKLM:\SOFTWARE\WOW6432Node\Microsoft\Windows\CurrentVersion\Uninstall\WRUNINST"
)
foreach ($Key in $RegKeys) {
Remove-RegistryKey -Path $Key
}
foreach ($CS in $ControlSets) {
foreach ($Svc in $ServiceNames) {
Remove-RegistryKey -Path "$($CS.PSPath)\Services\$Svc"
}
}
#endregion
#region Startup Entries
$StartupPaths = @(
"HKLM:\SOFTWARE\Microsoft\Windows\CurrentVersion\Run",
"HKLM:\SOFTWARE\WOW6432Node\Microsoft\Windows\CurrentVersion\Run"
)
foreach ($Path in $StartupPaths) {
if (Test-Path $Path) {
$Props = Get-ItemProperty -Path $Path
foreach ($Prop in $Props.PSObject.Properties) {
if ($Prop.Value -match "Webroot|WRSA") {
Write-Output "Removing startup entry '$($Prop.Name)' from $Path"
Remove-ItemProperty -Path $Path -Name $Prop.Name -ErrorAction SilentlyContinue
}
}
}
}
#endregion
#region Filesystem Cleanup
$Folders = @(
"$Env:ProgramData\WRData",
"$Env:ProgramData\WRCore",
"$Env:ProgramFiles\Webroot",
"$Env:ProgramFiles(x86)\Webroot",
"$Env:ProgramFiles\Common Files\Webroot",
"$Env:ProgramData\Microsoft\Windows\Start Menu\Programs\Webroot SecureAnywhere",
"$Env:ProgramData\Microsoft\Windows\Start Menu\Programs\OpenText Core Endpoint Protection"
)
foreach ($Folder in $Folders) {
Remove-Folder -Path $Folder
}
#endregion
#region Uninstall Entry Scan
$UninstallRoots = @(
"HKLM:\SOFTWARE\Microsoft\Windows\CurrentVersion\Uninstall",
"HKLM:\SOFTWARE\WOW6432Node\Microsoft\Windows\CurrentVersion\Uninstall"
)
foreach ($Root in $UninstallRoots) {
Get-ChildItem $Root -ErrorAction SilentlyContinue | ForEach-Object {
$Props = Get-ItemProperty $_.PsPath -ErrorAction SilentlyContinue
if ($null -ne $Props.DisplayName -and $Props.DisplayName -match "Webroot") {
Write-Output "Removing uninstall entry: $($Props.DisplayName)"
Remove-Item -Path $_.PsPath -Recurse -Force -ErrorAction SilentlyContinue
}
}
}
#endregion
#region Verification
$RemainingServices = @()
foreach ($Svc in $ServiceNames) {
$Query = sc.exe query $Svc 2>$null
if ($Query -and ($Query -notmatch "FAILED 1060")) {
$RemainingServices += $Svc
}
}
if ($RemainingServices.Count -gt 0) {
Write-Output "NOTICE: Services pending removal until reboot:"
$RemainingServices | ForEach-Object { Write-Output " - $_" }
Write-Output "Reboot is required to complete removal."
} else {
Write-Output "Verification passed: No remaining Webroot services detected."
}
#endregion
Write-Output "Webroot cleanup completed. Please reboot the computer."
exit 0
@axiomcs78

Copy link
Copy Markdown

No devices right now with webroot (hopefully no more webroot). Will test if I can. Thanks for that.

@chadmark

Copy link
Copy Markdown

I am trying this against a number of machines we have rouge Webroot installs on. I did need to make one correction because of an error. On line 51, "$Env:ProgramData\Microsoft\Windows\Start Menu\Programs\OpenText™ Core Endpoint Protection",. The TM after OpenText throws a powershell error. Some unsupported character. Once I removed that, it ran properly. Waiting for the user to reboot and we will see if it works!

@asheroto

Copy link
Copy Markdown
Author

@chadmark thanks for the info. For some reason on my computer, it has the TM symbol. I made some major revisions and added support for both, just in case.

@Johan-Claesson

Copy link
Copy Markdown

Hello, just wanted to say thanks for all the work. Im also gonna try something similar, here is our code (NOT TESTED):

#Requires -RunAsAdministrator
<#
.SYNOPSIS
Safe Webroot removal (no Safe Mode)
.DESCRIPTION
RMM/VSA-friendly and cautious:
- No driver file deletion
- No Winsock/AppId_Catalog deletions
- No HKCR Installer product deletions
- Attempts uninstall with timeout to avoid hanging
- Cleans services, Webroot-specific registry, startup entries, folders
- Cleans orphaned WMI SecurityCenter2 Webroot entries (keeps Defender)
Recommended: Run -> reboot -> run again.
#>

$ErrorActionPreference = "SilentlyContinue"

$ServiceNames = @("WRSVC","WRCoreService","WRSkyClient","WRCore","WRkrn","WRBoot","wrUrlFlt")
$ProcessNames = @("WRSA","WRSVC","WRCore","WRSkyClient","WRUI","WRTray","WRConsumerUI")

$LogDir  = Join-Path $env:ProgramData "\Logs"
$LogPath = Join-Path $LogDir "WebrootRemoval.log"
New-Item -Path $LogDir -ItemType Directory -Force | Out-Null

function Log([string]$Msg) {
    $line = "$(Get-Date -Format 'yyyy-MM-dd HH:mm:ss')  $Msg"
    $line | Out-File -FilePath $LogPath -Append -Encoding UTF8
    Write-Output $line
}

function Remove-RegistryKeySafe([string]$Path) {
    if (Test-Path $Path) {
        try {
            Log "Removing registry key: $Path"
            Remove-Item -Path $Path -Recurse -Force
        } catch {
            Log "Failed removing registry key: $Path ($($_.Exception.Message))"
        }
    }
}

function Remove-FolderSafe([string]$Path) {
    if ([string]::IsNullOrWhiteSpace($Path-Path $Path) {
        try {
            Log "Removing folder: $Path"
            Remove-Item -Path $Path -Recurse -Force
        } catch {
            Log "Failed removing folder: $Path ($($_.Exception.Message))"
        }
    }
}

function Stop-KillProcesses {
    foreach ($p in $ProcessNames) {
        Get-Process -Name $p -ErrorAction SilentlyContinue | ForEach-Object {
            try {
                Log "Killing process: $($_.Name) (PID $($_.Id))"
                $_.Kill()
            } catch {
                Log "Failed killing process: $p ($($_.Exception.Message))"
            }
        }
    }
}

function Remove-ServiceSafe([string]$Name) {
    $svc = Get-Service -Name $Name -ErrorAction SilentlyContinue
    if ($svc) {
        try { Log "Stopping service: $Name"; Stop-Service -Name $Name -Force } catch {}
        try { Log "Disabling service: $Name"; Set-Service -Name $Name -StartupType Disabled } catch {}
        try { Log "Deleting service: $Name"; sc.exe delete $Name | Out-Null } catch {}
    }

    $svcReg = "HKLM:\SYSTEM\CurrentControlSet\Services\$Name"
    if (Test-Path $svcReg) {
        try {
            Log "Removing leftover service registry: $svcReg"
            Remove-Item -Path $svcReg -Recurse -Force
        } catch {}
    }
}

function Try-OfficialUninstall {
    $WrsaPaths = @(
        "$env:ProgramFiles(x86)\Webroot\WRSA.exe",
        "$env:ProgramFiles\Webroot\WRSA.exe",
        "$env:ProgramW6432\Webroot\WRSA.exe"
    ) | Where-Object { $_ -and (Test-Path $_) } | Select-Object -Unique

    foreach ($wrsa in $WrsaPaths) {
        try {
            Log "Attempting uninstall: $wrsa -uninstall (timeout 120s)"
            $proc = Start-Process -FilePath $wrsa -ArgumentList "-uninstall" -PassThru -WindowStyle Hidden
            if ($proc) {
                $done = $proc | Wait-Process -Timeout 120 -ErrorAction SilentlyContinue
                if (-not $done) {
                    Log "Uninstall timed out -> killing WRSA process"
                    Stop-Process -Id $proc.Id -Force -ErrorAction SilentlyContinue
                }
            }
        } catch {
            Log "Uninstall attempt failed: $wrsa ($($_.Exception.Message))"
        }
    }
}

function Cleanup-StartupEntries {
    $RunPaths = @(
        "HKLM:\SOFTWARE\Microsoft\Windows\CurrentVersion\Run",
        "HKLM:\SOFTWARE\WOW6432Node\Microsoft\Windows\CurrentVersion\Run"
    )

    foreach ($path in $RunPaths) {
        if (Test-Path $path) {
            $props = Get-ItemProperty -Path $path
            foreach ($prop in $props.PSObject.Properties) {
                $val = "$($prop.Value)"
                if ($val -match "Webroot|\\Webroot\\|WRSA|WRCore|WRSVC|WRSkyClient") {
                    try {
                        Log "Removing startup entry '$($prop.Name)' from $path"
                        Remove-ItemProperty -Path $path -Name $prop.Name -ErrorAction SilentlyContinue
                    } catch {
                        Log "Failed removing startup entry '$($prop.Name)' ($($_.Exception.Message))"
                    }
                }
            }
        }
    }
}

function Cleanup-WMI-SecurityCenter2 {
    try {
        $items = Get-CimInstance -Namespace "root/SecurityCenter2" -ClassName "AntiVirusProduct" -ErrorAction SilentlyContinue
        foreach ($i in $items) {
            $name = "$($i.displayName)"
            $exe  = "$($i.pathToSignedProductExe)"
            if (($name -match "Webroot") -or ($exe -match "Webroot")) {
                if ($name -match "Defender") { continue } # extra guard
                Log "Removing WMI AV entry: $name"
                Remove-CimInstance -InputObject $i -ErrorAction SilentlyContinue
            }
        }
    } catch {
        Log "WMI cleanup skipped/failed: $($_.Exception.Message)"
    }
}

Log "=== Start: Webroot removal (safe, no Safe Mode) ==="
Log "Log file: $LogPath"

# 1) Try uninstall (best-effort, but never hang)
Try-OfficialUninstall

# 2) Kill processes
Stop-KillProcesses

# 3) Remove services (soft, no driver file deletion)
foreach ($s in $ServiceNames) { Remove-ServiceSafe -Name $s }

# 4) Registry cleanup (Webroot-specific only)
$RegKeys = @(
    "HKLM:\SOFTWARE\WRData",
    "HKLM:\SOFTWARE\WRCore",
    "HKLM:\SOFTWARE\WRMIDData",
    "HKLM:\SOFTWARE\webroot",
    "HKLM:\SOFTWARE\WOW6432Node\WRData",
    "HKLM:\SOFTWARE\WOW6432Node\WRCore",
    "HKLM:\SOFTWARE\WOW6432Node\WRMIDData",
    "HKLM:\SOFTWARE\WOW6432Node\webroot",
    "HKLM:\SOFTWARE\Microsoft\Windows\CurrentVersion\WRUNINST",
    "HKLM:\SOFTWARE\WOW6432Node\Microsoft\Windows\CurrentVersion\WRUNINST",
    "HKLM:\SOFTWARE\Microsoft\Windows\CurrentVersion\Uninstall\WRUNINST",
    "HKLM:\SOFTWARE\WOW6432Node\Microsoft\Windows\CurrentVersion\Uninstall\WRUNINST"
)
foreach ($k in $RegKeys) { Remove-RegistryKeySafe $k }

# ControlSets: remove only Webroot service keys + Webroot eventlog source
$ControlSets = Get-ChildItem "HKLM:\SYSTEM" -ErrorAction SilentlyContinue | Where-Object { $_.Name -match "ControlSet" }
foreach ($cs in $ControlSets) {
    foreach ($svc in $ServiceNames) {
        Remove-RegistryKeySafe -Path "$($cs.PSPath)\Services\$svc"
    }
    Remove-RegistryKeySafe -Path "$($cs.PSPath)\Services\EventLog\Application\Webroot-WRLog"
}

# CurrentControlSet equivalents
Remove-RegistryKeySafe -Path "HKLM:\SYSTEM\CurrentControlSet\Services\EventLog\Application\Webroot-WRLog"

# 5) Startup entries (only those pointing to Webroot)
Cleanup-StartupEntries

# 6) Remove folders (safe targets only)
$Folders = @(
    "$env:ProgramData\WRData",
    "$env:ProgramData\WRCore",
    "$env:ProgramFiles\Webroot",
    "$env:ProgramFiles(x86)\Webroot",
    "$env:ProgramW6432\Webroot",
    "$env:ProgramFiles\Common Files\Webroot",
    "$env:ProgramData\Microsoft\Windows\Start Menu\Programs\Webroot SecureAnywhere",
    "$env:ProgramData\Microsoft\Windows\Start Menu\Programs\OpenText Core Endpoint Protection"
) | Where-Object { $_ -and $_.Trim() -ne "" } | Select-Object -Unique

foreach ($f in $Folders) { Remove-FolderSafe $f }

# 7) Remove orphaned AV registration (helps Defender come back)
Cleanup-WMI-SecurityCenter2

# 8) Verification
$Remaining = @()
foreach ($svc in $ServiceNames) {
    if (Get-Service -Name $svc -ErrorAction SilentlyContinue) { $Remaining += $svc }
}

if ($Remaining.Count -gt 0) {
    Log "NOTICE: Remaining services (often pending removal until reboot): $($Remaining -join ', ')"
    Log "Reboot recommended, then run script again."
} else {
    Log "OK: No Webroot services detected."
}

Log "=== Done: Webroot removal ==="
exit 0

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment