Skip to content

Commit

Permalink
AzureAuth Windows uninstall script (#340)
Browse files Browse the repository at this point in the history
* First commit uninstall script

* Improved comments and variable names

* Added message about whether something was uninstalled or not

* Removed file accidentally created

* Redesigned workflow

* Close running instances of azureauth before deleting

* Fixed bug, not removing from path

* Added warning in case AZUREAUTH_INSTALL_DIRECTORY is not empty

* Applied feedback from code review

* Warn user about custom locations at the end

* Changed order of functions

* Fixed error, verbose not printing

* Changed checks to see if parent of path is the default location

* Improved messaging
  • Loading branch information
Emilio0404 authored Oct 12, 2023
1 parent 4457329 commit e3a00aa
Showing 1 changed file with 132 additions and 0 deletions.
132 changes: 132 additions & 0 deletions install/uninstall.ps1
Original file line number Diff line number Diff line change
@@ -0,0 +1,132 @@
# Enable a default -Verbose flag for debug output.
[CmdletBinding()]
$VerbosePreference = "Continue"

# Halt script execution at the first failed command.
$script:ErrorActionPreference='Stop'

$azureauthDefaultLocation = ([System.IO.Path]::Combine($Env:LOCALAPPDATA, "Programs", "AzureAuth"))

function Get-CustomLocationsFromPath {
$customLocations = [System.Collections.ArrayList]@()
$azureauthsInPath = (Get-Command -Name azureauth -ErrorAction SilentlyContinue -CommandType Application -All).Source

ForEach($az in $azureauthsInPath) {
$azureauthParent = (Get-Item $az).Directory.FullName
if (!(Is-ChildOfDefaultLocation($azureauthParent))) {
$_ = $customLocations.Add($azureauthParent)
}
}

return $customLocations
}

function Write-WarningForCustomLocations {
# We only warn the user of any custom locations that are found in the PATH.
# Installations in custom locations that are not listed in PATH cannot
# be found and uninstalled.
$customLocations = Get-CustomLocationsFromPath
$customLocationsCount = $customLocations.Count

if ($customLocationsCount -ne 0) {
$warning = "Uninstallation from custom locations is unsupported. Custom locations must be removed manually.
`rFound ${customLocationsCount} potential installations outside of the default location:"
ForEach($location in $customLocations) {
$warning += "`n ${location}"
}
Write-Warning $warning
}
}

# Send WM_SETTINGCHANGE after changing Environment variables.
# Refer to https://gist.github.com/alphp/78fffb6d69e5bb863c76bbfc767effda
function Send-SettingChange {
Add-Type -Namespace Win32 -Name NativeMethods -MemberDefinition @"
[DllImport("user32.dll", SetLastError = true, CharSet = CharSet.Auto)]
public static extern IntPtr SendMessageTimeout(IntPtr hWnd, uint Msg, UIntPtr wParam, string lParam, uint fuFlags, uint uTimeout, out UIntPtr lpdwResult);
"@
$HWND_BROADCAST = [IntPtr] 0xffff;
$WM_SETTINGCHANGE = 0x1a;
$result = [UIntPtr]::Zero

[void] ([Win32.Nativemethods]::SendMessageTimeout($HWND_BROADCAST, $WM_SETTINGCHANGE, [UIntPtr]::Zero, "Environment", 2, 5000, [ref] $result))
}

function Is-ChildOfDefaultLocation {
param ([string]$path)

$parent = (Split-Path $path -Parent)
return ($parent -eq $azureauthDefaultLocation)
}

function Remove-FromPath {
$registryPath = 'Registry::HKEY_CURRENT_USER\Environment'
$currentPath = (Get-ItemProperty -Path $registryPath -Name PATH -ErrorAction SilentlyContinue).Path

# Reconstruct the $PATH without any azureauth directories.
$updatedPath = "";
if (($null) -ne $currentPath) {
$paths = $currentPath.Split(";")
$pathArr = @()
ForEach($path in $paths){
if(!$path.Equals("") -And !(Is-ChildOfDefaultLocation($path))) {
$pathArr += "${path}"
}
elseif (!$path.Equals("")) {
Write-Verbose "Removing PATH entry '${path}'"
}
}
$updatedPath = ($pathArr -join ";") + ";"
}

Set-ItemProperty -Path $registryPath -Name PATH -Value $updatedPath
Send-SettingChange
}

function Remove-InstallationFolder {
param ([string]$directory)

if (Test-Path -Path $directory) {
Write-Verbose "Removing all installations at '${directory}'"
Remove-Item -Force -Recurse $directory
} else {
Write-Verbose "There were no installations found at '${directory}'"
}
}

function Remove-Directories {
Remove-InstallationFolder $azureauthDefaultLocation
}

function Kill-Process {
# Uninstall will fail if there are instances of AzureAuth running.
# We suppress taskkill output here because this is a best effort attempt and we don't want the user to see its output.
# Here, Get-Process is used to first determine whether there is an existing azureauth process. If there is, kill the existing process first.
$ProcessCheck = Get-Process -Name azureauth -ErrorAction SilentlyContinue -ErrorVariable ProcessError
if ($null -ne $ProcessCheck) {
Write-Verbose "Stopping any currently running azureauth instances"
taskkill /f /im azureauth.exe 2>&1 | Out-Null

# After killing the process it is still possible for there there to be locks on the files it was using (including
# its own DLLs). The OS may take an indeterminate amount of time to clean those up, but so far we've observed 1
# second to be enough.
Start-Sleep -Seconds 1
}
}

function Uninstall {
if (![string]::IsNullOrEmpty($Env:AZUREAUTH_INSTALL_DIRECTORY) `
-And $Env:AZUREAUTH_INSTALL_DIRECTORY -ne $azureauthDefaultLocation) {
Write-Warning "Ignoring AZUREAUTH_INSTALL_DIRECTORY environment variable. Uninstallation for custom locations is not supported."
}

Kill-Process

Remove-Directories
Remove-FromPath

Write-WarningForCustomLocations
Write-Output "Uninstalled AzureAuth!"
}

Uninstall

0 comments on commit e3a00aa

Please sign in to comment.