Public/Remove-FirebirdService.ps1
|
function Remove-FirebirdService { <# .SYNOPSIS Removes a Firebird system service. .DESCRIPTION Stops and unregisters a Firebird service from the system. On Windows, uses instsvc.exe to remove the Windows service. On Linux, stops, disables, and removes the systemd unit file. .PARAMETER Name The name of the service to remove. Accepts pipeline input from Get-FirebirdService. .PARAMETER Environment A Firebird environment whose default service name will be derived and removed. Cannot be used together with -Name. .PARAMETER Force Suppresses confirmation prompts. .EXAMPLE Remove-FirebirdService -Name 'Firebird-5' .EXAMPLE Remove-FirebirdService -Environment $fb5 .EXAMPLE Get-FirebirdService | Remove-FirebirdService #> [CmdletBinding(SupportsShouldProcess, DefaultParameterSetName = 'ByName')] param( [Parameter(Mandatory, Position = 0, ValueFromPipelineByPropertyName, ParameterSetName = 'ByName')] [string]$Name, [Parameter(Mandatory, ParameterSetName = 'ByEnvironment')] [FirebirdEnvironment]$Environment, [switch]$Force ) process { if ($PSCmdlet.ParameterSetName -eq 'ByEnvironment') { $Name = "Firebird-$($Environment.Version.Major)" Write-VerboseMark -Message "Derived service name from environment: $Name" } if ($IsWindows) { Write-VerboseMark -Message "Removing Windows service: $Name" $serviceName = "FirebirdServer$Name" # Get-Service uses EnumServicesStatus which returns services regardless # of their "marked for deletion" state — more reliable than sc.exe query. $svc = Get-Service -Name $serviceName -ErrorAction SilentlyContinue if (-not $svc) { throw "No Firebird service named '$serviceName' was found." } if ($Force -or $PSCmdlet.ShouldProcess($Name, 'Remove Windows service')) { # Stop first (ignore errors if already stopped) Write-VerboseMark -Message "Stopping service: Stop-Service '$serviceName'" Stop-Service -Name $serviceName -Force -ErrorAction SilentlyContinue # Delete via sc.exe — avoids Remove-Service wrapper caching that can # leave handles open and prevent immediate SCM cleanup. Write-VerboseMark -Message "Deleting service via sc.exe delete '$serviceName'" $deleteOutput = & sc.exe delete $serviceName 2>&1 # Accept 1072 (ERROR_SERVICE_MARKED_FOR_DELETE) — service is going away if ($LASTEXITCODE -notin @(0, 1072)) { if ($LASTEXITCODE -eq 1060) { throw "No Firebird service named '$serviceName' was found." } throw "Failed to remove Firebird service '$serviceName': $($deleteOutput -join ' ')" } # Wait until the service disappears from EnumServicesStatus so that # re-creating the same name is safe immediately after this call returns. $waitEnd = [DateTimeOffset]::Now.AddSeconds(30) while ((Get-Service -Name $serviceName -ErrorAction SilentlyContinue) -and [DateTimeOffset]::Now -lt $waitEnd) { Write-VerboseMark -Message "Waiting for SCM to fully remove '$serviceName'..." Start-Sleep -Milliseconds 300 } Write-VerboseMark -Message "Service '$serviceName' fully removed." } } elseif ($IsLinux) { Write-VerboseMark -Message "Removing systemd service: $Name" $unitName = $Name.ToLower() $unitPath = "/etc/systemd/system/$($unitName).service" if (-not (Test-Path $unitPath)) { throw "No systemd unit file found at '$unitPath'." } if ($Force -or $PSCmdlet.ShouldProcess($Name, 'Remove systemd service')) { # Stop the service (ignore errors if already stopped) Write-VerboseMark -Message "Stopping service: systemctl stop $unitName" try { Invoke-ExternalCommand { & systemctl stop $unitName } } catch { Write-VerboseMark -Message "Service stop returned an error (may already be stopped): $($_.Exception.Message)" } Write-VerboseMark -Message "Disabling service: systemctl disable $unitName" try { Invoke-ExternalCommand { & systemctl disable $unitName } } catch { Write-VerboseMark -Message "Service disable returned an error: $($_.Exception.Message)" } Write-VerboseMark -Message "Removing unit file: $unitPath" Remove-Item -Path $unitPath -Force Write-VerboseMark -Message 'Running: systemctl daemon-reload' Invoke-ExternalCommand { & systemctl daemon-reload } ` -ErrorMessage 'Failed to reload systemd daemon' } } else { throw 'Unsupported platform. Only Windows and Linux are supported.' } } } |