代码之家  ›  专栏  ›  技术社区  ›  user2871239

当通过ArgumentList传递到Start Job时,如何重新创建序列化为字符串的ScriptBlock?

  •  1
  • user2871239  · 技术社区  · 4 月前

    我想将ScriptBlock作为参数传递给Start Job ScriptBlock。我明白 [ScriptBlock] 在传递到作业时,为了安全起见,被序列化为字符串。所以,我需要反序列化它。我已经尝试过使用 [ScriptBlock]::Create() 但它似乎没有处理 $($args[0].cheese) 正确地。

    这是我正在做的事情的简化版本。

    function Format-Text {
        [CmdletBinding()]
        param([Parameter(Mandatory, ValueFromPipeline)][Object]$InputObject,
              [Parameter(Mandatory)][ScriptBlock]$Formatter)
        Write-Host ($Formatter.Invoke($InputObject))
    }
    
    $formatter = {"My favourite cheese is: $($args[0].cheese)"}
    $testObject = [PSCustomObject]@{cheese = 'cheddar'}
    
    Format-Text -InputObject $testObject -Formatter $formatter
    
    
    # stuff before this is just to demonstrate that it works outside of Start-Job 
    
    
    $job = Start-Job -ArgumentList $testObject,$formatter.ToString() -ScriptBlock {
        param ([String]$Obj,
               [String]$Fmtr)
    
        function Format-Text {
            [CmdletBinding()]
            param([Parameter(Mandatory, ValueFromPipeline)][Object]$InputObject,
                  [Parameter(Mandatory)][ScriptBlock]$Formatter)
            Write-Host ($Formatter.Invoke($InputObject))
        }
    
        $sb = [ScriptBlock]::Create($Fmtr)
    
        Format-Text -InputObject $Obj -Formatter $sb
    }
    
    # clean up
    
    do { Start-Sleep -Milliseconds 500 } until ($job.State -ne 'Running')
    Receive-Job $job; Remove-Job $job
    

    输出为:

    My favourite cheese is: cheddar
    My favourite cheese is: 
    

    我如何反序列化 string 使得 $($args[0].奶酪) 作品?

    上面的例子被简化为骨架,真正的脚本是00行和许多函数。如果可以避免的话,我不想重写这个函数,因为它在许多其他地方都有使用。

    我正在运行内置的PowerShell 5.1。

    1 回复  |  直到 4 月前
        1
  •  1
  •   mklement0    4 月前
    • 使用以下命令从字符串中重新创建脚本块 [scriptblock]::Create() 按预期工作。

      • 顺便说一句:导致选择反序列化脚本块的所谓安全考虑 作为字符串 从未被详细说明过。就我个人而言,鉴于以下情况,我认为反序列化脚本块本身没有任何风险 建设 脚本块的 结果为 执行 .

      • 请参阅 GitHub issue #11698 进行讨论。

    • 你唯一的问题是意外地输入了你的 -Object 参数as [String]$Obj ,而它应该是 [object] $Obj (或者简单地说 $Obj ).

      • A. [string] 对象显然没有 .cheese 属性,默认情况下,PowerShell会悄悄地将访问不存在的属性的尝试评估为 $null ,在字符串扩展(插值)的上下文中,其计算结果为 空字符串 (这就是你所看到的)。

      • 你本可以通过以下方式发现这个问题 Set-StrictMode -Version 2 或更高,报告试图访问不存在的属性 错误 ,但请注意这些模式施加的额外约束。

    推荐文章