Chapter 12Lesson 01~155 minutes

Processes, Child Processes, Start-Process, and Process Automation

Manage process automation safely across platforms: inspect Process objects, launch child processes, capture exit behavior, and preview state changes.

Learning objectives

  • Explain processes, PIDs, child-process concepts, and permission boundaries.
  • Inspect Process objects with Get-Process.
  • Choose between direct native invocation and Start-Process.
  • Control arguments, environment, working directory, waiting, and redirection.
  • Use WhatIf for process-control operations that support ShouldProcess.
  • Launch and monitor a harmless child process in a disposable lab.

1. A process is a running program with identity and state

A process is an operating-system execution container for a running program. It has a process identifier (PID), memory, CPU time, environment, open resources, security context, and lifecycle state. A program file such as pwsh can have many process instances at the same time.

PowerShell exposes processes as System.Diagnostics.Process objects. That means you should inspect properties and methods rather than scraping the human-formatted table.

$me = Get-Process -Id $PID
$me | Select-Object Id, ProcessName, StartTime, CPU, WorkingSet64
$me.GetType().FullName
$me | Get-Member -MemberType Property | Select-Object -First 12

2. PIDs, parent/child relationships, and permissions

A PID identifies one process while it exists. A child process is a process launched by another process, its parent. Parent/child information is an operating-system concept, but the portable PowerShell Process object does not give you a universal parent-PID property. Later in this chapter, Windows CIM can expose ParentProcessId; Unix-like systems also provide native process inspection tools.

Process visibility is also permission-sensitive. You can usually see basic information for many processes, but details such as executable paths, loaded modules, or control operations may require ownership or elevated privileges. Treat access failures as evidence, not as a reason to disable errors globally.

3. Inspect before you control

Get-Process is cross-platform and read-only. Start from narrow queries whenever possible. Avoid piping an unreviewed wildcard directly into Stop-Process.

# Current PowerShell host
Get-Process -Id $PID | Select-Object Id,ProcessName,StartTime,CPU

# A bounded view of local processes
Get-Process |
    Sort-Object WorkingSet64 -Descending |
    Select-Object -First 8 Id,ProcessName,@{Name='WorkingSetMB';Expression={[math]::Round($_.WorkingSet64/1MB,1)}}

4. Stop-Process is state-changing: preview first

Stop-Process supports -WhatIf and -Confirm. A production-safe sequence is: identify exactly one intended target, inspect it, preview the action, and only then perform the stop when your runbook authorizes it. Never use critical operating-system processes as practice targets.

$target = Get-Process -Id $PID
# Never execute the next line against the current shell; it is only a preview.
$target | Stop-Process -WhatIf

# For a disposable process that your lab created, a real stop can be explicit:
# $child | Stop-Process -Confirm

5. Direct native invocation is usually the best CLI boundary

When a native command is part of a pipeline or CI step, invoking it directly with the call operator & is usually clearest. PowerShell receives the program's standard output, standard error, and exit code through the native-command boundary covered in Chapter 10.

$pwsh = (Get-Command pwsh -CommandType Application).Source
& $pwsh -NoProfile -Command 'Write-Output "child-output"; exit 0'
$exitCode = $LASTEXITCODE
"native exit code = $exitCode"

6. Use Start-Process when process launch policy matters

Start-Process is useful when you need a distinct working directory, environment override, redirection files, window/credential behavior on Windows, asynchronous launch, or a returned process object. It is not automatically “better” than direct invocation.

NeedUsually prefer
Consume command output in the current pipelineDirect invocation with &
Check a CLI exit code immediatelyDirect invocation + $LASTEXITCODE
Launch asynchronously and keep a Process objectStart-Process -PassThru
Redirect child stdout/stderr to filesStart-Process -RedirectStandardOutput/-RedirectStandardError
Set child working directory/environmentStart-Process
Windows RunAs/window behaviorStart-Process with Windows-specific parameters

7. Arguments, working directory, environment, waiting, and exit status

By default, Start-Process returns immediately and emits no object. -PassThru returns a Process object; -Wait waits for the process tree to finish. The -Environment parameter, available in PowerShell 7.4+, overrides environment variables for the child process.

-ArgumentList ultimately forms a command-line string. Quoting becomes especially important when values contain spaces or quotes. Prefer simple, validated arguments and test the exact native interface you automate.

$pwsh = (Get-Command pwsh -CommandType Application).Source
$lab = Join-Path ([System.IO.Path]::GetTempPath()) 'ps-ch12-process'
New-Item -ItemType Directory -Path $lab -Force | Out-Null
$stdout = Join-Path $lab 'stdout.txt'
$stderr = Join-Path $lab 'stderr.txt'

