2011-12-15 54 views
4

点源代码powershell脚本时,我遇到了一些范围问题。 假设我有一个剧本 'A.ps1':点源代码脚本时PowerShell范围冲突

$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.ps1中被调用,所以我们仍然可以看到B的Write-Version函数的输出。

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

有没有人有任何想法?

+1

有趣的问题。如果是我,我不会在两个脚本中重复使用相同的变量名称(如果它们在同一个会话中使用)。 – JNK 2011-12-15 13:54:05

+1

有关您的问题的一切都是有效的,所以都是答案(您应该使用模块) - **除为你的前提**。您声明B输出2.0和A输出1.0。 (如果事实如此,你甚至不需要发布这个问题!)实际上,A输出2.0,这是你的观点。 (是的,我知道这只是一个错字,但是一个角色会有什么不同:-) – 2011-12-15 17:38:56

+0

@msorens是的,谢谢你的发现。你的推理绝对正确。我将修改帖子。 – wensveen 2011-12-16 08:45:21

回答

1

您可以通过将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

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

+0

感谢您的回答。我会标记雷恩的答案,因为它有更多的信息。我希望我可以标记两个。 – wensveen 2011-12-16 08:52:39

0

正如家伙abouve提到的解决方案之一是将脚本转换为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上面的脚本中的变量。