Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Start several process with Start-Process and then kill them all with Stop-Process

Tags:

powershell

We're using the following script to start five processes. Each of them run in a command prompt. We want to be able to stop all the processes afterward. How can we do that?

RunDemo.ps1

$global:p = @();

function global:kill-demo {
    $global:p | % {
        Write-Host "Killing $($_.ProcessName)"
        kill $_
        Write-Host "$($_.ProcessName) dead"
    }
}

# Authorization Server
Push-Location "./AuthorizationServer"
$global:p += Start-Process dotnet -ArgumentList "run" -PassThru
Pop-Location

# Aurelia Application
Push-Location "./AureliaApp"
$global:p += Start-Process npm -ArgumentList "run start" -PassThru
Pop-Location

# Oidc Client JS
Push-Location "./OidcClientJs"
$global:p += Start-Process npm -ArgumentList "run start" -PassThru
Pop-Location

# Resource Server 01
Push-Location "./ResourceServer01"
$global:p += Start-Process dotnet -ArgumentList "run" -PassThru
Pop-Location

# Resource Server 02
Push-Location "./ResourceServer02"
$global:p += Start-Process dotnet -ArgumentList "run" -PassThru
Pop-Location

Ideally, we would like to be able to open PowerShell and do the following. The output indicates that PowerShell is finding the processes and stopping them, though the command prompts all remain open.

PS> .\RunDemo.ps1
PS> kill-demo
Killing dotnet
dotnet dead
Killing cmd
cmd dead
Killing cmd
cmd dead
Killing dotnet
dotnet dead
Killing dotnet
dotnet dead

The script does work when we start simpler processes like notepad.exe or node.exe without running a web application.

like image 609
Shaun Luttin Avatar asked Oct 25 '25 18:10

Shaun Luttin


2 Answers

You can use Get-Help to discover many capabilities of PowerShell commands. In this case, get-help start-process -full, will describe -PassThru which does:

-PassThru

Returns a process object for each process that the cmdlet started. By default, this cmdlet does not generate any output.

You can use it something like so, and in your case, save the IDs in an array or something similar.

$x = Start-Process notepad.exe -PassThru
# wait some time, etc.
Stop-Process -Id $x.Id
like image 160
Kory Gill Avatar answered Oct 28 '25 06:10

Kory Gill


The following ended up working to kill the processes and all their child processes.

$global:p = @();

function global:Find-ChildProcess {
    param($ID = $PID)

    $result = Get-CimInstance win32_process |
        Where-Object { $_.ParentProcessId -eq $ID }
    Select-Object -Property ProcessId

    $result |
        Where-Object { $null -ne $_.ProcessId } |
        ForEach-Object {
        Find-ChildProcess -id $_.ProcessId
    }
}

function global:Stop-Demo {
    $global:p |
        ForEach-Object { 
        Stop-Process -Id $_.Id;
        Find-ChildProcess -ID $_.Id;
    } |
        ForEach-Object { 
        Stop-Process -id 
        $_.ProcessId 
    }
}

Push-Location "./AuthorizationServer"
$global:p += Start-Process dotnet -ArgumentList "run" -PassThru
Pop-Location

Push-Location "./AureliaApp"
$global:p += Start-Process npm -ArgumentList "run start" -PassThru
Pop-Location

Push-Location "./OidcClientJs"
$global:p += Start-Process npm -ArgumentList "run start" -PassThru
Pop-Location

Push-Location "./ResourceServer01"
$global:p += Start-Process dotnet -ArgumentList "run" -PassThru
Pop-Location

Push-Location "./ResourceServer02"
$global:p += Start-Process dotnet -ArgumentList "run" -PassThru
Pop-Location
like image 26
Shaun Luttin Avatar answered Oct 28 '25 08:10

Shaun Luttin