6

I have a script that requires a number of parameters:

param ([string]$FOO="foo",[string]$CFG='\ps\bcpCopyCfg.ps1', [string]$CFROM="none", `
[string]$CTO="none", [switch]$HELP=$FALSE, [switch]$FULL=$FALSE, [string]$CCOL="none" `
,[string]$CDSQUERY="none", [string]$CMSSRV="none" `
,[string]$CSYBDB="none", [string]$CMSDB="none")

when called from the command prompt e.g.

powershell .\bcpCopy.ps1 -CFROM earn_n_deduct_actg -CTO fin_earn_n_deduct_actg -CCOL f_edeh_doc_id

everything works fine. I need however to start several (dozens) instances of the script in parallel and I've written a wrapper script that calls the one doing the actual work as a job: I prepare an array with the arguments (including the keywords like "-CFG") anhd pass it to start-job:

    # Prepare script block to be released
    $ARGS=("-CFG ", $CFG, "-CSYBDB ", $SYBDB, "-CMSDB ",$MSDB, "-CFROM ", $SYBTBL, "-CTO ",$MSTBL)
    if ($FULL) {
        $ARGS = $ARGS + " -FULL"
    } else { 
        $ARGS = $ARGS + " -CCOL $($args[5])  "
    } 
    "Argument array:"
    $ARGS

    start-job  -scriptblock {powershell.exe -file '\ps\bcpCopy.ps1'} -ArgumentList $ARGS

Unfortunately, the called script does not receive the arguments: the caller prints the array and it looks fine:

Argument array:
-CFG
\ps\bcpCopyCfgOAH.ps1
-CSYBDB
vnimisro
-CMSDB
IMIS_UNOV
-CFROM
earn_n_deduct_ref
-CTO
fin_earn_n_deduct_ref
-FULL

but the output from the called scripts says that the only parameter received is the configuration file -- all the rest are at their default values.

PS C:\ps> receive-job 1391
12/17/2010 10:54:14 Starting the upload of table none; source db none;
12/17/2010 10:54:14 Target table is none; target db is none;
12/17/2010 10:54:14 Config file is \ps\bcpCopyCfg.ps1.
12/17/2010 10:54:14 Target server (MS SQL) is secap900-new
12/17/2010 10:54:14 Source database must be specified. Exiting...

Can you please point me what am I doing wrong?

John Saunders
  • 160,644
  • 26
  • 247
  • 397
Lubo
  • 61
  • 1
  • 1
  • 2

2 Answers2

6

I'm not sure what exactly you're trying to do, but this looks wrong:

start-job  -scriptblock {
    powershell.exe -file '\ps\bcpCopy.ps1'} -ArgumentList $ARGS

You are creating an entirely new powershell process needlessly. Try this instead:

start-job  -scriptblock {
    & 'c:\ps\bcpCopy.ps1' @args } -ArgumentList $ARGS

The "@args" syntax is called "splatting." This will expand the passed arguments and ensure each element is treated as a parameter. The ampersand (&) is the "call" operator.

x0n
  • 51,312
  • 7
  • 89
  • 111
  • Thanks for the advice. Now the jobs are released and appear to to hanging not doing anything. Continue to hang even I put an exit in the script right after it starts and prints the arguments. BTW with this way of starting the jobs the task mngr still shows 15 powershell processed -- exactly the # I started – Lubo Dec 17 '10 at 21:27
  • and also after manually stopping the jobs, receive-job does not returns anything – Lubo Dec 17 '10 at 21:31
  • As I said, the & (call) starts a powershell process but the process hangs. – Lubo Dec 18 '10 at 03:52
  • The @args (the splatting)after the script name was however a revelation -- solved my argument-passing problem -- thanks a lot. So the "final"ver that works is start-job -scriptblock {powershell.exe -file 'c:\ps\bcpCopy.ps1' @args} -ArgumentList $ARGS – Lubo Dec 18 '10 at 03:56
0

Another way is to put the @ before the array. I changed the $ARGS variable to $flags to differentiate $args in the scriptblock from $flags.

$flags = @("-CFG ", $CFG, "-CSYBDB ", $SYBDB, "-CMSDB ",$MSDB, "-CFROM ", $SYBTBL, "-CTO ",$MSTBL)

If($FULL) {
    $flags = $flags + " -FULL"
}
Else {
   $flags = $flags + " -CCOL $($args[5])  "
}
"Argument array:"
$flags

start-job  -scriptblock {powershell.exe -file '\ps\bcpCopy.ps1' $args} -ArgumentList $flags
T.CK
  • 411
  • 4
  • 6