如何解决使用范围重新创建PowerShell脚本块
我具有以下cmdlet来调用任意脚本块(通常调用exe)并处理返回代码。这里的目标是打印一个命令行,运行它,然后在失败时抛出一个错误....
function Invoke-ScriptBlock {
[CmdletBinding()]
param (
[Parameter(Mandatory)]
[ValidateNotNullOrEmpty()]
[scriptblock]$Block
)
$ErrorActionPreference = 'Continue'
$stringBlock = "@`"`n" + $Block.ToString().Trim() + "`n`"@"
$stringValue = . ([scriptblock]::create($stringBlock))
Write-information "Invoking command: $stringValue"
. $Block
if ($lastexitcode -ne 0) { Write-Error "Command exited with code $lastexitcode" -EA Stop }
}
$comment = 'acomment'
Invoke-ScriptBlock { git commit -m $comment }
# prints Invoking command: git commit -m acomment
只要Invoke-ScriptBlock cmdlet不在模块内部,此方法就很好用。如果是这样,我将丢失“调用命令”消息中捕获的变量的闭包。
Import-Module .\Util.psm1
$comment = 'acomment'
Invoke-ScriptBlock { git commit -m $comment }
# prints Invoking command: git commit -m
有没有一种方法可以使用传入的$ Block中的原始上下文重新创建脚本块?
解决方法
没有受支持的方法,但是您可以通过将会话状态引用从原始$Block
复制到重新创建的脚本块中来进行反射:
function Invoke-ScriptBlock {
[CmdletBinding()]
param (
[Parameter(Mandatory)]
[ValidateNotNullOrEmpty()]
[scriptblock]$Block
)
# To prove local and module-scoped variables won't affect the new script block
$comment = ''
# Obtain a reference to the relevant internal ScriptBlock property
$ssip = [scriptblock].GetProperty('SessionStateInternal',[System.Reflection.BindingFlags]'NonPublic,Instance')
# Copy the value from $Block
$ssi = $ssip.GetMethod.Invoke($Block,@())
# Create new block with the same content
$newBlock = [scriptblock]::create("@`"`n" + $Block.ToString().Trim() + "`n`"@")
# Overwrite session state value with the one with copied from $Block
$ssip.SetMethod.Invoke($newBlock,@($ssi))
$stringValue = & $newBlock
Write-Information "Invoking command: $stringValue"
& $Block
}
版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。