Send string parameters to a Start-Job script block

别来无恙 提交于 2021-02-08 06:53:25

问题


I need to initialize a job using the shell. The job will be a delay plus a call to a vbScript. The following code works fine. For my example, the vbScript is just a single line with a MsgBox "Hello world!"

$functions = {
    Function execute_vbs {
        param ([string]$path_VBScript, [int]$secs)
        Start-Sleep -Seconds $secs
        cscript /nologo $path_VBScript 
    }
}
$seconds = 2
Start-Job -InitializationScript $functions -ScriptBlock {execute_vbs -path_VBScript 'C:\Users\[USERNAME]\Desktop\hello_world.vbs' -secs $seconds} -Name MyJob

The problem comes the moment I want to parameterize the vbScript path. (the idea is to do several different calls to some different vbScripts). When I do this, the command seems to ignore the parameter input. I did other tests with int parameter and they work fine, the problem looks to be only with the string parameters. The following code does not work:

$functions = {
    Function execute_vbs {
        param ([string]$path_VBScript, [int]$secs)
        Start-Sleep -Seconds $secs
        cscript /nologo $path_VBScript 
    }
}
$input = 'C:\Users\[USERNAME]\Desktop\hello_world.vbs'
$seconds = 2
Start-Job -InitializationScript $functions -ScriptBlock {execute_vbs -path_VBScript $input -secs $seconds} -Name MyJob

I've also tried using the [-ArgumentList] command, but it has the same problem.

Any idea?


回答1:


The problem is that the $input and $seconds variables inside your script block are in a different scope and are effectively different variables to the ones in the main script.

I've modified your script slightly to remove the call to VBScript to make it easier to reproduce here - my example code is:

$functions = {
    Function execute_vbs {
        param ([string]$path_VBScript, [int]$secs)
        Start-Sleep -Seconds $secs
        write-output "filename = '$path_VBScript'"
        write-output "secs = '$secs'"
    }
}

Here's two ways to fix it:

The Using: scope modifier

See https://docs.microsoft.com/en-us/powershell/module/microsoft.powershell.core/about/about_scopes?view=powershell-7#the-using-scope-modifier for the full details, but basically:

For any script or command that executes out of session, you need the Using scope modifier to embed variable values from the calling session scope, so that out of session code can access them.

$filename = 'C:\Users\[USERNAME]\Desktop\hello_world.vbs'
$seconds = 2

$job = Start-Job -InitializationScript $functions -ScriptBlock {
        execute_vbs -path_VBScript $using:filename -secs $using:seconds
    } -Name MyJob

wait-job $job

receive-job $job
# output:
# filename = 'C:\Users\[USERNAME]\Desktop\hello_world.vbs'
# secs = '2'

Note the $using before the variable names inside the script block - this allows you to "inject" the variables from your main script into the scriptblock.

ScriptBlock Parameters

You can define parameters on the script block similar to how you do it with a function, and then provide the values in the -ArgumentList parameter when you invoke Start-Job.

$filename = 'C:\Users\[USERNAME]\Desktop\hello_world.vbs'
$seconds = 2

$job = Start-Job -InitializationScript $functions -ScriptBlock {
    param( [string] $f, [int] $s )
    execute_vbs -path_VBScript $f -secs $s
} -ArgumentList @($filename, $seconds) -Name MyJob

wait-job $job

receive-job $job
# output:
# filename = 'C:\Users\[USERNAME]\Desktop\hello_world.vbs'
# secs = '2'
``


来源:https://stackoverflow.com/questions/63700083/send-string-parameters-to-a-start-job-script-block

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!