Remove-SnapAgent.psm1
|
function Remove-SnapAgent { <# .SYNOPSIS Completely removes Blackpoint SNAP Agent and ZTAC components from a Windows system. .DESCRIPTION This function removes all traces of Blackpoint SNAP Agent and ZTAC software including: - Running processes - Windows services - MSI installations - Program files and directories - Registry keys and entries The function performs a thorough cleanup by dynamically discovering installed versions and removing them via MSI uninstall, followed by manual cleanup of remaining artifacts. .EXAMPLE Remove-SnapAgent Performs a complete removal of SNAP Agent and ZTAC components. .NOTES Requires Administrator privileges to execute. Author: Dailen Gunter .LINK https://github.com/DailenG/Remove-SnapAgent #> [CmdletBinding(SupportsShouldProcess = $true, ConfirmImpact = 'High')] param() #Requires -RunAsAdministrator $snapProcesses = @("SnapAgent", "snap", "snapw", "ztac") $snapFolders = @( "$env:ProgramFiles\Blackpoint\SNAP Agent", "$env:ProgramFiles(x86)\Blackpoint\SNAP Agent" ) $ztacFolders = @( "$env:ProgramFiles\Blackpoint\ZTAC", "$env:ProgramFiles(x86)\Blackpoint\ZTAC" ) $allServices = @("Snap", "SnapAgent", "ZTAC", "ZtacFltr") $criticalErrors = @() $rebootRequired = $false # Stop any running processes Write-Host "Stopping any SNAP or ZTAC processes..." -ForegroundColor Green Get-Process $snapProcesses -ErrorAction SilentlyContinue | Stop-Process -Force Start-Sleep -Seconds 2 # Stop and remove all SNAP/ZTAC services Write-Host "Stopping and removing SNAP/ZTAC services..." -ForegroundColor Green foreach ($serviceName in $allServices) { $svc = Get-Service $serviceName -ErrorAction SilentlyContinue if ($svc) { try { if ($svc.Status -ne 'Stopped') { Write-Host "Attempting to stop service: $serviceName" -ForegroundColor Yellow Stop-Service $serviceName -Force -ErrorAction Stop Start-Sleep -Seconds 2 # Verify service actually stopped $svc = Get-Service $serviceName -ErrorAction SilentlyContinue if ($svc -and $svc.Status -ne 'Stopped') { $errorMsg = "CRITICAL: Service '$serviceName' failed to stop (Status: $($svc.Status)). Manual intervention or reboot required." $criticalErrors += $errorMsg Write-Error $errorMsg $rebootRequired = $true continue } Write-Host "Stopped service: $serviceName" -ForegroundColor Green } # Use sc.exe to delete the service $scResult = sc.exe delete $serviceName 2>&1 if ($LASTEXITCODE -eq 0) { Write-Host "Removed service: $serviceName" -ForegroundColor Green } else { $errorMsg = "Failed to delete service '$serviceName': $scResult" Write-Warning $errorMsg if ($scResult -match "marked for deletion|pending") { $rebootRequired = $true } } } catch { $errorMsg = "Failed to stop/remove service: $serviceName. Error: $_" $criticalErrors += $errorMsg Write-Warning $errorMsg $rebootRequired = $true } } } # Uninstall using MSI for all SnapAgent versions Write-Host "Uninstalling all SnapAgent versions via MSI..." -ForegroundColor Yellow $snapPackages = Get-Package -Name "SnapAgent" -ErrorAction SilentlyContinue if ($snapPackages) { $pkgCount = 0 $totalPkgs = @($snapPackages).Count foreach ($pkg in $snapPackages) { $pkgCount++ Write-Progress -Activity "Uninstalling SnapAgent packages" -Status "Processing $($pkg.Name) $($pkg.Version) ($pkgCount of $totalPkgs)" -PercentComplete (($pkgCount / $totalPkgs) * 100) Write-Host "Found SnapAgent version $($pkg.Version) - Uninstalling..." -ForegroundColor Yellow try { # Try using Uninstall-Package first Uninstall-Package -Name $pkg.Name -RequiredVersion $pkg.Version -Force -ErrorAction Stop Write-Host "Uninstalled SnapAgent $($pkg.Version)" -ForegroundColor Green } catch { Write-Host "Uninstall-Package failed for version $($pkg.Version) (expected, will try msiexec)" -ForegroundColor DarkGray } } Write-Progress -Activity "Uninstalling SnapAgent packages" -Completed } # Dynamically find and uninstall using msiexec with all SnapAgent GUIDs Write-Host "Searching for SnapAgent installations in registry..." -ForegroundColor Yellow $uninstallPaths = @( "HKLM:\SOFTWARE\Microsoft\Windows\CurrentVersion\Uninstall\*", "HKLM:\SOFTWARE\WOW6432Node\Microsoft\Windows\CurrentVersion\Uninstall\*" ) $snapProducts = @() foreach ($path in $uninstallPaths) { $products = Get-ItemProperty $path -ErrorAction SilentlyContinue | Where-Object { $_.DisplayName -like "*Snap*" -or $_.Publisher -like "*Blackpoint*" } $snapProducts += $products } if ($snapProducts) { foreach ($product in $snapProducts) { $guid = $product.PSChildName $name = $product.DisplayName $version = $product.DisplayVersion Write-Host "Found: $name $version (GUID: $guid)" -ForegroundColor Yellow Write-Host "Uninstalling via msiexec..." -ForegroundColor Yellow try { # Use msiexec for silent uninstall $uninstallArgs = "/x $guid /qn /norestart" $process = Start-Process "msiexec.exe" -ArgumentList $uninstallArgs -Wait -PassThru -NoNewWindow if ($process.ExitCode -eq 0) { Write-Host "Successfully uninstalled: $name $version" -ForegroundColor Green } else { Write-Warning "msiexec returned exit code $($process.ExitCode) for $name $version" } } catch { Write-Warning "Failed to uninstall $name $version via msiexec: $_" } } } # Uninstall ZTAC packages Write-Host "Removing any existing versions of ZTAC..." -ForegroundColor Green try { Uninstall-Package -Name "ZTAC" -AllVersions -Force -ErrorAction Stop Write-Host "Uninstalled ZTAC packages" -ForegroundColor Green } catch { Write-Host "No ZTAC packages found or uninstall failed (not critical)" -ForegroundColor DarkGray } # Remove folders Write-Host "Removing program directories..." -ForegroundColor Green foreach ($folder in $snapFolders + $ztacFolders) { if (Test-Path $folder) { try { Remove-Item -Path $folder -Recurse -Force Write-Host "Removed folder: $folder" -ForegroundColor Green } catch { Write-Warning "Failed to remove folder: $folder. Error: $_" } } } # Clean up registry keys Write-Host "Cleaning up registry keys..." -ForegroundColor Green # Build list of all discovered product GUIDs plus hardcoded known keys $registryKeys = @( "HKLM:\SOFTWARE\Classes\Installer\Features\0E1D3F0C2B974FA4AA0418F12B055384", "HKLM:\SOFTWARE\Classes\Installer\Products\0E1D3F0C2B974FA4AA0418F12B055384", "HKLM:\SOFTWARE\Classes\Installer\Products\0E1D3F0C2B974FA4AA0418F12B055384\SourceList", "HKLM:\SOFTWARE\Classes\Installer\Products\0E1D3F0C2B974FA4AA0418F12B055384\SourceList\Media", "HKLM:\SOFTWARE\Classes\Installer\Products\0E1D3F0C2B974FA4AA0418F12B055384\SourceList\Net", "HKLM:\SOFTWARE\Classes\Installer\UpgradeCodes\7CF0653F8B24F2647B3A70510A96BEE6", "HKLM:\SOFTWARE\Microsoft\Windows\CurrentVersion\Installer\UpgradeCodes\7CF0653F8B24F2647B3A70510A96BEE6", "HKLM:\SOFTWARE\Microsoft\Windows\CurrentVersion\Installer\UserData\S-1-5-18\Components\08C8C87010175A141912F6695F06EB95", "HKLM:\SOFTWARE\Microsoft\Windows\CurrentVersion\Installer\UserData\S-1-5-18\Components\5E3D36BBC4ADCA749AC6CC3774478B04", "HKLM:\SOFTWARE\Microsoft\Windows\CurrentVersion\Installer\UserData\S-1-5-18\Components\74A044CACC826754BB48542EA5681E4C", "HKLM:\SOFTWARE\Microsoft\Windows\CurrentVersion\Installer\UserData\S-1-5-18\Components\A3129D8FE202CCF47B233E82C70367D2", "HKLM:\SOFTWARE\Microsoft\Windows\CurrentVersion\Installer\UserData\S-1-5-18\Components\A73F059633BC8314597EE7F81A662796", "HKLM:\SOFTWARE\Microsoft\Windows\CurrentVersion\Installer\UserData\S-1-5-18\Components\C0016A60CBED93E41900FCBD4BC10AB4", "HKLM:\SOFTWARE\Microsoft\Windows\CurrentVersion\Installer\UserData\S-1-5-18\Components\DB4ABEA1DA4832048BCCF78860ADA944", "HKLM:\SOFTWARE\Microsoft\Windows\CurrentVersion\Installer\UserData\S-1-5-18\Components\F1AB931B4E8A02A4F8E5F828409E4DD1", "HKLM:\SOFTWARE\Microsoft\Windows\CurrentVersion\Installer\UserData\S-1-5-18\Components\F81ECEA5C9A7CA3409D05D38A602B11C", "HKLM:\SOFTWARE\Microsoft\Windows\CurrentVersion\Installer\UserData\S-1-5-18\Products\0E1D3F0C2B974FA4AA0418F12B055384", "HKLM:\SOFTWARE\Microsoft\Windows\CurrentVersion\Installer\UserData\S-1-5-18\Products\0E1D3F0C2B974FA4AA0418F12B055384\Features", "HKLM:\SOFTWARE\Microsoft\Windows\CurrentVersion\Installer\UserData\S-1-5-18\Products\0E1D3F0C2B974FA4AA0418F12B055384\InstallProperties", "HKLM:\SOFTWARE\Microsoft\Windows\CurrentVersion\Installer\UserData\S-1-5-18\Products\0E1D3F0C2B974FA4AA0418F12B055384\Patches", "HKLM:\SOFTWARE\Microsoft\Windows\CurrentVersion\Installer\UserData\S-1-5-18\Products\0E1D3F0C2B974FA4AA0418F12B055384\Usage", "HKLM:\SOFTWARE\Microsoft\Windows\CurrentVersion\Uninstall\{C0F3D1E0-79B2-4AF4-AA40-811FB2503548}", "HKLM:\SYSTEM\CurrentControlSet\Services\ZTAC", "HKLM:\SYSTEM\CurrentControlSet\Services\ZtacFltr" ) # Add registry keys for any discovered product GUIDs if ($snapProducts) { foreach ($product in $snapProducts) { $guid = $product.PSChildName $registryKeys += "HKLM:\SOFTWARE\Microsoft\Windows\CurrentVersion\Uninstall\$guid" $registryKeys += "HKLM:\SOFTWARE\WOW6432Node\Microsoft\Windows\CurrentVersion\Uninstall\$guid" } } $i = 0 foreach ($key in $registryKeys) { Write-Progress -Activity "Cleaning up registry keys" -Status "Processing key $($i + 1) of $($registryKeys.Count)" -PercentComplete (($i / $registryKeys.Count) * 100) if (Test-Path $key) { try { # Use a job with timeout to prevent hanging $job = Start-Job -ScriptBlock { param($regKey) Remove-Item -Path $regKey -Recurse -Force -ErrorAction Stop } -ArgumentList $key # Wait up to 10 seconds for registry deletion $completed = Wait-Job $job -Timeout 10 if ($completed) { Receive-Job $job -ErrorAction SilentlyContinue Remove-Job $job Write-Host "Removed registry key: $key" -ForegroundColor Green } else { Stop-Job $job Remove-Job $job $errorMsg = "TIMEOUT: Registry key deletion hung after 10 seconds: $key - This may indicate the service is still running or a reboot is needed." $criticalErrors += $errorMsg Write-Error $errorMsg $rebootRequired = $true } } catch { $errorMsg = "Failed to remove registry key: $key. Error: $_" Write-Warning $errorMsg if ($_.Exception.Message -match "in use|cannot access") { $rebootRequired = $true } } } $i++ } Write-Progress -Activity "Cleaning up registry keys" -Completed -Status "All registry keys processed." # Final verification Write-Host "`nVerifying cleanup..." -ForegroundColor Cyan $remainingPackages = Get-Package -Name "*Snap*" -ErrorAction SilentlyContinue if ($remainingPackages) { Write-Warning "The following packages are still installed:" $remainingPackages | Format-Table Name, Version, ProviderName } else { Write-Host "No SnapAgent packages found - cleanup successful!" -ForegroundColor Green } # Check for remaining folders $remainingFolders = $snapFolders + $ztacFolders | Where-Object { Test-Path $_ } if ($remainingFolders) { Write-Warning "The following folders still exist:" $remainingFolders | ForEach-Object { Write-Host " $_" -ForegroundColor Yellow } $rebootRequired = $true } else { Write-Host "All program folders removed successfully!" -ForegroundColor Green } # Check for remaining services $remainingServices = Get-Service $allServices -ErrorAction SilentlyContinue | Where-Object { $_.Status -ne 'Stopped' } if ($remainingServices) { Write-Error "CRITICAL: The following services are still running:" $remainingServices | ForEach-Object { Write-Host " $($_.Name) - Status: $($_.Status)" -ForegroundColor Red $criticalErrors += "Service still running: $($_.Name)" } $rebootRequired = $true } Write-Host "`n========================================" -ForegroundColor Cyan if ($criticalErrors.Count -gt 0) { Write-Host "CLEANUP COMPLETED WITH ERRORS" -ForegroundColor Red Write-Host "========================================" -ForegroundColor Cyan Write-Host "`nCritical errors encountered:" -ForegroundColor Red $criticalErrors | ForEach-Object { Write-Host " - $_" -ForegroundColor Yellow } if ($rebootRequired) { Write-Host "`n⚠️ A SYSTEM REBOOT IS REQUIRED to complete the removal." -ForegroundColor Yellow -BackgroundColor DarkRed Write-Host "Some services or files are locked and can only be removed after restart." -ForegroundColor Yellow } throw "Remove-SnapAgent encountered critical errors. See above for details." } else { Write-Host "CLEANUP COMPLETED SUCCESSFULLY" -ForegroundColor Green Write-Host "========================================" -ForegroundColor Cyan if ($rebootRequired) { Write-Host "`n⚠️ A system reboot is recommended to complete the removal." -ForegroundColor Yellow } } } # Export the function Export-ModuleMember -Function Remove-SnapAgent |