PowerShell implementing -AsJob for a cmdlet

835 Views Asked by At

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.

1

There are 1 best solutions below

2
On BEST ANSWER

If we make the following assumptions:

  • Command is a script function
  • Function does not rely on module state

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'