Powershell 从不同范围引用当前对象

Powershell 从不同范围引用当前对象,powershell,scoping,Powershell,Scoping,我希望能够从我在catch块中调用的函数中引用catch块中的对象,如下所示: function foo { $something = ((Get-Variable -Name "_" -Scope 1).Value).Exception.Message Write-Host $something } 我想在这样的情况下使用它: foo #write-host should print empty line try { throw } catch { foo #

我希望能够从我在catch块中调用的函数中引用catch块中的对象,如下所示:

function foo
{
    $something = ((Get-Variable -Name "_" -Scope 1).Value).Exception.Message
    Write-Host $something
}
我想在这样的情况下使用它:

foo #write-host should print empty line
try {
    throw
} catch {
    foo #write-host should print $_.Exception.Message from this catch block
}
如何正确地做到这一点? 我们的目标是避免每次在catch块中使用
$\uu
时将其作为参数传递给
foo
,并且在调用
foo
而不是catch块时不打印任何内容

我也试过:

function foo
{
    $something = (($ExecutionContext.SessionState.PSVariable.Get("_")).Value).Exception.Message
    Write-Host $something
}
当以交互方式工作时,这似乎会产生我想要的结果,但在启动脚本时却不会产生这种结果。

这样做的干净方法当然是在
foo
上使用
foo$\ucode>从
catch
块调用一个(可选)参数。这就非常清楚地说明了我们称之为
foo
的内容,它与范围没有任何问题,它使
foo
可测试,所有这些都很好。您将在大多数打印错误的内容中看到这种方法(例如,在的答案中)

即使如此,如果坚持从父帧中提取错误变量,也可以这样做:

function foo {
    $lastError = (Get-PSCallStack)[1].GetFrameVariables()["_"].Value
    if ([Object]::ReferenceEquals($lastError.Exception, $error[0].Exception)) {
        $lastError.Exception.Message
    }
}
请注意
Object.ReferenceEquals
的额外技巧,以绝对确保
$\u
引用的是最后一条错误记录,而不是一些任意的管道项目(也使用
$\u
)。如果错误记录本身在管道中(例如,
$error |%{foo}
),此操作仍将失败,但此时您不妨将其称为功能。

执行此操作的干净方法当然是在
foo
上使用
foo$
catch
块调用一个(可选)参数。这就非常清楚地说明了我们称之为
foo
的内容,它与范围没有任何问题,它使
foo
可测试,所有这些都很好。您将在大多数打印错误的内容中看到这种方法(例如,在的答案中)

即使如此,如果坚持从父帧中提取错误变量,也可以这样做:

function foo {
    $lastError = (Get-PSCallStack)[1].GetFrameVariables()["_"].Value
    if ([Object]::ReferenceEquals($lastError.Exception, $error[0].Exception)) {
        $lastError.Exception.Message
    }
}

请注意
Object.ReferenceEquals
的额外技巧,以绝对确保
$\u
引用的是最后一条错误记录,而不是一些任意的管道项目(也使用
$\u
)。如果错误记录本身在管道中(例如,
$error |%{foo}
),此操作仍将失败,但此时您不妨将其称为功能。

有一个全局
$error
变量
$error[0]
保留遇到的最后一个错误。当调用“foo”而不是在catch块中时,它是全局的这一事实会产生不想要的结果,在这种情况下,我不希望它返回它从上一个catch块保存的最后一个错误。坦白地说,我会给出
foo()
默认值为
$null
的参数,并在catch块中调用
foo$\ucode>。仅当参数类型为
[Management.Automation.ErrorRecord]
时才输出异常消息。这就是我们目前正在做的,我正在探索如何避免这种情况。至少凭直觉我认为这是可以避免的,因为我们总是传递相同的参数。就像
$error
,使用
Get Variable
的解决方案也不是全局稳定的,因为
Foo
总是可以在与
catch
块无关的范围内使用
$\ucode>变量调用,即使你的方法有效。(无论您如何称呼
\uu
,这都是正确的)参数是语言的一部分是有原因的。有一个全局
$error
变量
$error[0]
保留遇到的最后一个错误。当调用“foo”而不是在catch块中时,它是全局的这一事实会产生不想要的结果,在这种情况下,我不希望它返回它从上一个catch块保存的最后一个错误。坦白地说,我会给出
foo()
默认值为
$null
的参数,并在catch块中调用
foo$\ucode>。仅当参数类型为
[Management.Automation.ErrorRecord]
时才输出异常消息。这就是我们目前正在做的,我正在探索如何避免这种情况。至少凭直觉我认为这是可以避免的,因为我们总是传递相同的参数。就像
$error
,使用
Get Variable
的解决方案也不是全局稳定的,因为
Foo
总是可以在与
catch
块无关的范围内使用
$\ucode>变量调用,即使你的方法有效。(无论您如何称呼
)参数是语言的一部分,这是有原因的。