Files
PS_AppDeploy-Scripts/Ivanti Secure Access Client/22.8.33059/Files/ISACDeepCleanScriptSilentSigned.ps1

927 lines
43 KiB
PowerShell

# ***********************************************************
# Copyright (c) 2024 by Ivanti, Inc. All rights reserved
# ***********************************************************
# Description: This script is used to deep clean the Ivanti
# Secure Access Client (ISAC) from the system. This script
# will remove all the ISAC related files, directories,
# registries, and services from the system.
# ***********************************************************
# Version: 1.0
# ***********************************************************
<#
.SYNOPSIS
This script performs a deep clean process for the Ivanti Secure Access Client (ISAC).
.DESCRIPTION
The ISACDeepCleanScriptSilent.ps1 script is designed to remove all traces of the Ivanti Secure Access Client from a system. It performs various cleanup tasks including uninstalling applications, deleting directories, removing registry entries, and terminating processes associated with ISAC.
.PARAMETER None
This script does not accept any parameters.
.NOTES
- This script should be run with administrative privileges.
- The script is intended for use on Windows systems.
- The script assumes the presence of certain file paths and registry keys associated with ISAC. If these paths or keys have been modified, the script may not function correctly.
- The script may take some time to complete, depending on the number of user profiles and the amount of data to be cleaned up.
- The script generates log files in the same directory where the script is located. The log files contain information about the cleanup process and any errors encountered during execution.
The script performs the following tasks:
1. Checks if the script is running with administrative privileges.
2. Creates a log directory to store the script execution logs.
3. Suspends and stops the ISAC client.
4. Terminates ISAC processes running in user mode.
5. Removes ISAC user-mode registry entries for all user SIDs.
6. Uninstalls ISAC user mode applications like PSAL, Pulse Setup Client, Host checker, terminal services clients, etc. for all user SIDs.
7. Uninstalls ISAC.
8. Uninstalls Pulse Secure client.
9. Cleans up the ISAC/Pulse Secure specific registries.
10. Cleans up the ISAC/Pulse Secure installer classes registry entries.
11. Cleans up the ISAC/Pulse Secure uninstall registries.
12. Cleans up the ISAC/Pulse Secure product registries.
13. Cleans up the Pulse Secure component registries.
14. Cleans up the Pulse Secure folders registry entries.
15. Cleans up the ISAC/Pulse Secure residual files.
.EXAMPLE
.\ISACDeepCleanScriptSilent.ps1
Runs the script to perform the deep clean process for ISAC.
#>
# ************** Declarations *******************************
$MsiexecExe = "$Env:WINDIR\System32\msiexec.exe"
$PowerShellExe = "$Env:WINDIR\System32\WindowsPowerShell\v1.0\powershell.exe"
$CurrDir = Split-Path $Script:MyInvocation.MyCommand.Path
$ScriptName = &{ $MyInvocation.ScriptName }
$LogDir = "$CurrDir\DeepCleanlogs"
$LogFile = "$LogDir\DeepCleanProgress.log"
$CmdLogFile = "$LogDir\CommandOutput.log"
$ProgFileDir = ''
$CommonProgFileDir = ''
$PulseProdName = "Pulse Secure"
$ISACProdName = "Ivanti Secure Access Client"
$JuniperProdName = "Juniper Networks"
$PsalName = "Pulse Application Launcher"
$PulseServiceName = "PulseSecureService"
$OSArch64Bit = "64-Bit"
#**************** Functions *******************************
# Function to check if the OS is 64-bit
Function Test-OS64Bit
{
$ProcessorType = (Get-WmiObject Win32_OperatingSystem).OSArchitecture
If($OSArch64Bit -ieq $ProcessorType){ $True } Else { $False }
}
# Function to check if a file exists
Function Test-FileExists
{
Param ( [string]$FilePath )
Test-Path -Path $FilePath
}
# Function to check if a directory exists
Function Test-DirectoryExists {
Param ( [String]$DirPath )
Test-Path -PathType container $DirPath
}
# Function to write log messages to the console and log file
Function Write-LogMessage
{
Param ( [String]$Message )
$timeStamp = (Get-Date).toString("yyyy/MM/dd HH:mm:ss")
Write-Output $Message
Add-Content $LogFile -value "[$timeStamp] | $Message"
}
# Function to remove a directory
Function Remove-Directory
{
Param ( [String]$DirFullPath, [Bool]$FlushOnly )
If(Test-DirectoryExists -DirPath $DirFullPath) {
If( $True -eq $FlushOnly ) {
Write-LogMessage -Message "Flushing Directory: $DirFullPath"
Remove-Item -Path "$DirFullPath\*" -Recurse -Force -Verbose *>> "$CmdLogFile"
} Else {
Write-LogMessage -Message "Removing Directory: $DirFullPath"
Remove-Item -Path $DirFullPath -Recurse -Force -Verbose *>> "$CmdLogFile"
}
} Else {
Write-LogMessage -Message "'$DirFullPath' does not exist"
}
}
# Function to remove files with wildcard
Function Remove-FileWithWildcard
{
Param ( [String]$DirFullPath, [String]$WildCharFileName )
Write-LogMessage -Message "Removing: $DirFullPath\$WildCharFileName"
Remove-Item -Path $DirFullPath -Include $WildCharFileName -Recurse -Force -Verbose *>> "$CmdLogFile"
}
# Function to remove registry entries
Function Remove-Registry
{
Param ( [String]$RegistryPath )
If(Test-FileExists -FilePath $RegistryPath) {
Remove-Item -Path "$RegistryPath\*" -Recurse -Force -Verbose *>> "$CmdLogFile"
Remove-Item -Path $RegistryPath -Recurse -Force -Verbose *>> "$CmdLogFile"
} Else {
Write-LogMessage -Message "'$RegistryPath' does not exist"
}
}
# Function to check if the script is running in Admin mode
Function Test-ScriptElevation
{
$currentUser = New-Object Security.Principal.WindowsPrincipal $([Security.Principal.WindowsIdentity]::GetCurrent())
$currentUser.IsInRole([Security.Principal.WindowsBuiltinRole]::Administrator)
}
# Function to stop a process by name
Function Stop-ProcessByName
{
Param ( [String]$ProcessName )
Write-LogMessage -Message "Terminating '$ProcessName'"
Stop-Process -Name $ProcessName -Force *>> "$CmdLogFile"
}
# Function to stop a service
Function Stop-ServiceAction
{
Param ( [String]$ServiceName )
Write-LogMessage -Message "Stopping Service: '$ServiceName'"
Stop-Service -Name $ServiceName -Force *>> "$CmdLogFile"
}
# *********** Deep Clean Script ****************************
$IsOS64Bit = Test-OS64Bit
If($IsOS64Bit){
$ProgFileDir = "${Env:PROGRAMFILES(X86)}"
$CommonProgFileDir = "${Env:COMMONPROGRAMFILES(X86)}"
} Else {
$ProgFileDir = "$Env:PROGRAMFILES"
$CommonProgFileDir = "$Env:COMMONPROGRAMFILES"
}
If(!(Test-DirectoryExists -DirPath $LogDir)) {
Write-Output "Log Dir does not Exists, creating one..."
New-Item -ItemType Directory -Path $LogDir
}
$JamUIPath = "$CommonProgFileDir\$PulseProdName\JamUI"
$PulseExe = "$JamUIPath\Pulse.exe"
# Check if the script is running in Admin mode
If (-not (Test-ScriptElevation)) {
Write-LogMessage -Message "The script is not running in Admin mode, so re-invoking it in Admin mode..."
Start-Process -FilePath $PowerShellExe -ArgumentList " -File `"$ScriptName`"" -Verb RunAs
Exit
}
# Flush the log directory
Remove-Directory -DirFullPath $LogDir -FlushOnly $True
# Start the Deep Clean Process
Write-LogMessage -Message "************************************************************************************"
Write-LogMessage -Message "Welcome to '$ISACProdName/$PulseProdName' Deep Clean Process"
Write-LogMessage -Message "Copyright (c) 2024 by Ivanti, Inc. All rights reserved"
Write-LogMessage -Message "************************************************************************************"
# Check if the script is running as the system user
$currentUser = [System.Security.Principal.WindowsIdentity]::GetCurrent()
$isSystemUser = $currentUser.Name -ieq 'NT AUTHORITY\SYSTEM'
If ($isSystemUser) {
Write-LogMessage -Message "Script is running as the system user"
} Else {
Write-LogMessage -Message "Script is not running as the system user"
}
If(Test-FileExists -FilePath $PulseExe) {
# Suspend ISAC
Write-LogMessage -Message "Suspending $ISACProdName ..."
Start-Process -FilePath $PulseExe -ArgumentList "-suspend" -Wait
Start-Sleep -Seconds 2
# Stop ISAC
Write-LogMessage -Message "Stopping $ISACProdName ..."
Start-Process -FilePath $PulseExe -ArgumentList "-stop" -Wait
Start-Sleep -Seconds 2
} Else {
Write-LogMessage -Message "Pulse.exe does not exist, skipping suspension and stop..."
}
# Terminate Pulse Secure Processes
Write-LogMessage -Message "Terminating User Mode Processes ..."
Stop-ProcessByName -ProcessName "Pulse"
Stop-ProcessByName -ProcessName "PulseServiceAPI"
Stop-ProcessByName -ProcessName "PulseSecure"
Stop-ProcessByName -ProcessName "PulseSetupClient"
Stop-ProcessByName -ProcessName "PulseApplicationLauncher"
# Get the list of installed applications and their product codes
Write-LogMessage -Message "Getting list of installed applications ..."
$InstalledApps = Get-WmiObject Win32_Product | Select-Object Name, IdentifyingNumber
$ISACProductCodes = @()
$PulseSecureProductCodes = @()
foreach ($App in $InstalledApps) {
$Found = $false
if ($App.Name -ieq $ISACProdName) {
$ISACProductCodes += $App.IdentifyingNumber
$Found = $true
}
if ($App.Name -ieq $PulseProdName) {
$PulseSecureProductCodes += $App.IdentifyingNumber
$Found = $true
}
if ($Found) {
Write-LogMessage -Message "Name: $($App.Name), Product Code: $($App.IdentifyingNumber)"
}
}
Write-LogMessage -Message "Uninstalling User Mode Applications ..."
# List all user SIDs when no user is logged in
Write-LogMessage -Message "Listing all user SIDs..."
# Get the list of user SIDs from the registry
$users = Get-ChildItem -Path "HKLM:\SOFTWARE\Microsoft\Windows NT\CurrentVersion\ProfileList" | Where-Object { $_.PSChildName -match 'S-\d-\d+-(\d+-){1,14}\d+$' }
# Iterate through each user SID and display it
foreach ($user in $users) {
$userSID = $user.PSChildName
Write-LogMessage -Message "User SID from Profile List: $userSID"
}
# Mount the HKU drive if it is not already mounted
$bMounted = $false
if (-not (Get-PSDrive -Name HKU -ErrorAction SilentlyContinue)) {
Write-LogMessage -Message "Mounting HKU drive..."
New-PSDrive -Name HKU -PSProvider Registry -Root HKEY_USERS *>> "$CmdLogFile"
$bMounted = $true
}
# Remove the Pulse Secure registry entries for all user SIDs
foreach ($user in $users) {
$userSID = $user.PSChildName
$fullRegPath = "HKU:\$userSID"
Write-LogMessage -Message "User SID: $userSID"
# Get the user profile path
$userProfilePath = (Get-WmiObject Win32_UserProfile | Where-Object { $_.SID -ieq $userSID }).LocalPath
# Load the user's registry hive
$regHive = "HKEY_USERS\$userSID"
$regFile = "$userProfilePath\NTUSER.DAT"
Write-LogMessage -Message "Loading user's registry hive: $regHive from file: $regFile"
reg load $regHive $regFile
# >>>>>> Remove the PSAL registry entries >>>>>>>>
$ProductsPath = "HKLM:\SOFTWARE\Microsoft\Windows\CurrentVersion\Installer\UserData\$userSID\Products"
$ProductKeys = Get-ChildItem -Path $ProductsPath
foreach ($key in $ProductKeys) {
$InstallRegPath = $key.PSPath + "\InstallProperties"
$DisplayName = (Get-ItemProperty -Path $InstallRegPath).DisplayName
$UninstallString = (Get-ItemProperty -Path $InstallRegPath).UninstallString
$PsalName = "Pulse Application Launcher"
if ($DisplayName -ieq $PsalName) {
$ProductCode = $UninstallString | Select-String -Pattern "{[A-F0-9]{8}-([A-F0-9]{4}-){3}[A-F0-9]{12}}" -AllMatches | ForEach-Object { $_.Matches.Value }
Write-LogMessage -Message "Product Code of PSAL for user: $userSID is: $ProductCode"
Write-LogMessage -Message "Found PSAL from registry: $($key.PSPath), removing it now..."
Remove-Registry -RegistryPath $key.PSPath
}
}
$RegPath = "$fullRegPath\Software\Microsoft\Installer\Products"
$ProductKeys = Get-ChildItem -Path $RegPath
foreach ($key in $ProductKeys) {
$ProductName = (Get-ItemProperty -Path $key.PSPath).ProductName
$PsalName = "Pulse Application Launcher"
if ($ProductName -ieq $PsalName) {
Write-LogMessage -Message "Found $PsalName from registry: $($key.PSPath), removing it now..."
Remove-Registry -RegistryPath $key.PSPath
}
}
# <<<<<< Remove the PSAL registry entries <<<<<<<<
# >>>>>> Remove the Pulse Secure Setup Client, HC and Terminal Services Client entries >>>>>>>>
$RegPath = "$fullRegPath\Software\Microsoft\Windows\CurrentVersion\Uninstall\Pulse_Setup_Client"
Write-LogMessage -Message "Removing PSC Registry: $RegPath"
Remove-Registry -RegistryPath $RegPath
$RegPath = "$fullRegPath\Software\Microsoft\Windows\CurrentVersion\Uninstall\PulseSecure_Host_Checker"
Write-LogMessage -Message "Removing HC Registry: $RegPath"
Remove-Registry -RegistryPath $RegPath
$RegPath = "$fullRegPath\Software\Microsoft\Windows\CurrentVersion\Uninstall\Pulse_Term_Services"
Write-LogMessage -Message "Removing Terminal Services Client Registry: $RegPath"
Remove-Registry -RegistryPath $RegPath
$RegPath = "$fullRegPath\Software\Microsoft\Windows\CurrentVersion\Uninstall\Pulse_Citrix_Services"
Write-LogMessage -Message "Removing Citrix Client Registry: $RegPath"
Remove-Registry -RegistryPath $RegPath
# <<<<<< Remove the Pulse Secure Setup Client, HC and Terminal Services Client entries <<<<<<<<
# >>>>>> Remove the Pulse Secure registry entries >>>>>>>>
$RegPath = "$fullRegPath\SOFTWARE\$PulseProdName"
Write-LogMessage -Message "Removing Registry: $RegPath"
Remove-Registry -RegistryPath $RegPath
If($IsOS64Bit) {
$RegPath = "$fullRegPath\SOFTWARE\Wow6432Node\$PulseProdName"
Write-LogMessage -Message "Removing Registry: $RegPath"
Remove-Registry -RegistryPath $RegPath
}
# <<<<<< Remove the Pulse Secure registry entries <<<<<<<<
# >>>>>> Remove the Pulse Secure React App for the user >>>>>>>>
# Remove the AppxPackage for the user
$appxPackages = Get-AppxPackage -User $userSID | Where-Object { $_.Name -like "PulseSecureReactAppPkg*" }
foreach ($appxPackage in $appxPackages) {
Write-LogMessage -Message "Uninstalling package: $($appxPackage.PackageFullName) for user SID: $userSID"
Remove-AppPackage -Package $($appxPackage.PackageFullName) -User $userSID *>> "$CmdLogFile"
}
# <<<<<< Remove the Pulse Secure React App for the user <<<<<<<<
# Unload the user's registry hive
Write-LogMessage -Message "Unloading user's registry hive: $regHive"
reg unload $regHive
}
# Remove the PSC registry entries for the default user
$RegPath = "HKU:\.DEFAULT\Software\Microsoft\Windows\CurrentVersion\Uninstall\Pulse_Setup_Client"
Write-LogMessage -Message "Removing PSC Registry: $RegPath"
Remove-Registry -RegistryPath $RegPath
# Remove the PSC registry entries for the system user
$RegPath = "HKU:\S-1-5-18\Software\Microsoft\Windows\CurrentVersion\Uninstall\Pulse_Setup_Client"
Write-LogMessage -Message "Removing PSC Registry: $RegPath"
Remove-Registry -RegistryPath $RegPath
# Unmount the HKU drive if it was mounted
if ($bMounted) {
Write-LogMessage -Message "Unmounting HKU drive..."
Remove-PSDrive -Name HKU *>> "$CmdLogFile"
}
Write-LogMessage -Message "Listing directories in $Env:SystemDrive\Users"
$UserDirectories = Get-ChildItem -Path "$Env:SystemDrive\Users" -Directory
foreach ($dir in $UserDirectories) {
Write-LogMessage -Message "User Name: $($dir.Name)"
$UserAppDataDir = "$($dir.FullName)\AppData\Roaming"
Write-LogMessage -Message "User AppData Directory: $UserAppDataDir"
# Uninstall the Setup Client
Write-LogMessage -Message "Un-installing Setup Client for user: $($dir.Name)..."
$SetupClientUninstaller="$UserAppDataDir\$PulseProdName\Setup Client\uninstall.exe"
If(Test-FileExists -FilePath $SetupClientUninstaller) {
Start-Process -FilePath $SetupClientUninstaller -ArgumentList "/S" -Wait
Write-LogMessage -Message "SetupClient uninstalled successfully..."
} Else {
Write-LogMessage -Message "'$SetupClientUninstaller' does not exist"
}
# Uninstall the Host Checker
Write-LogMessage -Message "Un-installing Host Checker for user: $($dir.Name)..."
$HostCheckerUninstaller="$UserAppDataDir\$PulseProdName\Host Checker\uninstall.exe"
If(Test-FileExists -FilePath $HostCheckerUninstaller) {
Write-LogMessage -Message "Terminating Host Checker Processes"
Stop-ProcessByName -ProcessName "dsHostChecker"
Stop-ProcessByName -ProcessName "uacHostChecker"
Start-Process -FilePath $HostCheckerUninstaller -ArgumentList "/S" -Wait
Write-LogMessage -Message "Host Checker uninstalled successfully..."
} Else {
Write-LogMessage -Message "'$HostCheckerUninstaller' does not exist"
}
# Uninstall the Term Services Client
Write-LogMessage -Message "Un-installing Term Services Client for user: $($dir.Name)..."
$UninstallerFile="$UserAppDataDir\$PulseProdName\Pulse Terminal Services Client\uninstall.exe"
If(Test-FileExists -FilePath $UninstallerFile) {
Write-LogMessage -Message "Terminating Term Services Client Process"
Stop-ProcessByName -ProcessName "dsTermServ"
Start-Process -FilePath $UninstallerFile -ArgumentList "/S" -Wait
Write-LogMessage -Message "The Terminal Services Client uninstalled successfully..."
} Else {
Write-LogMessage -Message "'$UninstallerFile' does not exist"
}
# Uninstall the Citrix Services Client
Write-LogMessage -Message "Un-installing Citrix Client for user: $($dir.Name)..."
$UninstallerFile="$UserAppDataDir\$PulseProdName\Pulse Secure Citrix Services Client\uninstall.exe"
If(Test-FileExists -FilePath $UninstallerFile) {
Write-LogMessage -Message "Terminating Citrix Client Process"
Stop-ProcessByName -ProcessName "dsCitrixProxy"
Start-Process -FilePath $UninstallerFile -ArgumentList "/S" -Wait
Write-LogMessage -Message "The Citrix Client uninstalled successfully..."
} Else {
Write-LogMessage -Message "'$UninstallerFile' does not exist"
}
# Clean User Mode Residuals
Write-LogMessage -Message "Cleaning User Mode Residuals for user: $($dir.Name)..."
$DirName = "$UserAppDataDir\$PulseProdName"
Remove-Directory -DirFullPath $DirName -FlushOnly $False
$DirName = "$UserAppDataDir\PulseSecure"
Remove-Directory -DirFullPath $DirName -FlushOnly $False
$DirName = "$UserAppDataDir\..\LocalLow\$PulseProdName"
Remove-Directory -DirFullPath $DirName -FlushOnly $False
$DirName = "$UserAppDataDir\..\..\Library\Application Support\$PulseProdName"
Remove-Directory -DirFullPath $DirName -FlushOnly $False
$UserLocalAppDataDir = "$($dir.FullName)\AppData\Local"
Write-LogMessage -Message "User Local AppData Directory: $UserLocalAppDataDir"
$DirName = "$UserLocalAppDataDir\$PulseProdName"
Remove-Directory -DirFullPath $DirName -FlushOnly $False
$DirName = "$UserLocalAppDataDir\CrashDumps"
Remove-FileWithWildcard -DirFullPath $DirName -WildCharFileName "Pulse*"
$DirName = "$UserLocalAppDataDir\CrashDumps"
Remove-FileWithWildcard -DirFullPath $DirName -WildCharFileName "cef*"
$DirName = "$UserLocalAppDataDir\Temp"
Remove-Directory -DirFullPath $DirName -FlushOnly $True
}
$DirName = "$Env:TEMP"
Remove-Directory -DirFullPath $DirName -FlushOnly $True
# Uninstall the Admin Mode ISAC Applications
Write-LogMessage -Message "Terminating Admin Mode ISAC Processes"
# Stop the Pulse Secure Service
Stop-ServiceAction -ServiceName $PulseServiceName
Stop-ProcessByName -ProcessName $PulseServiceName
Stop-ServiceAction -ServiceName $PulseServiceName
# Uninstall the Admin Mode ISAC Applications
Write-LogMessage -Message "Uninstalling Admin Mode ISAC Applications..."
If($IsOS64Bit){
# Uninstall the ActiveX Control (x64)
Write-LogMessage -Message "Un-installing ActiveX Control (x64)..."
$ActivexX64Uninstaller="$Env:SYSTEMDRIVE\Windows\Downloaded Program Files\PulseSetupClientCtrlUninstaller64.exe"
If(Test-FileExists -FilePath $ActivexX64Uninstaller) {
Start-Process -FilePath $ActivexX64Uninstaller -ArgumentList "/S" -Wait -Verb RunAs
Write-LogMessage -Message "ActiveX X64 uninstalled successfully..."
} Else {
Write-LogMessage -Message "'$ActivexX64Uninstaller' does not exist"
}
}
# Uninstall the ActiveX Control
Write-LogMessage -Message "Un-installing ActiveX Control..."
$ActivexUninstaller="$Env:SYSTEMDRIVE\Windows\Downloaded Program Files\PulseSetupClientCtrlUninstaller.exe"
If(Test-FileExists -FilePath $ActivexUninstaller) {
Start-Process -FilePath $ActivexUninstaller -ArgumentList "/S" -Wait -Verb RunAs
Write-LogMessage -Message "ActiveX uninstalled successfully..."
} Else {
Write-LogMessage -Message "'$ActivexUninstaller' does not exist"
}
# Uninstall the ISAC
Write-LogMessage -Message "Uninstalling ISAC Client instances if available..."
$count=0
if($ISACProductCodes) {
foreach ($code in $ISACProductCodes) {
$count++
Write-LogMessage -Message "Product code: $code. Uninstalling the Client using the Product Code now..."
Start-Process -FilePath $MsiexecExe -ArgumentList " /x $code /qn /L*vx `"$LogDir\ISAC_$($count)_uninstall.log`"" -Verb RunAs -Wait
}
} else {
Write-LogMessage -Message "No product codes found for '$ISACProdName'"
}
# Uninstall the Pulse Secure Client
Write-LogMessage -Message "Uninstalling '$PulseProdName' Client instances if available..."
$count=0
if($PulseSecureProductCodes) {
foreach ($code in $PulseSecureProductCodes) {
$count++
Write-LogMessage -Message "Product code: $code. Uninstalling the Client using the Product Code now..."
Start-Process -FilePath $MsiexecExe -ArgumentList " /x $code /qn /L*vx `"$LogDir\OldPulseSecure_$($count)_uninstall.log`"" -Verb RunAs -Wait
}
} else {
Write-LogMessage -Message "No product codes found for '$PulseProdName'"
}
# Uninstall the ISAC Client using custom uninstaller if available
Write-LogMessage -Message "Uninstalling '$ISACProdName' using custom uninstaller if available..."
$ISACUninstaller = "$ProgFileDir\$PulseProdName\Pulse\PulseUninstall.exe"
If(Test-FileExists -FilePath $ISACUninstaller) {
Write-LogMessage -Message "ISAC uninstaller file exists, so invoking it now"
Start-Process -FilePath $ISACUninstaller -ArgumentList "/silent=1" -Verb RunAs -Wait
} Else {
Write-LogMessage -Message "ISAC uninstaller file does not Exists..."
}
Write-LogMessage -Message "Cleaning Admin Mode Registries..."
$RegPath = "HKLM:\SOFTWARE\$PulseProdName"
Write-LogMessage -Message "Removing Registry: $RegPath"
Remove-Registry -RegistryPath $RegPath
If($IsOS64Bit) {
$RegPath = "HKLM:\SOFTWARE\Wow6432Node\$PulseProdName"
Write-LogMessage -Message "Removing Registry: $RegPath"
Remove-Registry -RegistryPath $RegPath
$RegPath = "HKLM:\SOFTWARE\Wow6432Node\PulseSecure"
Write-LogMessage -Message "Removing Registry: $RegPath"
Remove-Registry -RegistryPath $RegPath
}
# Remove the ISAC / Pulse Secure installer classes registry entries
$count = 0
Write-LogMessage -Message "Cleaning ISAC / Pulse Secure installer classes registries..."
$RegPath = "HKLM:\SOFTWARE\Classes\Installer\Products"
$ProductKeys = Get-ChildItem -Path $RegPath
foreach ($key in $ProductKeys) {
$ProductName = (Get-ItemProperty -Path $key.PSPath).ProductName
if ($ProductName -ieq $ISACProdName) {
Write-LogMessage -Message "Found '$ISACProdName' from registry: $($key.PSPath), removing it now..."
$count++
Remove-Registry -RegistryPath $key.PSPath
}
if ($ProductName -ieq $PulseProdName) {
Write-LogMessage -Message "Found '$PulseProdName' from registry: $($key.PSPath), removing it now..."
$count++
Remove-Registry -RegistryPath $key.PSPath
}
}
Write-LogMessage -Message "$($count) key(s) removed"
# Remove the ISAC / Pulse Secure registry entries
$count = 0
Write-LogMessage -Message "Cleaning ISAC / Pulse Secure uninstall registries..."
$RegPath = "HKLM:\SOFTWARE\Microsoft\Windows\CurrentVersion\Uninstall"
$ProductKeys = Get-ChildItem -Path $RegPath
foreach ($key in $ProductKeys) {
$ProductName = (Get-ItemProperty -Path $key.PSPath).DisplayName
if ($ProductName -ieq $ISACProdName) {
Write-LogMessage -Message "Found '$ISACProdName' from registry: $($key.PSPath), removing it now..."
$count++
Remove-Registry -RegistryPath $key.PSPath
}
if ($ProductName -ieq $PulseProdName) {
Write-LogMessage -Message "Found '$PulseProdName' from registry: $($key.PSPath), removing it now..."
$count++
Remove-Registry -RegistryPath $key.PSPath
}
if ($key.Name -like "$PulseProdName*") {
Write-LogMessage -Message "Found '$PulseProdName*' in registry: $($key.PSPath), removing it now..."
$count++
Remove-Registry -RegistryPath $key.PSPath
}
}
Write-LogMessage -Message "$($count) key(s) removed"
# Remove the ISAC / Pulse Secure registry entries
$count = 0
Write-LogMessage -Message "Cleaning ISAC / Pulse Secure product registries..."
$RegPath = "HKLM:\SOFTWARE\Microsoft\Windows\CurrentVersion\Installer\UserData\S-1-5-18\Products"
$ProductKeys = Get-ChildItem -Path $RegPath
foreach ($key in $ProductKeys) {
$InstallRegPath = $key.PSPath + "\InstallProperties"
$DisplayName = (Get-ItemProperty -Path $InstallRegPath).DisplayName
if ($DisplayName -ieq $ISACProdName) {
Write-LogMessage -Message "Found '$ISACProdName' from registry: $($key.PSPath), removing it now..."
$count++
Remove-Registry -RegistryPath $key.PSPath
}
if ($DisplayName -ieq $PulseProdName) {
Write-LogMessage -Message "Found '$PulseProdName' from registry: $($key.PSPath), removing it now..."
$count++
Remove-Registry -RegistryPath $key.PSPath
}
}
Write-LogMessage -Message "$($count) key(s) removed"
# clean residual registries
Write-LogMessage -Message "Cleaning ISAC / Pulse Secure component registries..."
$components = Get-ChildItem -Path "HKLM:\SOFTWARE\Microsoft\Windows\CurrentVersion\Installer\UserData\S-1-5-18\components"
$count = 0
foreach ($c in $components) {
foreach($p in $c.Property) {
$propValue = (Get-ItemProperty "Registry::$($c.Name)" -Name "$($p)")."$($p)"
if ($propValue -match $PulseProdName) {
Write-LogMessage -Message "Residual registry: $propValue"
$count++
Remove-Item Registry::$($c.Name) -Recurse *>> "$CmdLogFile"
}
}
}
Write-LogMessage -Message "$($count) key(s) removed"
# Remove the ISAC / Pulse Secure folders registry entries
$count = 0
Write-LogMessage -Message "Cleaning ISAC / Pulse Secure folders registries..."
$RegPath = Get-Item -Path "HKLM:\SOFTWARE\Microsoft\Windows\CurrentVersion\Installer\Folders"
foreach ($p in $RegPath.Property) {
if ($p -match $PulseProdName) {
Write-LogMessage -Message "Residual property: $p"
$count++
Remove-ItemProperty -Path $RegPath.PSPath -Name $p
}
}
Write-LogMessage -Message "$($count) key(s) removed"
# Clean Admin Mode Residualsz
Write-LogMessage -Message "Cleaning Admin Mode Residuals..."
$DirName = "$ProgFileDir\$PulseProdName"
Remove-Directory -DirFullPath $DirName -FlushOnly $False
$DirName = "$CommonProgFileDir\$PulseProdName"
Remove-Directory -DirFullPath $DirName -FlushOnly $False
$DirName = "$CommonProgFileDir\$JuniperProdName"
Remove-Directory -DirFullPath $DirName -FlushOnly $False
$DirName = "$Env:PROGRAMDATA\$PulseProdName\Logging"
Remove-Directory -DirFullPath $DirName -FlushOnly $False
$DirName = "$Env:PROGRAMDATA\Packages"
Remove-FileWithWildcard -DirFullPath $DirName -WildCharFileName "PulseSecureReactAppPkg*"
$DirName = "$Env:WINDIR\Prefetch"
Remove-FileWithWildcard -DirFullPath $DirName -WildCharFileName "Pulse*"
$DirName = "$Env:SYSTEMDRIVE\Windows\Downloaded Program Files"
Remove-Directory -DirFullPath $DirName -FlushOnly $True
$DirName = "$Env:WINDIR\Temp"
Remove-Directory -DirFullPath $DirName -FlushOnly $True
Write-LogMessage -Message "The '$ISACProdName/$PulseProdName' Deep Clean Process has been completed successfully"
# SIG # Begin signature block
# MIIuwgYJKoZIhvcNAQcCoIIuszCCLq8CAQExDzANBglghkgBZQMEAgEFADB5Bgor
# BgEEAYI3AgEEoGswaTA0BgorBgEEAYI3AgEeMCYCAwEAAAQQH8w7YFlLCE63JNLG
# KX7zUQIBAAIBAAIBAAIBAAIBADAxMA0GCWCGSAFlAwQCAQUABCAsZijYtSN3knqe
# rKl3/ww+1aL1j//zdDagi+wQmD8TH6CCE6UwggWQMIIDeKADAgECAhAFmxtXno4h
# MuI5B72nd3VcMA0GCSqGSIb3DQEBDAUAMGIxCzAJBgNVBAYTAlVTMRUwEwYDVQQK
# EwxEaWdpQ2VydCBJbmMxGTAXBgNVBAsTEHd3dy5kaWdpY2VydC5jb20xITAfBgNV
# BAMTGERpZ2lDZXJ0IFRydXN0ZWQgUm9vdCBHNDAeFw0xMzA4MDExMjAwMDBaFw0z
# ODAxMTUxMjAwMDBaMGIxCzAJBgNVBAYTAlVTMRUwEwYDVQQKEwxEaWdpQ2VydCBJ
# bmMxGTAXBgNVBAsTEHd3dy5kaWdpY2VydC5jb20xITAfBgNVBAMTGERpZ2lDZXJ0
# IFRydXN0ZWQgUm9vdCBHNDCCAiIwDQYJKoZIhvcNAQEBBQADggIPADCCAgoCggIB
# AL/mkHNo3rvkXUo8MCIwaTPswqclLskhPfKK2FnC4SmnPVirdprNrnsbhA3EMB/z
# G6Q4FutWxpdtHauyefLKEdLkX9YFPFIPUh/GnhWlfr6fqVcWWVVyr2iTcMKyunWZ
# anMylNEQRBAu34LzB4TmdDttceItDBvuINXJIB1jKS3O7F5OyJP4IWGbNOsFxl7s
# Wxq868nPzaw0QF+xembud8hIqGZXV59UWI4MK7dPpzDZVu7Ke13jrclPXuU15zHL
# 2pNe3I6PgNq2kZhAkHnDeMe2scS1ahg4AxCN2NQ3pC4FfYj1gj4QkXCrVYJBMtfb
# BHMqbpEBfCFM1LyuGwN1XXhm2ToxRJozQL8I11pJpMLmqaBn3aQnvKFPObURWBf3
# JFxGj2T3wWmIdph2PVldQnaHiZdpekjw4KISG2aadMreSx7nDmOu5tTvkpI6nj3c
# AORFJYm2mkQZK37AlLTSYW3rM9nF30sEAMx9HJXDj/chsrIRt7t/8tWMcCxBYKqx
# YxhElRp2Yn72gLD76GSmM9GJB+G9t+ZDpBi4pncB4Q+UDCEdslQpJYls5Q5SUUd0
# viastkF13nqsX40/ybzTQRESW+UQUOsxxcpyFiIJ33xMdT9j7CFfxCBRa2+xq4aL
# T8LWRV+dIPyhHsXAj6KxfgommfXkaS+YHS312amyHeUbAgMBAAGjQjBAMA8GA1Ud
# EwEB/wQFMAMBAf8wDgYDVR0PAQH/BAQDAgGGMB0GA1UdDgQWBBTs1+OC0nFdZEzf
# Lmc/57qYrhwPTzANBgkqhkiG9w0BAQwFAAOCAgEAu2HZfalsvhfEkRvDoaIAjeNk
# aA9Wz3eucPn9mkqZucl4XAwMX+TmFClWCzZJXURj4K2clhhmGyMNPXnpbWvWVPjS
# PMFDQK4dUPVS/JA7u5iZaWvHwaeoaKQn3J35J64whbn2Z006Po9ZOSJTROvIXQPK
# 7VB6fWIhCoDIc2bRoAVgX+iltKevqPdtNZx8WorWojiZ83iL9E3SIAveBO6Mm0eB
# cg3AFDLvMFkuruBx8lbkapdvklBtlo1oepqyNhR6BvIkuQkRUNcIsbiJeoQjYUIp
# 5aPNoiBB19GcZNnqJqGLFNdMGbJQQXE9P01wI4YMStyB0swylIQNCAmXHE/A7msg
# dDDS4Dk0EIUhFQEI6FUy3nFJ2SgXUE3mvk3RdazQyvtBuEOlqtPDBURPLDab4vri
# RbgjU2wGb2dVf0a1TD9uKFp5JtKkqGKX0h7i7UqLvBv9R0oN32dmfrJbQdA75PQ7
# 9ARj6e/CVABRoIoqyc54zNXqhwQYs86vSYiv85KZtrPmYQ/ShQDnUBrkG5WdGaG5
# nLGbsQAe79APT0JsyQq87kP6OnGlyE0mpTX9iV28hWIdMtKgK1TtmlfB2/oQzxm3
# i0objwG2J5VT6LaJbVu8aNQj6ItRolb58KaAoNYes7wPD1N1KarqE3fk3oyBIa0H
# EEcRrYc9B9F1vM/zZn4wggawMIIEmKADAgECAhAIrUCyYNKcTJ9ezam9k67ZMA0G
# CSqGSIb3DQEBDAUAMGIxCzAJBgNVBAYTAlVTMRUwEwYDVQQKEwxEaWdpQ2VydCBJ
# bmMxGTAXBgNVBAsTEHd3dy5kaWdpY2VydC5jb20xITAfBgNVBAMTGERpZ2lDZXJ0
# IFRydXN0ZWQgUm9vdCBHNDAeFw0yMTA0MjkwMDAwMDBaFw0zNjA0MjgyMzU5NTla
# MGkxCzAJBgNVBAYTAlVTMRcwFQYDVQQKEw5EaWdpQ2VydCwgSW5jLjFBMD8GA1UE
# AxM4RGlnaUNlcnQgVHJ1c3RlZCBHNCBDb2RlIFNpZ25pbmcgUlNBNDA5NiBTSEEz
# ODQgMjAyMSBDQTEwggIiMA0GCSqGSIb3DQEBAQUAA4ICDwAwggIKAoICAQDVtC9C
# 0CiteLdd1TlZG7GIQvUzjOs9gZdwxbvEhSYwn6SOaNhc9es0JAfhS0/TeEP0F9ce
# 2vnS1WcaUk8OoVf8iJnBkcyBAz5NcCRks43iCH00fUyAVxJrQ5qZ8sU7H/Lvy0da
# E6ZMswEgJfMQ04uy+wjwiuCdCcBlp/qYgEk1hz1RGeiQIXhFLqGfLOEYwhrMxe6T
# SXBCMo/7xuoc82VokaJNTIIRSFJo3hC9FFdd6BgTZcV/sk+FLEikVoQ11vkunKoA
# FdE3/hoGlMJ8yOobMubKwvSnowMOdKWvObarYBLj6Na59zHh3K3kGKDYwSNHR7Oh
# D26jq22YBoMbt2pnLdK9RBqSEIGPsDsJ18ebMlrC/2pgVItJwZPt4bRc4G/rJvmM
# 1bL5OBDm6s6R9b7T+2+TYTRcvJNFKIM2KmYoX7BzzosmJQayg9Rc9hUZTO1i4F4z
# 8ujo7AqnsAMrkbI2eb73rQgedaZlzLvjSFDzd5Ea/ttQokbIYViY9XwCFjyDKK05
# huzUtw1T0PhH5nUwjewwk3YUpltLXXRhTT8SkXbev1jLchApQfDVxW0mdmgRQRNY
# mtwmKwH0iU1Z23jPgUo+QEdfyYFQc4UQIyFZYIpkVMHMIRroOBl8ZhzNeDhFMJlP
# /2NPTLuqDQhTQXxYPUez+rbsjDIJAsxsPAxWEQIDAQABo4IBWTCCAVUwEgYDVR0T
# AQH/BAgwBgEB/wIBADAdBgNVHQ4EFgQUaDfg67Y7+F8Rhvv+YXsIiGX0TkIwHwYD
# VR0jBBgwFoAU7NfjgtJxXWRM3y5nP+e6mK4cD08wDgYDVR0PAQH/BAQDAgGGMBMG
# A1UdJQQMMAoGCCsGAQUFBwMDMHcGCCsGAQUFBwEBBGswaTAkBggrBgEFBQcwAYYY
# aHR0cDovL29jc3AuZGlnaWNlcnQuY29tMEEGCCsGAQUFBzAChjVodHRwOi8vY2Fj
# ZXJ0cy5kaWdpY2VydC5jb20vRGlnaUNlcnRUcnVzdGVkUm9vdEc0LmNydDBDBgNV
# HR8EPDA6MDigNqA0hjJodHRwOi8vY3JsMy5kaWdpY2VydC5jb20vRGlnaUNlcnRU
# cnVzdGVkUm9vdEc0LmNybDAcBgNVHSAEFTATMAcGBWeBDAEDMAgGBmeBDAEEATAN
# BgkqhkiG9w0BAQwFAAOCAgEAOiNEPY0Idu6PvDqZ01bgAhql+Eg08yy25nRm95Ry
# sQDKr2wwJxMSnpBEn0v9nqN8JtU3vDpdSG2V1T9J9Ce7FoFFUP2cvbaF4HZ+N3HL
# IvdaqpDP9ZNq4+sg0dVQeYiaiorBtr2hSBh+3NiAGhEZGM1hmYFW9snjdufE5Btf
# Q/g+lP92OT2e1JnPSt0o618moZVYSNUa/tcnP/2Q0XaG3RywYFzzDaju4ImhvTnh
# OE7abrs2nfvlIVNaw8rpavGiPttDuDPITzgUkpn13c5UbdldAhQfQDN8A+KVssIh
# dXNSy0bYxDQcoqVLjc1vdjcshT8azibpGL6QB7BDf5WIIIJw8MzK7/0pNVwfiThV
# 9zeKiwmhywvpMRr/LhlcOXHhvpynCgbWJme3kuZOX956rEnPLqR0kq3bPKSchh/j
# wVYbKyP/j7XqiHtwa+aguv06P0WmxOgWkVKLQcBIhEuWTatEQOON8BUozu3xGFYH
# Ki8QxAwIZDwzj64ojDzLj4gLDb879M4ee47vtevLt/B3E+bnKD+sEq6lLyJsQfmC
# XBVmzGwOysWGw/YmMwwHS6DTBwJqakAwSEs0qFEgu60bhQjiWQ1tygVQK+pKHJ6l
# /aCnHwZ05/LWUpD9r4VIIflXO7ScA+2GRfS0YW6/aOImYIbqyK+p/pQd52MbOoZW
# eE4wggdZMIIFQaADAgECAhAKWa4NduqztbG3densaafyMA0GCSqGSIb3DQEBCwUA
# MGkxCzAJBgNVBAYTAlVTMRcwFQYDVQQKEw5EaWdpQ2VydCwgSW5jLjFBMD8GA1UE
# AxM4RGlnaUNlcnQgVHJ1c3RlZCBHNCBDb2RlIFNpZ25pbmcgUlNBNDA5NiBTSEEz
# ODQgMjAyMSBDQTEwHhcNMjMwOTI1MDAwMDAwWhcNMjYwNDI5MjM1OTU5WjBhMQsw
# CQYDVQQGEwJVUzENMAsGA1UECBMEVXRhaDEVMBMGA1UEBxMMU291dGggSm9yZGFu
# MRUwEwYDVQQKEwxJdmFudGksIEluYy4xFTATBgNVBAMTDEl2YW50aSwgSW5jLjCC
# AiIwDQYJKoZIhvcNAQEBBQADggIPADCCAgoCggIBAPZSo6iSXWipswC6jPqwOwqJ
# gIJHXh8Pi7t4aXmaorOlpa+y3Q38EJ3wFrVG4cWdrcpBFT01Je8eASXuh7Ndy6yc
# B3sdtQ41B/zET1ePmWa6a9KJV2LYy2BmiMRqgw2HBMh0K3rcG/imzTvXr65MFWJu
# +gZfVTmzWkwUtDNCR9PflRuPzklp1w9kFT+fS5TiDGCPGe424ABe6HLYJHDNT6Ry
# L4LlZoZjM8YnUVNdPLjHrcjtuxd2wIOSFebn8Ch6xlYChvPyxeIJtBT9fg+NQEmE
# X0VjYH2mnv5TrlMBYvi1uJD6HAEjxcIt/6STBgLQ5VGP0NShX9z3uqvZ12E0F+Qg
# qJnN2GnuGqDd7sJisCM1+LRDLU+VtssI7k2khbDk+07iV+KjVoOdb7BdWxArWgj/
# W7YI/K5ca241O7v5zKC0QW2V6x2AK5bA0po9iCdHoGhjGns9xE2HRmNIJNRph6J5
# Yl57d5I4gtFfD1fUHQ+K6AF52W8a6ycBoF2//f4OQiT3MHOSfBcb0NBjGeMtEL3p
# 0GHn6COV1txl1fLZtAuLV3QF1DOKmmX30HDZ0E6f17JnUMpEUCvICSIL/BkG+y0i
# 54OHUU0n7WqcLWKDvAWmq4x/vduWQWOleOJsKpPAnbNmOhDKsH71+7bninOjStYI
# YUliqMMKBhVm9CIhTHE/AgMBAAGjggIDMIIB/zAfBgNVHSMEGDAWgBRoN+Drtjv4
# XxGG+/5hewiIZfROQjAdBgNVHQ4EFgQUfVFT5pRwkUJj1o3NPg/oZ0O7sPcwPgYD
# VR0gBDcwNTAzBgZngQwBBAEwKTAnBggrBgEFBQcCARYbaHR0cDovL3d3dy5kaWdp
# Y2VydC5jb20vQ1BTMA4GA1UdDwEB/wQEAwIHgDATBgNVHSUEDDAKBggrBgEFBQcD
# AzCBtQYDVR0fBIGtMIGqMFOgUaBPhk1odHRwOi8vY3JsMy5kaWdpY2VydC5jb20v
# RGlnaUNlcnRUcnVzdGVkRzRDb2RlU2lnbmluZ1JTQTQwOTZTSEEzODQyMDIxQ0Ex
# LmNybDBToFGgT4ZNaHR0cDovL2NybDQuZGlnaWNlcnQuY29tL0RpZ2lDZXJ0VHJ1
# c3RlZEc0Q29kZVNpZ25pbmdSU0E0MDk2U0hBMzg0MjAyMUNBMS5jcmwwgZQGCCsG
# AQUFBwEBBIGHMIGEMCQGCCsGAQUFBzABhhhodHRwOi8vb2NzcC5kaWdpY2VydC5j
# b20wXAYIKwYBBQUHMAKGUGh0dHA6Ly9jYWNlcnRzLmRpZ2ljZXJ0LmNvbS9EaWdp
# Q2VydFRydXN0ZWRHNENvZGVTaWduaW5nUlNBNDA5NlNIQTM4NDIwMjFDQTEuY3J0
# MAkGA1UdEwQCMAAwDQYJKoZIhvcNAQELBQADggIBADzrxl/w8qgIM1YXfhF1mjQo
# ikGn88zJmyEWW6m3dgSZxdhwMHlK69dkBZ6U5v0G4MkT0Jp/RVyCi2ywkr5w5edy
# MGl/ULvuoWS7HtuusX0rE7YO79hLWLWP+VcSIzXc8Ev1IxaqIO1jdv7rOdfTtqc8
# SFfhYzkKuomMSFC0lYPoITags2jFFFiiSk/ainmdN9poEhANVeID+YD0Fy7U7xzv
# qfi1/+aFYkcpsmp4SqqExBhZeq2StufODXH5f36wU2pLtJ9QaKYT36f60HIoMNFk
# F5rLmp18C5zb6rXPFVVN75jm+xD4LqyYBqZwcPIPPmTYhZQW83TKryT9myv/WQ7j
# avtlTrpKa+3dYTrooaVooKtTaVu/sjDPc44FfmfiUpU7Y+lxULmMjKeua9BEPgmX
# UvLHD6mxu8HLYnd7JU8caidTkhqCQ5vdZuoTC7rEC3m8rnUDFkvPOgM2spfH+hHi
# t3qVIvWpzKVbxXm3OY5pJAFAaH1DY4NzuwgefadQ+CtjeIeITQiL887AudiGKVSm
# ZPRvXNwF5T3nJtlBEtHzz32DDA7wmFfS38uzvG5FRJcYBEAuuPJ2sQbJkV5QnCPD
# FXsZLrUhd45V69/mGMiJYrpxQnsbPFFV8bNX3fG/FttbtZItkG3x3JZlXjGKmtEw
# lBLUpq5qo0HeykpmeKoyMYIaczCCGm8CAQEwfTBpMQswCQYDVQQGEwJVUzEXMBUG
# A1UEChMORGlnaUNlcnQsIEluYy4xQTA/BgNVBAMTOERpZ2lDZXJ0IFRydXN0ZWQg
# RzQgQ29kZSBTaWduaW5nIFJTQTQwOTYgU0hBMzg0IDIwMjEgQ0ExAhAKWa4Nduqz
# tbG3densaafyMA0GCWCGSAFlAwQCAQUAoIGEMBgGCisGAQQBgjcCAQwxCjAIoAKA
# AKECgAAwGQYJKoZIhvcNAQkDMQwGCisGAQQBgjcCAQQwHAYKKwYBBAGCNwIBCzEO
# MAwGCisGAQQBgjcCARUwLwYJKoZIhvcNAQkEMSIEIMINw6DYtyCmr1ewMxmDR4QL
# ge+F2/f50T/0QW5lzmo+MA0GCSqGSIb3DQEBAQUABIICADTt0yQkLrLDpakIcRi3
# Jpk0ozw3Zjg8YbGlHoHDWsXgq4IUfyNe2I49eT+vU2VgVamb/RzKxd6IB3WCxdz2
# iyoUID9i8UTllL9E1SNK0oCTjZcKWl5WwykOPSGaZnwsa7PAoMmvM2FTRDUBPhXV
# JCjknanGJj0MbQ3zaKTn6FW3hhIl7EN6+B8iq/rIZnYnkr6XiRUIWvh++xh2sppG
# IM8SFcQon4Q+6ajJYrNBMPsm66lisOw87zFceiGqHXaHNevBUDiposXFnNXNiOJP
# ShijuoLHnCTB2mPNDrkKyIlQ++ix73/oToWxvZRaTFWXWUxvuQhzNBYm+A3v75XP
# p4N/PdDKT9aVu9eAaY2BWkPFTJq1G2WI9Mku8zPYepSq+ggxXsDHHz6kXoxfoMGj
# +ocSv/P2Wo1HDoPQ8f3j1O2meanLr2/l1DZkMW0BatNAaKvAwWXhPtoAK2qASyma
# 9DJdMcYXX2qY/4tc75CLttLZLXQlecHrQLILf0DsSBJf0DJkpiHMv/Fy15E+ahFv
# /WiAOS8CyDriNt3MqSGX/V5Qqjvqk6ia0oUaR655sfpk0HdTEKHpTJAnM5SfrvrH
# ivGZrinNBqZ7QdI/fnqRFrLnad5vjxNuXDHneRtBPIHFKILP64evWywmndIMM2Lh
# +z2qvKm84J0egCE6ornMCu4+oYIXQDCCFzwGCisGAQQBgjcDAwExghcsMIIXKAYJ
# KoZIhvcNAQcCoIIXGTCCFxUCAQMxDzANBglghkgBZQMEAgEFADB4BgsqhkiG9w0B
# CRABBKBpBGcwZQIBAQYJYIZIAYb9bAcBMDEwDQYJYIZIAWUDBAIBBQAEIBRCKw0i
# D8L3m0MDcWttAmF69oyzYyTNJIO9wQuE8/vnAhEAoGIADJ/2Tlz6L+kL5KanBxgP
# MjAyNDA5MzAwNzM2NDhaoIITCTCCBsIwggSqoAMCAQICEAVEr/OUnQg5pr/bP1/l
# YRYwDQYJKoZIhvcNAQELBQAwYzELMAkGA1UEBhMCVVMxFzAVBgNVBAoTDkRpZ2lD
# ZXJ0LCBJbmMuMTswOQYDVQQDEzJEaWdpQ2VydCBUcnVzdGVkIEc0IFJTQTQwOTYg
# U0hBMjU2IFRpbWVTdGFtcGluZyBDQTAeFw0yMzA3MTQwMDAwMDBaFw0zNDEwMTMy
# MzU5NTlaMEgxCzAJBgNVBAYTAlVTMRcwFQYDVQQKEw5EaWdpQ2VydCwgSW5jLjEg
# MB4GA1UEAxMXRGlnaUNlcnQgVGltZXN0YW1wIDIwMjMwggIiMA0GCSqGSIb3DQEB
# AQUAA4ICDwAwggIKAoICAQCjU0WHHYOOW6w+VLMj4M+f1+XS512hDgncL0ijl3o7
# Kpxn3GIVWMGpkxGnzaqyat0QKYoeYmNp01icNXG/OpfrlFCPHCDqx5o7L5Zm42nn
# af5bw9YrIBzBl5S0pVCB8s/LB6YwaMqDQtr8fwkklKSCGtpqutg7yl3eGRiF+0Xq
# DWFsnf5xXsQGmjzwxS55DxtmUuPI1j5f2kPThPXQx/ZILV5FdZZ1/t0QoRuDwbjm
# UpW1R9d4KTlr4HhZl+NEK0rVlc7vCBfqgmRN/yPjyobutKQhZHDr1eWg2mOzLukF
# 7qr2JPUdvJscsrdf3/Dudn0xmWVHVZ1KJC+sK5e+n+T9e3M+Mu5SNPvUu+vUoCw0
# m+PebmQZBzcBkQ8ctVHNqkxmg4hoYru8QRt4GW3k2Q/gWEH72LEs4VGvtK0VBhTq
# YggT02kefGRNnQ/fztFejKqrUBXJs8q818Q7aESjpTtC/XN97t0K/3k0EH6mXApY
# TAA+hWl1x4Nk1nXNjxJ2VqUk+tfEayG66B80mC866msBsPf7Kobse1I4qZgJoXGy
# bHGvPrhvltXhEBP+YUcKjP7wtsfVx95sJPC/QoLKoHE9nJKTBLRpcCcNT7e1NtHJ
# XwikcKPsCvERLmTgyyIryvEoEyFJUX4GZtM7vvrrkTjYUQfKlLfiUKHzOtOKg8tA
# ewIDAQABo4IBizCCAYcwDgYDVR0PAQH/BAQDAgeAMAwGA1UdEwEB/wQCMAAwFgYD
# VR0lAQH/BAwwCgYIKwYBBQUHAwgwIAYDVR0gBBkwFzAIBgZngQwBBAIwCwYJYIZI
# AYb9bAcBMB8GA1UdIwQYMBaAFLoW2W1NhS9zKXaaL3WMaiCPnshvMB0GA1UdDgQW
# BBSltu8T5+/N0GSh1VapZTGj3tXjSTBaBgNVHR8EUzBRME+gTaBLhklodHRwOi8v
# Y3JsMy5kaWdpY2VydC5jb20vRGlnaUNlcnRUcnVzdGVkRzRSU0E0MDk2U0hBMjU2
# VGltZVN0YW1waW5nQ0EuY3JsMIGQBggrBgEFBQcBAQSBgzCBgDAkBggrBgEFBQcw
# AYYYaHR0cDovL29jc3AuZGlnaWNlcnQuY29tMFgGCCsGAQUFBzAChkxodHRwOi8v
# Y2FjZXJ0cy5kaWdpY2VydC5jb20vRGlnaUNlcnRUcnVzdGVkRzRSU0E0MDk2U0hB
# MjU2VGltZVN0YW1waW5nQ0EuY3J0MA0GCSqGSIb3DQEBCwUAA4ICAQCBGtbeoKm1
# mBe8cI1PijxonNgl/8ss5M3qXSKS7IwiAqm4z4Co2efjxe0mgopxLxjdTrbebNfh
# YJwr7e09SI64a7p8Xb3CYTdoSXej65CqEtcnhfOOHpLawkA4n13IoC4leCWdKgV6
# hCmYtld5j9smViuw86e9NwzYmHZPVrlSwradOKmB521BXIxp0bkrxMZ7z5z6eOKT
# GnaiaXXTUOREEr4gDZ6pRND45Ul3CFohxbTPmJUaVLq5vMFpGbrPFvKDNzRusEEm
# 3d5al08zjdSNd311RaGlWCZqA0Xe2VC1UIyvVr1MxeFGxSjTredDAHDezJieGYkD
# 6tSRN+9NUvPJYCHEVkft2hFLjDLDiOZY4rbbPvlfsELWj+MXkdGqwFXjhr+sJyxB
# 0JozSqg21Llyln6XeThIX8rC3D0y33XWNmdaifj2p8flTzU8AL2+nCpseQHc2kTm
# Ot44OwdeOVj0fHMxVaCAEcsUDH6uvP6k63llqmjWIso765qCNVcoFstp8jKastLY
# OrixRoZruhf9xHdsFWyuq69zOuhJRrfVf8y2OMDY7Bz1tqG4QyzfTkx9HmhwwHcK
# 1ALgXGC7KP845VJa1qwXIiNO9OzTF/tQa/8Hdx9xl0RBybhG02wyfFgvZ0dl5Rtz
# tpn5aywGRu9BHvDwX+Db2a2QgESvgBBBijCCBq4wggSWoAMCAQICEAc2N7ckVHzY
# R6z9KGYqXlswDQYJKoZIhvcNAQELBQAwYjELMAkGA1UEBhMCVVMxFTATBgNVBAoT
# DERpZ2lDZXJ0IEluYzEZMBcGA1UECxMQd3d3LmRpZ2ljZXJ0LmNvbTEhMB8GA1UE
# AxMYRGlnaUNlcnQgVHJ1c3RlZCBSb290IEc0MB4XDTIyMDMyMzAwMDAwMFoXDTM3
# MDMyMjIzNTk1OVowYzELMAkGA1UEBhMCVVMxFzAVBgNVBAoTDkRpZ2lDZXJ0LCBJ
# bmMuMTswOQYDVQQDEzJEaWdpQ2VydCBUcnVzdGVkIEc0IFJTQTQwOTYgU0hBMjU2
# IFRpbWVTdGFtcGluZyBDQTCCAiIwDQYJKoZIhvcNAQEBBQADggIPADCCAgoCggIB
# AMaGNQZJs8E9cklRVcclA8TykTepl1Gh1tKD0Z5Mom2gsMyD+Vr2EaFEFUJfpIjz
# aPp985yJC3+dH54PMx9QEwsmc5Zt+FeoAn39Q7SE2hHxc7Gz7iuAhIoiGN/r2j3E
# F3+rGSs+QtxnjupRPfDWVtTnKC3r07G1decfBmWNlCnT2exp39mQh0YAe9tEQYnc
# fGpXevA3eZ9drMvohGS0UvJ2R/dhgxndX7RUCyFobjchu0CsX7LeSn3O9TkSZ+8O
# pWNs5KbFHc02DVzV5huowWR0QKfAcsW6Th+xtVhNef7Xj3OTrCw54qVI1vCwMROp
# VymWJy71h6aPTnYVVSZwmCZ/oBpHIEPjQ2OAe3VuJyWQmDo4EbP29p7mO1vsgd4i
# FNmCKseSv6De4z6ic/rnH1pslPJSlRErWHRAKKtzQ87fSqEcazjFKfPKqpZzQmif
# tkaznTqj1QPgv/CiPMpC3BhIfxQ0z9JMq++bPf4OuGQq+nUoJEHtQr8FnGZJUlD0
# UfM2SU2LINIsVzV5K6jzRWC8I41Y99xh3pP+OcD5sjClTNfpmEpYPtMDiP6zj9Ne
# S3YSUZPJjAw7W4oiqMEmCPkUEBIDfV8ju2TjY+Cm4T72wnSyPx4JduyrXUZ14mCj
# WAkBKAAOhFTuzuldyF4wEr1GnrXTdrnSDmuZDNIztM2xAgMBAAGjggFdMIIBWTAS
# BgNVHRMBAf8ECDAGAQH/AgEAMB0GA1UdDgQWBBS6FtltTYUvcyl2mi91jGogj57I
# bzAfBgNVHSMEGDAWgBTs1+OC0nFdZEzfLmc/57qYrhwPTzAOBgNVHQ8BAf8EBAMC
# AYYwEwYDVR0lBAwwCgYIKwYBBQUHAwgwdwYIKwYBBQUHAQEEazBpMCQGCCsGAQUF
# BzABhhhodHRwOi8vb2NzcC5kaWdpY2VydC5jb20wQQYIKwYBBQUHMAKGNWh0dHA6
# Ly9jYWNlcnRzLmRpZ2ljZXJ0LmNvbS9EaWdpQ2VydFRydXN0ZWRSb290RzQuY3J0
# MEMGA1UdHwQ8MDowOKA2oDSGMmh0dHA6Ly9jcmwzLmRpZ2ljZXJ0LmNvbS9EaWdp
# Q2VydFRydXN0ZWRSb290RzQuY3JsMCAGA1UdIAQZMBcwCAYGZ4EMAQQCMAsGCWCG
# SAGG/WwHATANBgkqhkiG9w0BAQsFAAOCAgEAfVmOwJO2b5ipRCIBfmbW2CFC4bAY
# LhBNE88wU86/GPvHUF3iSyn7cIoNqilp/GnBzx0H6T5gyNgL5Vxb122H+oQgJTQx
# Z822EpZvxFBMYh0MCIKoFr2pVs8Vc40BIiXOlWk/R3f7cnQU1/+rT4osequFzUNf
# 7WC2qk+RZp4snuCKrOX9jLxkJodskr2dfNBwCnzvqLx1T7pa96kQsl3p/yhUifDV
# inF2ZdrM8HKjI/rAJ4JErpknG6skHibBt94q6/aesXmZgaNWhqsKRcnfxI2g55j7
# +6adcq/Ex8HBanHZxhOACcS2n82HhyS7T6NJuXdmkfFynOlLAlKnN36TU6w7HQhJ
# D5TNOXrd/yVjmScsPT9rp/Fmw0HNT7ZAmyEhQNC3EyTN3B14OuSereU0cZLXJmvk
# OHOrpgFPvT87eK1MrfvElXvtCl8zOYdBeHo46Zzh3SP9HSjTx/no8Zhf+yvYfvJG
# nXUsHicsJttvFXseGYs2uJPU5vIXmVnKcPA3v5gA3yAWTyf7YGcWoWa63VXAOimG
# sJigK+2VQbc61RWYMbRiCQ8KvYHZE/6/pNHzV9m8BPqC3jLfBInwAM1dwvnQI38A
# C+R2AibZ8GV2QqYphwlHK+Z/GqSFD/yYlvZVVCsfgPrA8g4r5db7qS9EFUrnEw4d
# 2zc4GqEr9u3WfPwwggWNMIIEdaADAgECAhAOmxiO+dAt5+/bUOIIQBhaMA0GCSqG
# SIb3DQEBDAUAMGUxCzAJBgNVBAYTAlVTMRUwEwYDVQQKEwxEaWdpQ2VydCBJbmMx
# GTAXBgNVBAsTEHd3dy5kaWdpY2VydC5jb20xJDAiBgNVBAMTG0RpZ2lDZXJ0IEFz
# c3VyZWQgSUQgUm9vdCBDQTAeFw0yMjA4MDEwMDAwMDBaFw0zMTExMDkyMzU5NTla
# MGIxCzAJBgNVBAYTAlVTMRUwEwYDVQQKEwxEaWdpQ2VydCBJbmMxGTAXBgNVBAsT
# EHd3dy5kaWdpY2VydC5jb20xITAfBgNVBAMTGERpZ2lDZXJ0IFRydXN0ZWQgUm9v
# dCBHNDCCAiIwDQYJKoZIhvcNAQEBBQADggIPADCCAgoCggIBAL/mkHNo3rvkXUo8
# MCIwaTPswqclLskhPfKK2FnC4SmnPVirdprNrnsbhA3EMB/zG6Q4FutWxpdtHauy
# efLKEdLkX9YFPFIPUh/GnhWlfr6fqVcWWVVyr2iTcMKyunWZanMylNEQRBAu34Lz
# B4TmdDttceItDBvuINXJIB1jKS3O7F5OyJP4IWGbNOsFxl7sWxq868nPzaw0QF+x
# embud8hIqGZXV59UWI4MK7dPpzDZVu7Ke13jrclPXuU15zHL2pNe3I6PgNq2kZhA
# kHnDeMe2scS1ahg4AxCN2NQ3pC4FfYj1gj4QkXCrVYJBMtfbBHMqbpEBfCFM1Lyu
# GwN1XXhm2ToxRJozQL8I11pJpMLmqaBn3aQnvKFPObURWBf3JFxGj2T3wWmIdph2
# PVldQnaHiZdpekjw4KISG2aadMreSx7nDmOu5tTvkpI6nj3cAORFJYm2mkQZK37A
# lLTSYW3rM9nF30sEAMx9HJXDj/chsrIRt7t/8tWMcCxBYKqxYxhElRp2Yn72gLD7
# 6GSmM9GJB+G9t+ZDpBi4pncB4Q+UDCEdslQpJYls5Q5SUUd0viastkF13nqsX40/
# ybzTQRESW+UQUOsxxcpyFiIJ33xMdT9j7CFfxCBRa2+xq4aLT8LWRV+dIPyhHsXA
# j6KxfgommfXkaS+YHS312amyHeUbAgMBAAGjggE6MIIBNjAPBgNVHRMBAf8EBTAD
# AQH/MB0GA1UdDgQWBBTs1+OC0nFdZEzfLmc/57qYrhwPTzAfBgNVHSMEGDAWgBRF
# 66Kv9JLLgjEtUYunpyGd823IDzAOBgNVHQ8BAf8EBAMCAYYweQYIKwYBBQUHAQEE
# bTBrMCQGCCsGAQUFBzABhhhodHRwOi8vb2NzcC5kaWdpY2VydC5jb20wQwYIKwYB
# BQUHMAKGN2h0dHA6Ly9jYWNlcnRzLmRpZ2ljZXJ0LmNvbS9EaWdpQ2VydEFzc3Vy
# ZWRJRFJvb3RDQS5jcnQwRQYDVR0fBD4wPDA6oDigNoY0aHR0cDovL2NybDMuZGln
# aWNlcnQuY29tL0RpZ2lDZXJ0QXNzdXJlZElEUm9vdENBLmNybDARBgNVHSAECjAI
# MAYGBFUdIAAwDQYJKoZIhvcNAQEMBQADggEBAHCgv0NcVec4X6CjdBs9thbX979X
# B72arKGHLOyFXqkauyL4hxppVCLtpIh3bb0aFPQTSnovLbc47/T/gLn4offyct4k
# vFIDyE7QKt76LVbP+fT3rDB6mouyXtTP0UNEm0Mh65ZyoUi0mcudT6cGAxN3J0TU
# 53/oWajwvy8LpunyNDzs9wPHh6jSTEAZNUZqaVSwuKFWjuyk1T3osdz9HNj0d1pc
# VIxv76FQPfx2CWiEn2/K2yCNNWAcAgPLILCsWKAOQGPFmCLBsln1VWvPJ6tsds5v
# Iy30fnFqI2si/xK4VC0nftg62fC2h5b9W9FcrBjDTZ9ztwGpn1eqXijiuZQxggN2
# MIIDcgIBATB3MGMxCzAJBgNVBAYTAlVTMRcwFQYDVQQKEw5EaWdpQ2VydCwgSW5j
# LjE7MDkGA1UEAxMyRGlnaUNlcnQgVHJ1c3RlZCBHNCBSU0E0MDk2IFNIQTI1NiBU
# aW1lU3RhbXBpbmcgQ0ECEAVEr/OUnQg5pr/bP1/lYRYwDQYJYIZIAWUDBAIBBQCg
# gdEwGgYJKoZIhvcNAQkDMQ0GCyqGSIb3DQEJEAEEMBwGCSqGSIb3DQEJBTEPFw0y
# NDA5MzAwNzM2NDhaMCsGCyqGSIb3DQEJEAIMMRwwGjAYMBYEFGbwKzLCwskPgl3O
# qorJxk8ZnM9AMC8GCSqGSIb3DQEJBDEiBCCoNSPQ9S/lkXksGkFHj/GkueV7/D9/
# IftHn1Qqafd/mDA3BgsqhkiG9w0BCRACLzEoMCYwJDAiBCDS9uRt7XQizNHUQFdo
# QTZvgoraVZquMxavTRqa1Ax4KDANBgkqhkiG9w0BAQEFAASCAgB6XeSX7HubNVyV
# 2ZXeu/b1eGayl6G7IOV8C6bbP43qqLM/T1AY9OUsxl6fdcIO90e58QuI2HU+yYs8
# 0NBDPkEm0EREtsJaJAcDhXUQgAzUo3TujT7BX7BvKxpseWJOitTR0yLY9nTb7R1A
# 00XJy3VKIHULvm/ZkzzxjmTXY7mDFERMiITFI5xzLiPIxbSV24P5ln31r5pBoZWZ
# h+EuAE8ud7gF8xoEAzcbckootTsQfZXyCnPxrEpgbSr6KqlavOszdEZPF39AYFdT
# VY0gQl+lpiFphHHBHbWD7eCvQzHUSVMD+MIoj1EPUGZIVm98RlD9UUsssxv2s76V
# Tm1HPLrtIJy1bSF6xIH23P442p65J+On54V7+z0XsjSwVmeKbBifXANZqiBhiM4v
# psBrFhXgFDSmC5IScwqy0EqKO6Iuc9fkhJNtPWnyml/QFlMKXHV0bZkUeV4iGXAT
# TrkCNf9Y7mCWr8j9U522KfLuRHhAXceEW5CCN+XH8uloA2i2w1eKbabUKkIdBSmB
# H6SLvUqIQAc0vxmRRxVV3hzm8YG6j9pntPphG3Kgv4QFpesUYPLXj1DrfsIYt22D
# zBvokUWu33xcWG/jpWEVdPaipTQU4ags/sRDDjzllzu5hOSyJ445gLZMGKkSlyUJ
# FXsKnBAj4ObbqpZ9506exrRG6aJ9Aw==
# SIG # End signature block