点源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可能不是一个选项。
有没有人有任何想法?
答案 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 变量对此进行了解释。