已编译的 cmdlet 和高级函数的脚本块参数评估是否不同?

发布于 2024-09-10 11:43:00 字数 1292 浏览 4 评论 0原文

在试验脚本块时,我尝试将脚本块参数与高级函数一起使用,并注意到它的执行方式与提供给已编译的 cmdlet 时的执行方式不同。

在审查 此博文来自 PowerShell 团队博客,如果脚本块不是参数的有效输入,则 PowerShell 引擎似乎应该评估脚本块。看起来,当使用脚本块参数调用该函数时,它会尝试直接将脚本块转换为参数类型,而不是根据管道中的当前对象评估脚本块。

我的目的是复制以下行为:

Import-CSV somecsv.csv | get-wmiobject -class {$_.class} -Computer {$_.computer}

对于高级功能。

示例脚本:

$sb = {throw "If there was an error, the scriptblock was evaluated!"}

function test ()
{
  param (
    [Parameter()]
    [string]
    $ThisShouldBeEvaluatedForEachItem,
    [Parameter(ValueFromPipelineByPropertyName = $true)]
    [string]
    $FullName
 )  

 process 
 {  
  write-host $Fullname, $ThisShouldBeEvaluatedForEachItem
 }
} 
Get-ChildItem | test -ThisShouldBeEvaluatedForEachItem $sb

这是预期的行为还是我走错了方向?

基于基思的回应,我将 ValueFromPipeline 和 ValueFromPipelineByPropertyName (在两个单独的测试中)添加到 ThisShouldBeEvaluatedForEachItem 参数的 Parameter 属性中。这样做可以使示例工作,尽管它似乎违背了团队博客文章中脚本块参数的既定目的。

In experimenting with scriptblocks, I was attempting to use a scriptblock parameter with an advanced function and noticed that it performs differently than when supplied to a compiled cmdlet.

In reviewing this blog post from the PowerShell Team blog, it appears that the PowerShell engine should be evaluating the scriptblock if a scriptblock is not a valid input for the parameter. It seems that when calling the function with a scriptblock parameter, it attempts to convert a scriptblock to the parameters type directly, rather than evaluating the scriptblock based on the current object in the pipeline.

My intention is to duplicate behavior like:

Import-CSV somecsv.csv | get-wmiobject -class {$_.class} -Computer {$_.computer}

for advanced functions.

Example script:

$sb = {throw "If there was an error, the scriptblock was evaluated!"}

function test ()
{
  param (
    [Parameter()]
    [string]
    $ThisShouldBeEvaluatedForEachItem,
    [Parameter(ValueFromPipelineByPropertyName = $true)]
    [string]
    $FullName
 )  

 process 
 {  
  write-host $Fullname, $ThisShouldBeEvaluatedForEachItem
 }
} 
Get-ChildItem | test -ThisShouldBeEvaluatedForEachItem $sb

Is this the intended behavior or am I headed in the wrong direction?

Based on Keith's response, I added ValueFromPipeline and ValueFromPipelineByPropertyName (in two separate tests) to the Parameter attribute for the ThisShouldBeEvaluatedForEachItem parameter. Doing that makes the example work, though it seems to defeat the stated purpose of scriptblock parameters from the Team Blog post.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(1

陈甜 2024-09-17 11:43:00

如果参数是 ValueFromPipelineValueFromPipelineByPropertyName,则 PowerShell 将评估 Scriptblock 并尝试将结果强制为参数类型。不久前我们从 PowerShell 团队获得了以下信息:

ScriptBlock 参数按原样传递
(作为 ScriptBlock)当参数
type 是 Object、ScriptBlock 或类型
从 ScriptBlock 派生,或
这些类型的集合。

我们只调用 ScriptBlock
参数绑定期间的参数
有管道输入并且有
没有简单的方法来绑定 ScriptBlock
直接。

If the parameter is ValueFromPipeline or ValueFromPipelineByPropertyName then PowerShell will evaluate the Scriptblock and try to coerce the result to the parameter type. We got this info from the PowerShell team a while back:

ScriptBlock arguments are passed as is
(as a ScriptBlock) when the parameter
type is Object, ScriptBlock, or a type
deriving from ScriptBlock, or
collections of these types.

We only invoke the ScriptBlock
argument during parameter binding when
there is pipeline input and there was
no trivial way to bind the ScriptBlock
directly.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文