考虑以下呼叫站点:
$modifiedLocal = 'original local value'
'input object' | SomeScriptblockInvoker {
$modifiedLocal = 'modified local value'
[pscustomobject] @{
Local = $local
DollarBar = $_
}
}
$modifiedLocal
我想实现SomeScriptblockInvoker
这样
呼叫站点的功能输出如下:
Local DollarBar
----- ---------
local input object
modified local value
PowerShell似乎能够做到这一点。例如,将SomeScriptblockInvoker
替换为ForEach-Object
会产生所需的输出。
我接近使用以下定义:
New-Module m {
function SomeScriptblockInvoker {
param
(
[Parameter(Position = 1)]
[scriptblock]
$Scriptblock,
[Parameter(ValueFromPipeline)]
$InputObject
)
process
{
$InputObject | . $Scriptblock
}
}
} |
Import-Module
使用该定义的呼叫站点的输出如下:
Local DollarBar
----- ---------
local
modified local value
请注意,DollarBar
为空时input object
。
答案 0 :(得分:2)
一般来说,你不能。 scriptblock的调用者无法控制与该scriptblock关联的SessionState,并且SessionState(部分)确定执行scriptblock的上下文(有关详细信息,请参阅Scope部分)。根据脚本块的定义位置,其SessionState可能与调用者的上下文匹配,但可能不匹配。
关于执行scriptblock的上下文,有两个相关的注意事项:
Here is a good explanation of how this works
$_
自动变量 $_
contains the current object in the pipeline。提供给%
的脚本块的解释与提供.
和&
的脚本块不同:
'input_object' | % {$_}
- $_
的值为'input_object'
,因为scriptblock已绑定到%
的{{1}}参数。该脚本块对管道中的每个对象执行一次。-Process
和'input_object' | . {process{$_}}
- 'input_object' | & {process{$_}}
的值为$_
,因为scriptblock中的'input_object'
位于执行的$_
块内一次为管道中的每个对象。请注意,在使用process{}
调用scriptblock时,OP $_
为空。这是因为scriptblock不包含.
块。 scriptblock中的每个语句都隐含在scriptblock的process{}
块中。运行end{}
块时,管道中不再有任何对象,end{}
为空。
$_
vs .
vs &
%
,.
和&
均使用scriptblock的SessionState调用scriptblock,但根据下表有一些差异:
%
+---+-----------------+-----------+-------------------+----------------------+
| | Name | Kind | interprets {} as | adds scope to stack |
+---+-----------------+-----------+-------------------+----------------------+
| % | ForEach-Object | Command | Process block | No |
| . | dot-source | Operator | scriptblock | No |
| & | call | Operator | scriptblock | Yes |
+---+-----------------+-----------+-------------------+----------------------+
命令包含与%
和Begin{}
块对应的其他参数。传递the tests in OP的两个最可行的选项如下。请注意,既不严格在调用者的上下文中调用scriptblock,而是在使用与scriptblock关联的SessionState的上下文中调用。
更改通话网站,以便脚本块包含End{}
:
process{}
使用OP中的$modifiedLocal = 'original local value'
'input object' | SomeScriptblockInvoker {
process {
$modifiedLocal = 'modified local value'
[pscustomobject] @{
Local = $local
DollarBar = $_
}
}
}
$modifiedLocal
调用脚本块。
使用SomeScriptblockInvoker
作为suggested by PetSerAl调用脚本块。