Search code examples
powershellescapingparameter-passingquoting

Can't pass a script block as a parameter to powershell.exe via -Command


I'm trying this

$Global:commandBlock={
Start-Transcript -path $projectFolder\gruntLog.txt;
grunt $argList;
Stop-Transcript
}

$cmdProc=start-process powershell -ArgumentList ('-command `$Global:commandBlock') -WorkingDirectory $fwd -PassThru -NoNewWindow:$NoNewWindow

And keep getting $commandBlock : The term '$Global:commandBlock' is not recognized as the name of a cmdlet, function, script file, or operable program.

My guess was it has to do with scope. But making variable global didn't help. Adding -args $commandBlock like that:

-ArgumentList ('-command `$Global:commandBlock -args "-commandBlock:$commandBlock"') 
-ArgumentList ('-command `$Global:commandBlock -args $commandBlock"') 

didn't help

And I'm not sure that I escape variables correctly in the block, read this, but not sure how to apply to my script.


Solution

  • There's a few things which I think are keeping this from working. First, when you're using single quotes, ' you're instructing PowerShell to operate literally. This means that it won't expand variables. Not what you're looking for.

    A better way to do this is to do it with an subexpression like this.

    $Global:commandBlock={
    'ham' >> C:\temp\test.txt
    }
    
    $cmdProc=start-process powershell -ArgumentList ("-command $($Global:commandBlock)") -PassThru -NoNewWindow:$NoNewWindow
    

    This will give you the desired results.

    Subexpressions are pretty sweet. It lets you embed a mini-scriptblock within a string, and it's then expanded out in the parent string.

    "today's date is $(get-date), on system: $($env:COMPUTERNAME)"
    

    today's date is 02/14/2017 11:50:49, on system: BEHEMOTH