powershelljobspowershell-jobs

PowerShell implementing -AsJob for a cmdlet


Is there a nice way to implement the switch parameter -AsJob in custom cmdlets, like Invoke-Command has?

The only way I thought about this is:

function Use-AsJob {
   [CmdletBinding()]
   [OutputType()]
   param (
      [Parameter(Mandatory = $true)]
      [string]
      $Message,

      [switch]
      $AsJob
   )

   # Wrap Script block in a variable
   $myScriptBlock = {
       # stuff
   }
   if ($AsJob) {
       Invoke-Command -ScriptBlock $myScriptBlock -AsJob
   }
   else {
       Invoke-Command -ScriptBlock $myScriptBlock
   }
}

Is there a better approach? I couldn't find Microsoft docs on this, any lead helps.


Solution

  • If we make the following assumptions:

    Then you can use the following boilerplate for any command:

    function Test-AsJob {
        param(
            [string]$Parameter = '123',
            [switch]$AsJob
        )
    
        if ($AsJob) {
            # Remove the `-AsJob` parameter, leave everything else as is
            [void]$PSBoundParameters.Remove('AsJob')
    
            # Start new job that executes a copy of this function against the remaining parameter args
            return Start-Job -ScriptBlock {
                param(
                    [string]$myFunction,
                    [System.Collections.IDictionary]$argTable
                )
    
                $cmd = [scriptblock]::Create($myFunction)
    
                & $cmd @argTable 
            } -ArgumentList $MyInvocation.MyCommand.Definition,$PSBoundParameters
        }
    
        # here is where we execute the actual function
        return "Parameter was '$Parameter'"
    }
    

    Now you can do either:

    PS C:\> Test-AsJob
    Parameter was '123'
    PS C:\> Test-AsJob -AsJob |Receive-Job -Wait
    Parameter was '123'