From af626c9ff6fafc2a57324e3d41f7c3bc6f29671f Mon Sep 17 00:00:00 2001 From: Andreas Jordan Date: Sat, 12 Sep 2026 15:25:40 +0200 Subject: [PATCH] Stop-DbaExternalProcess - Stop eating the caller loop when the process cannot be stopped Stop-Function -Continue runs PowerShell's continue. No loop encloses this call site inside the command, so the continue unwound out of the command and consumed an iteration of whatever loop the caller runs in: a user's foreach silently skipped an element, and Pester's runner corrupted. The escape only bites the non-EnableException path; with EnableException Stop-Function throws before it gets there. Part of #10638 (do Stop-DbaExternalProcess) Co-Authored-By: Claude Fable 5.1 --- public/Stop-DbaExternalProcess.ps1 | 4 +++- tests/Stop-DbaExternalProcess.Tests.ps1 | 17 ++++++++++++++++- 2 files changed, 19 insertions(+), 2 deletions(-) diff --git a/public/Stop-DbaExternalProcess.ps1 b/public/Stop-DbaExternalProcess.ps1 index a14dd22d3b50..5f6acc60bd4a 100644 --- a/public/Stop-DbaExternalProcess.ps1 +++ b/public/Stop-DbaExternalProcess.ps1 @@ -95,7 +95,9 @@ function Stop-DbaExternalProcess { } } } catch { - Stop-Function -Message "Error killing $ProcessId on $ComputerName" -ErrorRecord $_ -Continue + # No -Continue here: this block has no enclosing loop, so the continue would escape the command + # and eat an iteration of whatever loop the caller runs in (#10638). + Stop-Function -Message "Error killing $ProcessId on $ComputerName" -ErrorRecord $_ } } } \ No newline at end of file diff --git a/tests/Stop-DbaExternalProcess.Tests.ps1 b/tests/Stop-DbaExternalProcess.Tests.ps1 index d9240b8d26c0..a992abf31a38 100644 --- a/tests/Stop-DbaExternalProcess.Tests.ps1 +++ b/tests/Stop-DbaExternalProcess.Tests.ps1 @@ -92,4 +92,19 @@ Describe $CommandName -Tag IntegrationTests { $results.Status | Should -Be "Stopped" } } -} \ No newline at end of file + + Context "When the process does not exist" { + It "Warns without eating an iteration of the caller's loop" { + # The catch used to run Stop-Function -Continue at the end of the process block, where no loop + # encloses it - the continue escaped the command and consumed an iteration of this very loop, so + # the counter stayed at zero (#10638). Stop-Process on a process id that does not exist throws. + $loopCount = 0 + foreach ($i in 1..3) { + $null = Stop-DbaExternalProcess -ComputerName localhost -ProcessId 2147483647 -WarningAction SilentlyContinue -Confirm:$false + $loopCount++ + } + $loopCount | Should -Be 3 + ($WarnVar -join " ") | Should -BeLike "*Error killing 2147483647*" + } + } +}