liveBook · Manning

Stop-Process

As explained in Practical Automation with PowerShell: Effective scripting from the console to the cloud

Stop-Process is a PowerShell cmdlet that stops one or more running processes.

Stop-Process stops a running process when graceful completion is no longer acceptable or an executable exceeds its allowed runtime. Use it as a controlled fallback inside automation rather than as an unconditional first step. section 6.1.2 section 9.4.2

Reliable process termination follows an explicit control flow:

Timed executable termination

Start an executable with -PassThru, poll its HasExited property, and measure runtime with a stopwatch. When the limit is exceeded, pipe the process to Stop-Process -Force and throw an error indicating that execution failed. section 9.4.2

$RuntimeSeconds = 2
$ping = Start-Process -FilePath 'ping.exe' -ArgumentList 
 'google.com','-n 10' -PassThru
$timer =  [system.diagnostics.stopwatch]::StartNew()
while($ping.HasExited -eq $false){
    if($timer.Elapsed.TotalSeconds -gt $RuntimeSeconds){
        $ping | Stop-Process -Force
        throw "The application did not exit in time"
    }
}
$timer.Elapsed.TotalSeconds
$timer.Stop()

Shows the complete timeout pattern: Start-Process -PassThru, HasExited polling, stopwatch measurement, forced termination, and failure reporting. section 9.4.2

Listing 6.3 Disable-WindowsService
Function Disable-WindowsService {
    [CmdletBinding()]
    [OutputType([object])]
    param(
        [Parameter(Mandatory = $true)]
        [string[]]$Services,
        [Parameter(Mandatory = $true)]
        [int]$HardKillSeconds,
        [Parameter(Mandatory = $true)]
        [int]$SecondsToWait
    )
 
    [System.Collections.Generic.List[PSObject]] $ServiceStatus = @()
    foreach ($Name in $Services) {
        $ServiceStatus.Add([pscustomobject]@{                         #1
                Service  = $Name
                HardKill = $false
                Status   = $null
                Startup  = $null
            })
        try {
            $Get = @{                                                 #2
                Name        = $Name
                ErrorAction = 'Stop'
            }
            $Service = Get-Service @Get
            $Set = @{
                InputObject = $Service
                StartupType = 'Disabled'
            }
            Set-Service @Set
            $Stop = @{
                InputObject = $Service
                Force       = $true
                NoWait      = $true
                ErrorAction = 'SilentlyContinue'
            }
            Stop-Service @Stop
            Get-Service -Name $Name | ForEach-Object {
                $ServiceStatus[-1].Status = $_.Status.ToString()
                $ServiceStatus[-1].Startup = $_.StartType.ToString()
            }
        }
        catch {
            $msg = 'NoServiceFoundForGivenName,Microsoft.PowerShell' +
                '.Commands.GetServiceCommand'
            if ($_.FullyQualifiedErrorId -eq $msg) {
                $ServiceStatus[-1].Status = 'Stopped'                 #3
            }
            else {
                Write-Error $_
            }
        }
    }
 
    $timer = [system.diagnostics.stopwatch]::StartNew()
    do {                                                              #4
        $ServiceStatus | Where-Object { $_.Status -ne 'Stopped' } |
        ForEach-Object {
            $_.Status = (Get-Service $_.Service).Status.ToString()
 
            if ($_.HardKill -eq $false -and                           #5
                $timer.Elapsed.TotalSeconds -gt $HardKillSeconds) {
                Write-Verbose "Attempting hard kill on $($_.Service)"
                $query = "SELECT * from Win32_Service WHERE name = '{0}'"
                $query = $query -f $_.Service
                $svcProcess = Get-CimInstance -Query $query
                $Process = @{
                    Id          = $svcProcess.ProcessId
                    Force       = $true
                    ErrorAction = 'SilentlyContinue'
                }
                Stop-Process @Process
                $_.HardKill = $true
            }
        }
        $Running = $ServiceStatus | Where-Object { $_.Status -ne 'Stopped' }
    } while ( $Running -and $timer.Elapsed.TotalSeconds -lt $SecondsToWait )
    $ServiceStatus |                                                 #6
        Where-Object { $_.Status -ne 'Stopped' } |
        ForEach-Object { $_.Status = 'Reboot Required' }
 
    $ServiceStatus                                                   #7
}

Places forced process termination inside a reusable Disable-WindowsService function that tracks service status and prevents repeated hard-kill attempts. section 6.1.2

How Practical Automation with PowerShell: Effective scripting from the console to the cloud covers it

How deep it goes
Explains placement within wait loops, timers, process-state checks, error reporting, and one-attempt state tracking.
Examples
Demonstrates stopping stalled services and terminating ping.exe after a two-second runtime limit.
What it assumes
Assumes familiarity with PowerShell processes, services, loops, and error handling while demonstrating process monitoring from execution through timeout.
What you can do after
Diagnose and control hung automation by enforcing runtime limits, killing overdue processes, and reporting failed completion.
How it connects
Connects Stop-Process with Windows services, Start-Process, Get-CimInstance, HasExited, while loops, timers, and error handling.

Related concepts

This explainer was generated by Manning's knowledge graph from the text of Practical Automation with PowerShell: Effective scripting from the console to the cloud. The section links point to the parts of the book it draws on.