$child = Start-Process -FilePath $pwsh `
    -ArgumentList '-NoProfile -Command "[Console]::Out.WriteLine($env:CH12_MARKER); Start-Sleep -Seconds 2; exit 0"' `
    -WorkingDirectory $lab `
    -Environment @{ CH12_MARKER = 'child-ok' } `
    -RedirectStandardOutput $stdout `
    -RedirectStandardError $stderr `
    -PassThru -Wait

[pscustomobject]@{
    Id       = $child.Id
    ExitCode = $child.ExitCode
    StdOut   = (Get-Content -Raw -LiteralPath $stdout).Trim()
    StdErr   = (Get-Content -Raw -LiteralPath $stderr).Trim()
}

8. Start-Process can also be previewed

Current Start-Process supports -WhatIf. That is useful when launch itself is consequential—for example, starting an installer or administrative tool. A preview does not validate that the executable would succeed; it only verifies the intended PowerShell action contract.

$pwsh = (Get-Command pwsh -CommandType Application).Source
Start-Process -FilePath $pwsh -ArgumentList '-NoProfile -Command "exit 0"' -WhatIf

9. Cross-platform behavior is not identical

Process discovery is broadly cross-platform, but launch/wait details differ. On Windows, Start-Process can open an independent window and supports Windows-only concepts such as -Verb RunAs and -WindowStyle. On Unix-like systems, a process started with Start-Process remains attached to the launching shell unless you deliberately use an operating-system detachment mechanism such as nohup. Microsoft also documents Wait-Process as not working on Linux or macOS, so portable code can wait through the returned System.Diagnostics.Process object instead.

Write automation around the behavior you actually require rather than assuming Windows process semantics apply everywhere.

10. Lab: launch, monitor, verify, and clean up a harmless child process

This lab starts a short-lived child pwsh process. It never targets an unrelated process and does not require elevation.

$pwsh = (Get-Command pwsh -CommandType Application).Source
$child = Start-Process -FilePath $pwsh `
    -ArgumentList '-NoProfile -Command "Start-Sleep -Seconds 3; exit 0"' `
    -PassThru

$observed = Get-Process -Id $child.Id -ErrorAction Stop
[pscustomobject]@{
    Id        = $observed.Id
    Name      = $observed.ProcessName
    HasExited = $observed.HasExited
}

# Wait-Process is Windows-only in current PowerShell 7.6, so use the underlying
# Process.WaitForExit(timeoutMilliseconds) method for a cross-platform lab.
if (-not $child.WaitForExit(10000)) {
    $child | Stop-Process -WhatIf
    throw 'Disposable child did not exit within 10 seconds.'
}
$child.Refresh()
"Exited: $($child.HasExited)"

11. Verification checklist

  • You can explain PID versus process name.
  • You can inspect the current PowerShell process without formatting away the object.
  • You know why direct native invocation is preferable when output/exit status belong in the current pipeline.
  • You can use Start-Process -PassThru and the returned Process object deliberately.
  • You know that Wait-Process is Windows-only in PowerShell 7.6.
  • You preview a process stop before changing state.

12. Common mistakes and their failure modes

  • Stopping by broad name/wildcard: may terminate unrelated instances.
  • Assuming output means success: native tools can emit output and still return a failure code.
  • Using Start-Process for every CLI: can make pipeline capture and exit-code handling harder.
  • Assuming Windows window/detachment behavior on Linux/macOS: produces lifecycle surprises.
  • Ignoring permissions: turns expected access boundaries into confusing automation failures.

13. Knowledge check

Question 1. What identifies one running process instance?

Question 2. When is direct native invocation usually clearer than Start-Process?

Question 3. What does Start-Process -PassThru add?

Question 4. Why use Stop-Process -WhatIf in operational automation?

Question 5. Is Start-Process detachment behavior identical on Windows and Unix-like systems?

14. Summary and next bridge

Processes are live operating-system resources, not just rows of text. Inspect narrow targets, preserve Process objects, choose direct invocation or Start-Process based on the boundary you need, and make process termination explicit. Next we apply the same evidence-first model to long-running services and daemons, where platform differences become even more important.

15. Authoritative references

Keep the academy open

Support free, practical DevOps education.

Every lesson is designed to remain readable in a browser, downloadable from GitHub, and usable without a paid learning platform. Contributions help expand and maintain the curriculum.

Ethereum / ERC-20
0x716c4Ab160C4B66F31a28AE2448BfF68fc3a2ef0 Send only Ethereum/ERC-20 compatible assets to this address.