Function SourceTools
{ . $([Scriptblock]::Create((New-Object Net.WebClient).DownloadString('https://dev.emberkom.com/emberkom/management-scripts/raw/branch/master/Tools.ps1'))) }
. SourceTools

Function Get-UninstallCodes ([string]$DisplayName) {
    'HKLM:SOFTWARE\Microsoft\Windows\CurrentVersion\Uninstall', 'HKLM:SOFTWARE\WOW6432Node\Microsoft\Windows\CurrentVersion\Uninstall' | ForEach-Object {
        Get-ChildItem -Path $_ -ErrorAction SilentlyContinue | ForEach-Object {
            If ( $(Get-ItemProperty -Path $_.PSPath -Name 'DisplayName' -ErrorAction SilentlyContinue) -and ($(Get-ItemPropertyValue -Path $_.PSPath -Name 'DisplayName' -ErrorAction SilentlyContinue) -eq $DisplayName) ) {
                $str = (Get-ItemPropertyValue -Path $_.PSPath -Name 'UninstallString')
                $code = $str.Substring(($str.Length - 37),36)
                LogMsg "  - ${code}"
                $UninstallCodes.Add($code) | Out-Null
            }
        }
    }
}

Function Get-ProductKeys ([string]$ProductName) {
    Get-ChildItem -Path 'HKCR:Installer\Products' | ForEach-Object {
        If ( $(Get-ItemProperty -Path $_.PSPath -Name 'ProductName' -ErrorAction SilentlyContinue) -and ($(Get-ItemPropertyValue -Path $_.PSPath -Name 'ProductName' -ErrorAction SilentlyContinue) -eq $ProductName) ) {
            $prod = $_.PSPath.Substring($_.PSPath.Length - 32)
            LogMsg "  - ${prod}"
            $ProductKeys.Add($prod) | Out-Null
        }
    }
}

Function Get-ServiceStatus ([string]$Name) { (Get-Service -Name $Name -ErrorAction SilentlyContinue).Status }

Function Stop-RunningService ([string]$Name) {
    If ( $(Get-ServiceStatus -Name $Name) -eq "Running" ) { LogMsg "Stopping : ${Name} service" ; Stop-Service -Name $Name -Force }
}

Function Remove-StoppedService ([string]$Name) {
    $s = (Get-ServiceStatus -Name $Name)
    If ( $s ) {
        If ( $s -eq "Stopped" ) {
            LogMsg "Deleting : ${Name} service"
            Start-Process "sc.exe" -ArgumentList "delete ${Name}" -Wait
        }
    } Else { LogMsg "Not Found: ${Name} service" }
}

Function Stop-RunningProcess ([string]$Name) {
    $p = (Get-Process -Name $_ -ErrorAction SilentlyContinue)
    If ( $p ) { LogMsg "Stopping : ${Name}.exe" ; $p | Stop-Process -Force }
    Else { LogMsg "Not Found: ${Name}.exe is not running"}
}

Function Remove-Path ([string]$Path) {
    If ( Test-Path $Path ) {
        LogMsg "Deleting : ${Path}"
        Remove-Item $Path -Recurse -Force
    } Else { LogMsg "Not Found: ${Path}" }
}

Function Get-AllExeFiles ([string]$Path) {
    If ( Test-Path $Path ) {
        Get-ChildItem -Path $Path -Filter *.exe -Recurse | ForEach-Object { $ExeFiles.Add($_.BaseName) | Out-Null }
    }
}

LogMsg "Uninstalling Atera agent"

LogMsg "Mounting HKEY_CLASSES_ROOT registry hive"
New-PSDrive -Name HKCR -PSProvider Registry -Root HKEY_CLASSES_ROOT | Out-Null

LogMsg "Getting MSI package codes from the uninstall key"
$UninstallCodes = New-Object System.Collections.ArrayList
'AteraAgent' | ForEach-Object { Get-UninstallCodes -DisplayName $_ }

LogMsg "Getting product keys from the list of installed products"
$ProductKeys = New-Object System.Collections.ArrayList
'AteraAgent' | ForEach-Object { Get-ProductKeys -ProductName $_ }

LogMsg "Directories that we may need to delete"
$Directories = @("${Env:ProgramFiles}\ATERA Networks")
$Directories | ForEach-Object { LogMsg "  - ${_}" }

LogMsg "Processes that we may need to terminate"
$ExeFiles = New-Object System.Collections.ArrayList
$Directories | ForEach-Object { Get-AllExeFiles -Path $_ }
$ExeFiles.Add('reg')  | Out-Null
$ExeFiles | ForEach-Object { LogMsg "  - ${_}.exe" }

LogMsg "Windows services that we may need to stop and/or delete"
$ServiceList = @('AteraAgent')
$ServiceList | ForEach-Object { LogMsg "  - ${_}" }

LogMsg "Windows Registry keys we may need to delete"
$RegistryKeys = @('HKLM:SOFTWARE\ATERA Networks')
$RegistryKeys | ForEach-Object { LogMsg "  - ${_}" }

# Uninstall each MSI package code in $UninstallCodes
$UninstallCodes | ForEach-Object { LogMsg "Uninstall: ${_}" ; Start-Process "msiexec.exe" -ArgumentList "/X{${_}} /qn" -Wait }

# Stop services if they're still running
$ServiceList | ForEach-Object { Stop-RunningService -Name $_ }

# Terminate all relevant processes that may still be running
$ExeFiles | ForEach-Object { Stop-RunningProcess $_ }

# Delete services if they're still present
$ServiceList | ForEach-Object { Remove-StoppedService -Name $_ }

# Delete products from MSI installer registry
$ProductKeys | ForEach-Object { Remove-Path -Path "HKCR:Installer\Products\${_}" }

# Delete registry keys
$RegistryKeys | ForEach-Object { Remove-Path -Path $_ }

# Delete remaining directories
$Directories | ForEach-Object { Remove-Path -Path $_ }

LogMsg "Unmount HKEY_CLASSES_ROOT registry hive"
Remove-PSDrive -Name HKCR

LogMsg "Finished uninstalling Atera Agent"

# Delete this script
Remove-Item $MyInvocation.MyCommand.Path -Force