Last active
May 20, 2026 14:47
-
-
Save asheroto/4b1313fc41b3801a1362d421ff577406 to your computer and use it in GitHub Desktop.
Forcefully removes Webroot Endpoint Protection.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| #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 |
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!
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.
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
No devices right now with webroot (hopefully no more webroot). Will test if I can. Thanks for that.