ps/Modules/Alkami.PowerShell.Services/Public/Uninstall-AlkamiService.ps1
2023-05-30 22:51:22 -07:00

108 lines
5.6 KiB
PowerShell

function Uninstall-AlkamiService {
<#
.SYNOPSIS
Uninstalls an Alkami Windows Service (not a legacy microservice)
.DESCRIPTION
Uninstalls an Alkami Windows Service (not a legacy microservice)
Legacy Microservices are considered to be Microservices that implement Alkami.Services.Subscriptions.ParticipatingService.DistributedServiceBase or derivatives.
This installer does not remove k8s or Lambdas or anything that is not a Windows Service.
This installer is intended to be used in conjunction with new practices from the Vanguard team
.PARAMETER ServicePath
[string] The path to the service folder or service file. If to a folder, assumes that the file matches the path name.
Ex: C:\ProgramData\chocolatey\lib\Alkami.Services.Subscriptions.Host as a param would then find the file that matches Alkami.Services.Subscriptions.Host.exe under this path
.EXAMPLE
Uninstall-AlkamiService C:\ProgramData\chocolatey\lib\Alkami.Services.Subscriptions.Host
#>
[CmdletBinding()]
Param(
[Parameter(Mandatory = $true, Position = 0)]
[Alias("Path")]
[string]$ServicePath
)
$logLead = (Get-LogLeadName)
$ServicePath = (Resolve-Path $ServicePath)
if (!(Test-Path $ServicePath)) {
Write-Warning "$logLead : Path passed in does not represent a valid path: [$ServicePath]. Can not uninstall something which does not exist."
return
}
$parentPath = Split-Path -Path $ServicePath -Parent
$serviceName = ""
if (-not (Get-Item -Path $servicePath).PSIsContainer) {
$serviceName = Split-Path -Path $ServicePath -Leaf
if ($serviceName.Substring($serviceName.Length - 4) -eq '.exe') {
$serviceName = $serviceName.Substring(0, $serviceName.Length - 4)
}
}
$serviceCandidates = (Get-ServiceInfoByCIMFragment -Fragment $ServicePath -ForceExact)
# If we didn't find anything by the AssemblyInfo, let's double check the parent path
if (Test-IsCollectionNullOrEmpty $serviceCandidates) {
if (Test-StringIsNullOrWhiteSpace -Value $serviceName) {
$serviceCandidates = @(Get-ServiceInfoByCIMFragment -Fragment $parentPath)
if ($serviceCandidates.Count -gt 3) {
# 3 chosen because you could end up with 2 services in one folder, and that's not-great, but at 3 we clearly have a bad search
# This comment is for Cole to know that we just flat out couldn't get there from here
Write-Host "$logLead : Bad path given for trying to determine the root of the service to remove it"
}
if (!(Test-IsCollectionNullOrEmpty $serviceCandidates)) {
# This comment is for Cole to know that there were only 2, or more than 2, based on the prior output
# We will write out more details at the end
Write-Warning "$logLead : Could not find services under [$ServicePath] but found some under [$parentPath]"
}
} else {
$serviceCandidates = @(Get-ServiceInfoByCIMFragment -Fragment $serviceName -ForceExact)
}
}
if (Test-IsCollectionNullOrEmpty $serviceCandidates) {
Write-Host "$logLead : No services found registered under [$ServicePath] or [$parentPath] or with [$serviceName]"
return
}
$exactPathMatch = @($serviceCandidates.Where({
# Manifest based installers allow for three paths
(Join-Path -Path $_.ParentFolder -ChildPath '\') -eq (Join-Path -Path $ServicePath -ChildPath 'lib\') -or
(Join-Path -Path $_.ParentFolder -ChildPath '\') -eq (Join-Path -Path $ServicePath -ChildPath 'app\') -or
(Join-Path -Path $_.ParentFolder -ChildPath '\') -eq (Join-Path -Path $ServicePath -ChildPath 'tools\') -or
(Join-Path -Path $_.ParentFolder -ChildPath '\') -eq (Join-Path -Path $ServicePath -ChildPath '\')
}))
if ($exactPathMatch.Count -eq 1) {
$serviceCandidateName = $exactPathMatch.Name
$serviceCandidatePath = $exactPathMatch.Path
Write-Host "$logLead : Uninstalling existing service [$serviceCandidateName] at [$serviceCandidatePath] for [$ServicePath]"
# Ensure it isn't running first
Stop-AlkamiService $serviceCandidateName
Write-Verbose "$logLead : Removing [$serviceCandidateName] via sc.exe"
Invoke-SCExe @("delete", $serviceCandidateName)
# Give Windows time to breathe. This might could be shorter, who knows. 150 is a magic number from thin air.
Start-Sleep -Milliseconds 150
if ($null -ne (Get-Service -Name $serviceCandidateName -ErrorAction Ignore)) {
# How did this happen? sc.exe is a hot-knife.
throw "$logLead : Tried to uninstall [$serviceCandidateName] from [$serviceCandidatePath] but it seems to still be present"
}
} else {
# If it couldn't do the thing, Cole needs to investigate, because the assumptions are bad
foreach($candidate in $serviceCandidates) {
Write-Warning "$logLead : TOO MANY SERVICES FOUND FOR [$ServicePath] : Found service [$($candidate.Name)] at [$($candidate.Path)]"
}
Write-Warning "$logLead : ---------------------"
Write-Warning "$logLead : You probably have an inconsistent package state. Please reinstall this service, then re-uninstall it."
Write-Warning "$logLead : It is worth slacking/paging out to Cole on this to see why we ended up in this weird state, because this was unexpected"
Write-Warning "$logLead : ---------------------"
throw "$logLead : More than 1 service candidates found in this location. Are you sure you wanna do this? Did you mean to specify a deeper path?"
}
}