I have a powershell script in which I have been trying to pass scriptblock(ie $sb) as an argument to another scriptblock. However, I keep getting error that:
Cannot convert the "{get-member}" value of type "System.String" to type "System.Management.Automation.ScriptBlock
a.psm1:
$sb = {get-member}
# $type = $sb.GetType().FullName => Returns scriptblock as data type
$result = Invoke-Command -Session "DC" -Scriptblock
{
Param(
[Parameter(Mandatory=$true)]
[scriptblock]
$sb
)
//Do some task
} -ArgumentList $sb
I am not able to figure out why $sb is treated as a string instead of Scriptblock?
The only way it works is changing the argument inside the Invoke-Command scriptblock to be of type string instead of Scriptblock. I am not sure why scriptblocks gets implicitly converted to string while passing argument to Invoke-Command scriptblock.
When a script block (type [scriptblock]
, {... }
as a literal) is passed to code that executes out-of-process , such as during remoting (your case) or in background jobs , XML-based serialization and deserialization must be performed.
On deserialization in the target process, [scriptblock]
instances indeed unexpectedly become strings .
Unfortunately and bewilderingly, this behavior has been declared by design ( ) - see GitHub issue #11698 .
Your only option is to pass the script block('s source code) as a string , and convert it back to a script block via [scriptblock]::Create()
; a simple example, using a background job:
Start-Job {
param([string] $scriptBlockSourceCode) # Note the type: [string]
# Use [scriptblock]::Create() to turn the string into a script block,
# and execute it with &
& ([scriptblock]::Create($scriptBlockSourceCode))
} -ArgumentList { 'hi' } |
Receive-Job -Wait -AutoRemove
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.