PowerShell Genie

PowerShell Background jobs

A background job runs work in a separate process so your prompt comes back immediately. Start-Job -ScriptBlock { } begins one, Get-Job lists them, Receive-Job collects the output, and Wait-Job blocks until they finish.

Lesson 2 min read Windows PowerShell 5.1 and PowerShell 7

Documentation: Microsoft Learn

Overview

The separate process is the whole trade-off. Nothing from your session is visible inside the job: not variables, not functions, not loaded modules. Pass values in with -ArgumentList and read them from $args or a param block. This surprises people whose job fails with an empty variable that was clearly set two lines above.

Receive-Job removes the output from the job by default, so calling it twice gives you nothing the second time. Pass -Keep if you need to read the results more than once.

Jobs also cost real memory and startup time, roughly a fifth of a second and tens of megabytes each, because each one is a process. For a handful of long tasks that is fine. For a hundred short ones it is the wrong tool, and thread jobs are the answer.

Remove-Job cleans up. Finished jobs stay in the list until you do.

Inspect this example’s structure

Read the command and its supplied arguments. This example requires real PowerShell or its module; this diagram does not execute it.

$job = [pscustomobject]@{ Id = 1 Name = 'Job1' State = 'Completed' HasMoreData = $true Command = 'Get-Service' } $job | Format-Table Id, Name, State, HasMoreData
  1. Stage 1$jobPositional values or no named parameters
  2. Stage 2Format-TablePositional values or no named parameters

    An example to inspect

    Preview the example. Sign in for the full lesson and activities.

    $job = [pscustomobject]@{
      Id = 1
      Name = 'Job1'
      State = 'Completed'
      HasMoreData = $true
      Command = 'Get-Service'
    }
    $job | Format-Table Id, Name, State, HasMoreData

    What happens

    This shows the shape Get-Job returns rather than starting a real job. The State column is what you poll: Running, Completed, Failed or Blocked. HasMoreData tells you whether Receive-Job still has output waiting, which is how you know whether a completed job has already been collected.

    Worth remembering

    • Start-Job runs in a separate process, so your session's state is not visible.
    • Pass data in with -ArgumentList.
    • Receive-Job consumes the output unless you pass -Keep.
    • Each job costs a process. Use thread jobs for many short tasks.

    Primary documentation

    Get-Service reference

    Try it

    Illustrative output · values vary by environment

    1PS> $job = [pscustomobject]@{
    2PS> Id = 1
    3PS> Name = 'Job1'
    4PS> State = 'Completed'
    5PS> HasMoreData = $true
    6PS> Command = 'Get-Service'
    7PS> }
    8PS> $job | Format-Table Id, Name, State, HasMoreData

    Example reader

    Inspect this page's example

    Fictional browser data when supported

    Run supported commands against the practice data, or inspect the example without executing it.

    Ready to inspect.

      Shows the columns Get-Job returns and what State and HasMoreData mean.

      Show reference output

      Illustrative output · values vary by environment

      Id Name State     HasMoreData
      -- ---- -----     -----------
       1 Job1 Completed        True

      Keep going

      Next: PowerShell Thread jobs
      Genie guidePowerShell Background jobs

      A background job runs work in a separate process so your prompt comes back immediately. Start-Job -ScriptBlock { } begins one, Get-Job lists them, Receive-Job collects the output, and Wait-Job blocks until they finish.