8

I've got a working Powershell script and I'd like to have the scriptblock pulled in from an external file.

Working:

$scriptblock = { ... }
invoke-command -ComputerName $server -ScriptBlock $Scriptblock -ArgumentList $server,$team -Credential $credential -asjob -JobName Dashboard_$server -SessionOption (New-PSSessionOption -NoMachineProfile)

Output of "get-job -id | receive-job" is fine

Not working:

# Generate scriptblock from file
$file = Get-Content E:\Dashboard\Windows\winrm_scriptblock.txt
$Scriptblock = $executioncontext.invokecommand.NewScriptBlock($file)

invoke-command -ComputerName $server -ScriptBlock $Scriptblock -ArgumentList $server,$team -Credential $credential -asjob -JobName Dashboard_$server -SessionOption (New-PSSessionOption -NoMachineProfile)

Output of "get-job -id | receive-job" is empty

The contents of winrm_scriptblock.txt is exactly what is included between the braces in the scriptblock variable defined in the working version.

Any assistance is appreciated.

kernelpanic
  • 1,158
  • 5
  • 17
  • 36
  • Does this work for you? `$Scriptblock = [scriptblock]::Create((Get-Content E:\Dashboard\Windows\winrm_scriptblock.txt))` – Matt Jan 16 '15 at 20:51

4 Answers4

14

I know you already have answers, but another way to get a scriptblock from a script file is to use the get-command cmdlet:

$sb=get-command C:\temp\add-numbers.ps1 | select -ExpandProperty ScriptBlock 

$sb is now the scriptblock for the script.

Mike Shepard
  • 17,466
  • 6
  • 51
  • 69
4

Very related to the answer from How do I pass a scriptblock as one of the parameters in start-job

If you stored the string "Get-ChildItem C:\temp" in the file "E:\Dashboard\Windows\winrm_scriptblock.txt" then this code should output the contents of the folder "C:\temp" on your local machine.

Invoke-Command -ScriptBlock ([scriptblock]::Create((Get-Content "E:\Dashboard\Windows\winrm_scriptblock.txt")))

Parameters

As far as passing parameters goes Pass arguments to a scriptblock in powershell covers that answer as well. As Keith Hill states: a scriptblock is just an anonymous function

Consider the following file contents

param(
    $number
)

$number..2 | ForEach-Object{
    Write-Host "$_ lines of code in the file."
}

And the command

Invoke-Command -ScriptBlock ([scriptblock]::Create((Get-Content "E:\Dashboard\Windows\winrm_scriptblock.txt"))) -ArgumentList "99"

Would give you the annoying output of

99 lines of code in the file.
98 lines of code in the file.
97 lines of code in the file.
....
Community
  • 1
  • 1
Matt
  • 45,022
  • 8
  • 78
  • 119
  • Tried this and it doesn't work for me. My scriptblock is around 350 lines long and accepts parameters. Not sure if that matters. – kernelpanic Jan 16 '15 at 20:58
  • I will try and pass it parameters and see if it works. The length itself should not matter at all – Matt Jan 16 '15 at 21:00
  • @kernelpanic The updated answer should cover that base. – Matt Jan 16 '15 at 21:08
2

Any reason not to just use the -FilePath parameter of Invoke-Command?

mjolinor
  • 66,130
  • 7
  • 114
  • 135
  • 1
    Taking me as an example - I would like to execute script block on remote machine, by passing it through arguments or with using variable scope, so this won't work for me. – Gucu112 Jan 10 '22 at 12:26
-3

you must extract {} from E:\Dashboard\Windows\winrm_scriptblock.txt