tambre tambre - 3 months ago 36
PowerShell Question

Passing arguments to job initialization script

I have multiple jobs and for every job I want to have the same initialization script that sets some things up. I'd like to pass some arguments to the initialization script, but unfortunately the arguments passed using

-ArgumentList
seem to be only accessible in the actual job script.

Here's an example that demonstrates the argument only being accessible in the actual script:

function StartJob([ScriptBlock] $script, [string] $name, [ScriptBlock] $initialization_script = $null, $argument = $null)
{
Start-Job -ScriptBlock $script -Name $name -InitializationScript $initialization_script -ArgumentList $argument | Out-Null
}

[ScriptBlock] $initialization_script =
{
# The argument given to StartJob should be accessible here
param($test)
echo "Test: $test"
}

[ScriptBlock] $actual_script =
{
param($test)
echo "Test: $test"
}

StartJob $actual_script "Test job" $initialization_script "Have this string in the `$initialization_script"

@(Get-Job).ForEach({
# Wait for the job to finish, remove it and output its results
Write-Host "$($_.Name) results:"
Receive-Job -Job $_ -Wait -AutoRemoveJob | Write-Host
})


How would I be able to be access the arguments passed in the
$initialization_script
?

Answer

AFAIK it's not possible to pass parameters to initialization scripts. Init scripts are designed to be reusable scripblocks to load known resources. If something can't be defined once, then it's unique to that job's scriptblock and doesn't belong in a init. script. You have a few alternatives:

  • If you have a module (.psm1 and maybe a .psd1), then place tem in one of the module-folders (see $env:PSModulePath for paths) so you could simply write Import-Module MyImportantModule in your initialization script.

  • If you can't use the solution above, I would add a paramter to the actual script and pass in the path as a regular argument.

    [ScriptBlock] $actual_script =
    {
        # The argument given to StartJob should be accessible here
        param($test, $ModulePath)
    
        #Import-Module $ModulePath
    
        echo "Test: $test"
    }
    
    Start-Job -ScriptBlock $actual_script -Name "Test job" -ArgumentList "c:\mymodule.ps1"
    
  • Or you could generate the initialization scriptblock in your script so it's dynamic:

    $ModulePath = "c:\mymodule.ps1"
    
    $init = @"
    
    #Import-Module "$ModulePath"
    #Something-Else
    
    "@
    
    $initsb = [scriptblock]::Create($init)