点源脚本时PowerShell范围发生冲突

时间:2011-12-15 13:41:33

标签: powershell scope

点源PowerShell脚本时我遇到了一些范围问题。 假设我有一个脚本'A.ps1':

$VERSION = "1.0"

# Dot source B.ps1
. .\B.ps1

function Write-Version { Write-Host "A.ps1 version $VERSION" }
Write-Version

脚本B.ps1

$VERSION = "2.0"
function Write-Version { Write-Host "B.ps1 version $VERSION" }
Write-Version

运行A.ps1的输出将是:

B.ps1 version 2.0
A.ps1 version 2.0

为什么会发生这种情况非常明显。来自B.ps1的$VERSION变量被放入A.ps1的范围并覆盖该变量。实际上,这也发生在Write-Version,但是这里A.ps1覆盖了B的版本,但是因为在{。}之前调用了Write-Version,我们仍然可以看到B的Write-Version的输出功能

问题当然是如何防止这种情况?我尝试了各种范围选项,但这在点源时似乎不起作用。由于B.ps1中有函数我需要在A的范围内,所以只调用B.ps1可能不是一个选项。

有没有人有任何想法?

3 个答案:

答案 0 :(得分:2)

模块是在Powershell V2中创建的,用于解决点源的这些问题。使用psm1扩展名保存脚本,并在代码中使用Import-Module cmdlet而不是dot sourcing。

答案 1 :(得分:2)

您可以通过将B.ps1作为模块并将其重命名为B.psm1来实现。添加Export-ModuleMember以使您的功能可用于其他脚本。

这将是B.psm1:

$VERSION = "2.0"
function Write-Version { Write-Host "B.ps1 version $VERSION" }
Write-Version

# Only items specified here will be exported. If Export-ModuleMember is not used,
# ALL members (functions, variables, and aliases) will be exported. In this case
# if $VERSION was exported, $VERSION will be set to "2.0" in script A.ps1
Export-ModuleMember -Function Write-Version

而A.ps1将是:

$VERSION = "1.0"

# Import B.psm1
Import-Module .\B.psm1

function Write-Version { Write-Host "A.ps1 version $VERSION" }
Write-Version

# Use B.psm1's `Write-Version` function
B\Write-Version

答案 2 :(得分:0)

正如大家提到的,其中一个解决方案是将脚本转换为PS模块。

但是,只要您不需要将函数中的点源函数发送到全局源代码(我遇到问题并且不确定是否有办法解决它:question)您可以解决以这种方式发出:

ScopesA.ps1:

$VERSION = "1.0"
$overridenFromAntotherFile = "original"

# Invoke ScopesB.ps1 via &
& .\ScopesB.ps1

Function Write-Version { Write-Host "ScopesA.ps1 version $VERSION" }
Write-Version

Write-Host $overridenFromAntotherFile

ScopesB.ps1:

$VERSION = '2.0'
$global:overridenFromAntotherFile = 'overriden'
function Write-Version { Write-Host "ScopesB.ps1 version $VERSION" }
Write-Version

输出:

ScopesB.ps1 version 2.0
ScopesA.ps1 version 1.0
overriden

这个想法是使用&调用而不是点源(你可以在我的article中阅读它们,但是并没有多说&调用某些东西而不将其添加到当前范围和。调用并添加到范围内。)

但是,您仍然可以通过范围修饰符从ScopeB.ps1访问全局范围(same article中也提到了示例)。上面的脚本中使用 $ overridenFromAntotherFile 变量对此进行了解释。