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?" } }