I am writing a function to execute commands on a remote machine. The function receives a scriptblock
and needs to wrap those commands inside additional commands (i.e. a try / catch). However, I need to expand local variables before remote execution. As an example, I created the below script:
function Child {
param(
[scriptblock]$command
)
write-host "Command: $command"
# Command: echo $using:var
$session = New-PSSession
invoke-command -session $session -command $command
# My Variable
invoke-command -session $session -command {
try {
$using:command
} catch {}
}
# echo $using:var
Remove-PSSession $session
}
Function Parent {
$var = "My Variable"
Child -command {
echo $using:var
}
}
Parent
I can see that the Child
function receives the command without the variable expanded. This is expected because $using
only works inside certain expressions i.e. invoke-command
. Next, the first invoke-command
executes the $command
directly. You can see that the variable is expanded before being sent to the remote machine. Finally, the second invoke-command
I try to wrap $command
in a try / catch
block. In this case, the local variable is not expanded as it is sent directly to the remote machine, as is.
How can I wrap, or expand on, the instructions of an existing scriptblock like this?
In addition, I would much prefer to expand the local variables in the Parent
function before Child
receives it. Is that possible?
To solve this issue I create a new scriptblock
and embed the original scriptblock
as a string in the new scriptblock
which allows the new scriptblock
to expand the $using
variables included in the original scriptblock
. Because of this, variables that are "local" to the "remote host" are escaped in the new scriptblock. I imagine that same thing could be done in the parent function to expand the variables before it is passed to the child function.
function Child {
param(
[scriptblock]$command
)
write-host "Command: $command"
# Command: echo $using:var
$session = New-PSSession
invoke-command -session $session -command $command
# My Variable
$newCommand = [scriptblock]::Create("
`$errorActionPreference = 'stop'
try {
$command
} catch {
throw `$_ | Select-Object ScriptStackTrace, Exception, ErrorDetails
}
")
invoke-command -session $session -command $newCommand
# My Variable
Remove-PSSession $session
}
Function Parent {
$var = "My Variable"
Child -command {
echo $using:var
}
}
Parent