首页 > 解决方案 > Invoke-Command 在本地运行时是在当前范围内运行还是在子范围内运行?

问题描述

我在另一篇帖子的评论中获悉:

至于Invoke-Command:不幸的是,文档不正确:默认情况下,本地调用发生在子范围内,但您可以选择使用-NoNewScope. – mklement0

但是,根据帮助文档(强调添加):

您还可以在本地计算机上使用 Invoke-Command 来评估或运行脚本块中的字符串作为命令。Windows PowerShell 将脚本块转换为命令并立即在当前范围内运行命令,而不是仅仅在命令行中回显字符串。

这似乎按预期工作:

PS C:\> $TestVar = 99
PS C:\> Invoke-Command { Get-Variable TestVar }

Name                           Value
----                           -----
TestVar                        99

如果文档有误,我希望这会导致变量对Invoke-Command. 文档到底是正确的吗?

标签: powershellscope

解决方案


该文档提供了混合信息,并且问题中引用的部分肯定已过时/不正确。

提供正确信息的帮助部分如下-NoNewScope所述:

指示此 cmdlet 在当前范围内运行指定的命令。默认情况下,Invoke-Command 在它们自己的范围内运行命令。

该参数仅对当前会话中运行的命令有效,即同时省略ComputerName和Session参数的命令。

此参数是在 Windows PowerShell 3.0 中引入的。

以下显示了-NoNewScope正确的范围信息(用编号的范围表示):

$TestVar = 99
Invoke-Command { Get-Variable TestVar -Scope 0 } #Scope 0, current scope
Invoke-Command { Get-Variable TestVar -Scope 1 } #Scope 1, parent scope
Invoke-Command { Get-Variable TestVar -Scope 0 } -NoNewScope #Scope 0, current scope

第一个命令的结果将返回一个错误,指出找不到变量:

PS C:\> Invoke-Command { Get-Variable TestVar -Scope 0 } #Scope 0, current scope
Get-Variable : Cannot find a variable with the name 'TestVar'.

其他命令将按预期返回变量信息。但是,正如在另一篇文章的评论中提到的,-NoNewScope必须用于明确告诉Invoke-Command使用当前范围,否则默认情况下它将在子范围中运行。

问题中的命令起作用的唯一原因是因为默认情况下变量可用于子范围,并且不需要声明范围,因为没有使用-ComputerNameor-Session参数。

截至 2019 年 8 月 21 日,文档更新请求已完成。问题中提到的问题部分的新版本现在显示为:

You can also use `Invoke-Command` on a local computer to a script block as a command.
PowerShell runs the script block immediately in a child scope of the current scope.

推荐阅读