Powershell expand variable in scriptblock
Asked Answered
I

2

6

I am trying to follow this article to expand a variable in a scriptblock

My code tries this:

$exe = "setup.exe"

invoke-command -ComputerName $j -Credential $credentials -ScriptBlock {cmd /c 'C:\share\[scriptblock]::Create($exe)'}

How to fix the error:

The filename, directory name, or volume label syntax is incorrect.
    + CategoryInfo          : NotSpecified: (The filename, d...x is incorrect.:String) [], RemoteException
    + FullyQualifiedErrorId : NativeCommandError
    + PSComputerName        : remote_computer
Indite answered 28/8, 2014 at 14:53 Comment(1)
Here's the referenced article on the WaybackMachine as Microsoft have moved/deleted the original.Florri
S
4

To follow the article, you want to make sure to leverage PowerShell's ability to expand variables in a string and then use [ScriptBlock]::Create() which takes a string to create a new ScriptBlock. What you are currently attempting is to generate a ScriptBlock within a ScriptBlock, which isn't going to work. It should look a little more like this:

$exe = 'setup.exe'
# The below line should expand the variable as needed
[String]$cmd = "cmd /c 'C:\share\$exe'"
# The below line creates the script block to pass in Invoke-Command
[ScriptBlock]$sb = [ScriptBlock]::Create($cmd) 
Invoke-Command -ComputerName $j -Credential $credentials -ScriptBlock $sb
Sulk answered 28/8, 2014 at 15:20 Comment(0)
F
5

You definitely don't need to create a new script block for this scenario, see Bruce's comment at the bottom of the linked article for some good reasons why you shouldn't.

Bruce mentions passing parameters to a script block and that works well in this scenario:

$exe = 'setup.exe'
invoke-command -ComputerName $j -Credential $credentials -ScriptBlock { param($exe) & "C:\share\$exe" } -ArgumentList $exe

In PowerShell V3, there is an even easier way to pass parameters via Invoke-Command:

$exe = 'setup.exe'
invoke-command -ComputerName $j -Credential $credentials -ScriptBlock { & "C:\share\$using:exe" }

Note that PowerShell runs exe files just fine, there's usually no reason to run cmd first.

Faust answered 28/8, 2014 at 15:25 Comment(3)
Am I missing the linked article?Devonna
See the link in the question, not in the answer.Faust
Ah, thanks. The gist is avoid doing [scriptblock]::create because if you screw up the quoting, you can create/run code you don't mean to. The using you describe looks great and means no 'eval' like stuff going on, so I'll definitely try that way first.Devonna
S
4

To follow the article, you want to make sure to leverage PowerShell's ability to expand variables in a string and then use [ScriptBlock]::Create() which takes a string to create a new ScriptBlock. What you are currently attempting is to generate a ScriptBlock within a ScriptBlock, which isn't going to work. It should look a little more like this:

$exe = 'setup.exe'
# The below line should expand the variable as needed
[String]$cmd = "cmd /c 'C:\share\$exe'"
# The below line creates the script block to pass in Invoke-Command
[ScriptBlock]$sb = [ScriptBlock]::Create($cmd) 
Invoke-Command -ComputerName $j -Credential $credentials -ScriptBlock $sb
Sulk answered 28/8, 2014 at 15:20 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.