gpt4 book ai didi

PowerShell:调用包含下划线变量的脚本 block

转载 作者:行者123 更新时间:2023-12-05 04:14:04 26 4
gpt4 key购买 nike

我通常会执行以下操作来调用包含 $_ 的脚本 block :

$scriptBlock = { $_ <# do something with $_ here #> }
$theArg | ForEach-Object $scriptBlock

实际上,我正在创建一个管道,它将为 $_ 赋值(在 Foreach-Object 函数调用中)。

但是,在查看 LINQ 模块的源代码时,它定义并使用了以下函数来调用委托(delegate):

# It is actually surprisingly difficult to write a function (in a module)
# that uses $_ in scriptblocks that it takes as parameters. This is a strange
# issue with scoping that seems to only matter when the function is a part
# of a module which has an isolated scope.
#
# In the case of this code:
# 1..10 | Add-Ten { $_ + 10 }
#
# ... the function Add-Ten must jump through hoops in order to invoke the
# supplied scriptblock in such a way that $_ represents the current item
# in the pipeline.
#
# Which brings me to Invoke-ScriptBlock.
# This function takes a ScriptBlock as a parameter, and an object that will
# be supplied to the $_ variable. Since the $_ may already be defined in
# this scope, we need to store the old value, and restore it when we are done.
# Unfortunately this can only be done (to my knowledge) by hitting the
# internal api's with reflection. Not only is this an issue for performance,
# it is also fragile. Fortunately this appears to still work in PowerShell
# version 2 through 3 beta.
function Invoke-ScriptBlock {
[CmdletBinding()]

param (
[Parameter(Position=1,Mandatory=$true)]
[ScriptBlock]$ScriptBlock,

[Parameter(ValueFromPipeline=$true)]
[Object]$InputObject
)

begin {
# equivalent to calling $ScriptBlock.SessionState property:
$SessionStateProperty = [ScriptBlock].GetProperty('SessionState',([System.Reflection.BindingFlags]'NonPublic,Instance'))
$SessionState = $SessionStateProperty.GetValue($ScriptBlock, $null)
}
}
process {
$NewUnderBar = $InputObject
$OldUnderBar = $SessionState.PSVariable.GetValue('_')
try {
$SessionState.PSVariable.Set('_', $NewUnderBar)
$SessionState.InvokeCommand.InvokeScript($SessionState, $ScriptBlock, @())
}
finally {
$SessionState.PSVariable.Set('_', $OldUnderBar)
}
}
}

这让我觉得有点低级。有推荐的安全方法吗?

最佳答案

您可以使用与号调用脚本 block 。无需使用 Foreach-Object。

$scriptblock = {## whatever}
& $scriptblock

@(1,2,3) | % { & {write-host $_}}

传递参数:

$scriptblock = {write-host $args[0]}
& $scriptblock 'test'

$scriptBlock = {param($NamedParam) write-host $NamedParam}
& $scriptBlock -NamedParam 'test'

如果您打算在 Invoke-Command 中使用它,您也可以使用 $using 结构。

$test = 'test'
$scriptblock = {write-host $using:test}

关于PowerShell:调用包含下划线变量的脚本 block ,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/35897998/

26 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com