mirror of
https://github.com/sbroenne/mcp-server-excel.git
synced 2026-09-19 07:53:08 +08:00
748a33b7c9
* fix: preserve sessions during stale cleanup Wait for the tracked daemon to finish graceful shutdown even when its reply is lost, so pre-build cleanup cannot interrupt session auto-save. Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com> * fix: await tracked Excel shutdown Treat graceful cleanup as complete only after the exact daemon generation and its tracked Excel processes exit, while retaining the existing bounded forced fallback. Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com> Copilot-Session: b07d5dc3-38d8-4d20-9f07-122e079dd612 * fix: unify exact process exit handling Observe exact process identities before requesting termination, share the bounded exit window across session and pipe cleanup, keep daemon readiness probes within their existing deadline, and wait deterministically for verified MCPB staging locks to release. Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com> Copilot-Session: b07d5dc3-38d8-4d20-9f07-122e079dd612 * fix: stabilize MCPB staging cleanup Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com> Copilot-Session: 9b9eefe6-dd82-44e6-abdc-98202899cf32 --------- Co-authored-by: Stefan Broenner <stbrnner@microsoft.com> Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com> Copilot-Session: b07d5dc3-38d8-4d20-9f07-122e079dd612 Copilot-Session: 9b9eefe6-dd82-44e6-abdc-98202899cf32
179 lines
6.8 KiB
PowerShell
179 lines
6.8 KiB
PowerShell
<#
|
|
.SYNOPSIS
|
|
Stops the ExcelMCP CLI service and Excel processes owned by one CLI pipe.
|
|
.DESCRIPTION
|
|
Invokes the CLI-owned service stop path for EXCELMCP_CLI_PIPE (or the
|
|
default user pipe when no override is set). The CLI validates tracked
|
|
process start times before stopping anything.
|
|
|
|
If an existing CLI is older than the ownership lifecycle sources, a
|
|
current cleanup client is built in an isolated temporary output first.
|
|
If no CLI binary exists yet, the script safely does nothing. It never
|
|
scans for or stops unrelated Excel or service processes.
|
|
.NOTES
|
|
Called once from Directory.Build.props before the CLI project builds.
|
|
Safe to run when no processes are running (silently succeeds).
|
|
#>
|
|
|
|
param(
|
|
[string]$PipeName = $env:EXCELMCP_CLI_PIPE,
|
|
[switch]$Verbose
|
|
)
|
|
|
|
$ErrorActionPreference = 'Stop'
|
|
|
|
function Write-Status($message) {
|
|
if ($Verbose) {
|
|
Write-Host " [pre-build] $message" -ForegroundColor DarkGray
|
|
}
|
|
}
|
|
|
|
function Remove-StagingClient([string]$path) {
|
|
if ([string]::IsNullOrWhiteSpace($path) -or -not (Test-Path -LiteralPath $path)) {
|
|
return
|
|
}
|
|
|
|
try {
|
|
Remove-Item -LiteralPath $path -Recurse -Force
|
|
}
|
|
catch {
|
|
Write-Host " Isolated owned-cleanup client could not be removed: $($_.Exception.Message)" -ForegroundColor Yellow
|
|
}
|
|
}
|
|
|
|
$repoRoot = Split-Path -Parent $PSScriptRoot
|
|
$cliPaths = @(
|
|
(Join-Path $repoRoot 'src\ExcelMcp.CLI\bin\Release\net10.0-windows\excelcli.exe'),
|
|
(Join-Path $repoRoot 'src\ExcelMcp.CLI\bin\Debug\net10.0-windows\excelcli.exe')
|
|
)
|
|
$safetyInputs = @(
|
|
$PSCommandPath,
|
|
(Join-Path $repoRoot 'src\ExcelMcp.CLI\Commands\ServiceCommands.cs'),
|
|
(Join-Path $repoRoot 'src\ExcelMcp.CLI\Infrastructure\DaemonAutoStart.cs'),
|
|
(Join-Path $repoRoot 'src\ExcelMcp.CLI\Infrastructure\DaemonPipeIdentity.cs'),
|
|
(Join-Path $repoRoot 'src\ExcelMcp.CLI\Infrastructure\DaemonProcessTracker.cs'),
|
|
(Join-Path $repoRoot 'src\ExcelMcp.CLI\Infrastructure\DaemonStartupLock.cs'),
|
|
(Join-Path $repoRoot 'src\ExcelMcp.CLI\Infrastructure\DaemonTrackingJson.cs'),
|
|
(Join-Path $repoRoot 'src\ExcelMcp.CLI\Infrastructure\OwnedProcessCleanup.cs'),
|
|
(Join-Path $repoRoot 'src\ExcelMcp.CLI\Infrastructure\PreBuildProcessCleanup.cs'),
|
|
(Join-Path $repoRoot 'src\ExcelMcp.Cleanup\ExcelMcp.Cleanup.csproj'),
|
|
(Join-Path $repoRoot 'src\ExcelMcp.Cleanup\Program.cs'),
|
|
(Join-Path $repoRoot 'src\ExcelMcp.Cleanup\ParameterTransforms.cs'),
|
|
(Join-Path $repoRoot 'src\ExcelMcp.Service\ServiceClient.cs'),
|
|
(Join-Path $repoRoot 'src\ExcelMcp.Service\ServiceProtocol.cs'),
|
|
(Join-Path $repoRoot 'src\ExcelMcp.Service\Rpc\IExcelDaemonRpc.cs'),
|
|
(Join-Path $repoRoot 'src\ExcelMcp.ComInterop\ServiceClient\ServiceProtocol.cs'),
|
|
(Join-Path $repoRoot 'src\ExcelMcp.CLI\Program.cs'),
|
|
(Join-Path $repoRoot 'src\ExcelMcp.ComInterop\Session\ExcelBatch.cs'),
|
|
(Join-Path $repoRoot 'src\ExcelMcp.ComInterop\Session\ExcelProcessIdentity.cs'),
|
|
(Join-Path $repoRoot 'src\ExcelMcp.ComInterop\Session\OwnedProcessGuard.cs'),
|
|
(Join-Path $repoRoot 'src\ExcelMcp.ComInterop\Session\ProcessTerminationPolicy.cs'),
|
|
(Join-Path $repoRoot 'src\ExcelMcp.ComInterop\Session\SessionManager.cs'),
|
|
(Join-Path $repoRoot 'src\ExcelMcp.Service\ServiceSecurity.cs')
|
|
)
|
|
$latestSafetyInput = $safetyInputs |
|
|
Where-Object { Test-Path $_ } |
|
|
ForEach-Object { (Get-Item $_).LastWriteTimeUtc } |
|
|
Sort-Object -Descending |
|
|
Select-Object -First 1
|
|
$availableClis = @($cliPaths |
|
|
Where-Object { Test-Path $_ } |
|
|
ForEach-Object { Get-Item $_ } |
|
|
Sort-Object LastWriteTimeUtc -Descending |
|
|
Select-Object -First 1)
|
|
$excelcli = $availableClis |
|
|
Where-Object { $_.LastWriteTimeUtc -ge $latestSafetyInput } |
|
|
Select-Object -First 1
|
|
$stagingRoot = $null
|
|
$useCleanupBootstrap = $false
|
|
|
|
if (-not $excelcli) {
|
|
if ($availableClis.Count -eq 0) {
|
|
Write-Status 'excelcli is missing; owned cleanup skipped safely'
|
|
exit 0
|
|
}
|
|
|
|
$stagingRoot = Join-Path ([System.IO.Path]::GetTempPath()) "excelmcp-cleanup-$PID-$([Guid]::NewGuid().ToString('N'))"
|
|
$cleanupProject = Join-Path $repoRoot 'src\ExcelMcp.Cleanup\ExcelMcp.Cleanup.csproj'
|
|
$stagedCliPath = Join-Path $stagingRoot 'bin\ExcelMcp.Cleanup\Release\net10.0-windows\excelmcp-cleanup.exe'
|
|
Write-Status "Existing CLI is older than the cleanup sources; building isolated cleanup client in $stagingRoot"
|
|
|
|
try {
|
|
$buildOutput = & dotnet build $cleanupProject `
|
|
--configuration Release `
|
|
-p:ExcelMcpCleanupRoot=$stagingRoot `
|
|
-p:ExcelMcpSkipCleanup=true `
|
|
-p:NuGetAudit=false `
|
|
-maxcpucount:1 `
|
|
-nodeReuse:false `
|
|
--verbosity quiet 2>&1
|
|
$buildExitCode = $LASTEXITCODE
|
|
}
|
|
catch {
|
|
Write-Host " Isolated owned-cleanup client could not be built: $($_.Exception.Message). No process sweep was attempted." -ForegroundColor Yellow
|
|
Remove-StagingClient $stagingRoot
|
|
exit 1
|
|
}
|
|
|
|
if ($buildExitCode -ne 0 -or -not (Test-Path $stagedCliPath)) {
|
|
Write-Host " Isolated owned-cleanup client build failed with exit code $buildExitCode. No process sweep was attempted." -ForegroundColor Yellow
|
|
if ($buildOutput) {
|
|
Write-Status ($buildOutput | Out-String).Trim()
|
|
}
|
|
Remove-StagingClient $stagingRoot
|
|
exit $(if ($buildExitCode -ne 0) { $buildExitCode } else { 1 })
|
|
}
|
|
|
|
$excelcli = Get-Item $stagedCliPath
|
|
$useCleanupBootstrap = $true
|
|
}
|
|
|
|
$previousPipeName = $env:EXCELMCP_CLI_PIPE
|
|
try {
|
|
if ([string]::IsNullOrWhiteSpace($PipeName)) {
|
|
Remove-Item Env:EXCELMCP_CLI_PIPE -ErrorAction SilentlyContinue
|
|
Write-Status 'Using the default CLI pipe'
|
|
}
|
|
else {
|
|
$env:EXCELMCP_CLI_PIPE = $PipeName
|
|
Write-Status "Using CLI pipe: $PipeName"
|
|
}
|
|
|
|
Write-Status "Using CLI: $($excelcli.FullName)"
|
|
try {
|
|
if ($useCleanupBootstrap) {
|
|
$output = & $excelcli.FullName 2>&1
|
|
}
|
|
else {
|
|
$output = & $excelcli.FullName service stop --quiet 2>&1
|
|
}
|
|
$exitCode = $LASTEXITCODE
|
|
}
|
|
catch {
|
|
Write-Host " Owned CLI cleanup could not start: $($_.Exception.Message). No process sweep was attempted." -ForegroundColor Yellow
|
|
exit 1
|
|
}
|
|
|
|
if ($exitCode -ne 0) {
|
|
Write-Host " Owned CLI cleanup failed with exit code $exitCode. No process sweep was attempted." -ForegroundColor Yellow
|
|
if ($output) {
|
|
[Console]::Error.WriteLine(($output | Out-String).Trim())
|
|
}
|
|
exit $exitCode
|
|
}
|
|
|
|
Write-Status 'Owned CLI cleanup completed'
|
|
}
|
|
finally {
|
|
if ($null -eq $previousPipeName) {
|
|
Remove-Item Env:EXCELMCP_CLI_PIPE -ErrorAction SilentlyContinue
|
|
}
|
|
else {
|
|
$env:EXCELMCP_CLI_PIPE = $previousPipeName
|
|
}
|
|
|
|
Remove-StagingClient $stagingRoot
|
|
}
|
|
|
|
exit 0
|