2016-04-14 34 views
4

The 我使用的脚本Microsoft.PowerShell_profile.ps1运行时会创建很多变量。我已将所有变量的范围设置为“脚本”,但脚本中使用的变量永远不会超出范围。Powershell Profile脚本点源?

我希望一旦脚本完成运行并将控制权交给我后,变量就会超出范围。

如果我比较了全局变量,本地变量和脚本变量的数量,我想出了相同的数字。

例子:

# Profile script does what it does. 

Get-Variable -Scope Global | Measure-Object 
Get-Variable -Scope Local | Measure-Object 
Get-Variable -Scope Script | Measure-Object 

Output: 
60 
60 
60 

目前,我捕捉变量的快照我的配置脚本的开头,然后在最后删除任何新的变数。

例子:

$snapshotBefore = Get-Variable 
$profileVar1 = 'some value' 
$profileVar2 = 'some other value' 
$snapshotAfter = Get-Variable 

# Compare before and after, and create list of new variables. 

Remove-Variable $variablesToRemove 
+0

我不确定你的目标。为什么要将变量的范围设置为'script'? –

+0

@Bill_Stewart:意图是在配置文件内部使用临时变量,一旦配置文件加载完成后,暂时变量不应该留下。 – mklement0

+1

啊。是的,PowerShell配置文件是点源。 –

回答

2

是,PowerShell配置文件是点源设计,因为这是使其中所含的定义(别名,函数,...)是全球可用默认 - 这毕竟是配置文件的主要目的。

不幸的是,没有范围修改,允许你创建一个变量临时范围内,你只希望存在,而轮廓装载 - 即使是范围local在配置文件脚本有效全球;同样,使用范围private也不是一个选项,因为配置文件的脚本范围 - 由于是点源 - 是全球范围的

一般来说,你可以使用&(电话运营商)用一个脚本块,以创建范围限定于该块是块中的变量,但通常是有分歧与在配置文件创建全球可用定义,至少在默认情况下。
同样,如果在自己的答案中调用另一个没有点源的脚本,则默认情况下不会使其全局可用。
可以,然而,通过指定全球范围内创建 -dot来源的脚本块/脚本全局元素明确;例如:& { $global:foo = 'Going global' }& { function global:bar { 'global func' } }

这就是说,后面点采购型材的理由可能是,它更容易使默认所有定义全球,使得轮廓的典型元素的定义 - 别名,功能,驱动器映射,加载模块 - 更简单(不需要指定明确的范围)。
相比之下,全局变量不太典型,为了定义上面列出的典型元素,您通常不需要配置文件中的脚本级变量(因此全局变量)。


如果您还需要在您的配置文件来创建(概念)临时变量(这是创建全局可用的别名,函数,...的要求):

一个简单的解决方法在配置文件脚本中使用外来变量名称前缀(如__)以降低其意外引用(例如,$__profileVar1 = ...)的风险。
换句话说:变量仍然全球存在,但他们的异国名称通常不会导致问题。

然而,你的方法,尽管它需要一些额外的工作,听起来像一个可靠的替代方法,这里是什么样子全(使用PSv3 +语法):

# Save a snapshot of current variables. 
# * If there are variables that you DO want to exist globally, 
# define them ABOVE this command. 
# * Also, load MODULE and dot-source OTHER SCRIPTS ABOVE this command, 
# because they may create variables that *should* be available globally. 
$varsBefore = (Get-Variable).Name 

# ... define and use temporary variables 

# Remove all variables that were created since the 
# snapshot was taken, including $varsBefore. 
Remove-Variable (Compare-Object $varsBefore (Get-Variable).Name).InputObject 

注意我依靠Compare-Object的默认行为只报告对象之间的差异,假设你还没有试过删除任何变量,只有变量是重新移植。


注意的是,虽然它可以从他们确实是点源轮廓文件的实际行为推断 - 因为点采购是将元素添加到当前作用域的唯一途径(全球范围,在配置文件的情况下) - 这个事实并不明确记录本身。

下面是各种帮助主题片段(如PSv5的),提供线索(重点煤矿):

Get-Help about_Profiles

Windows PowerShell配置文件是运行在Windows PowerShell中 脚本开始。 您可以使用该配置文件作为登录脚本来自定义 环境。您可以添加命令,别名,函数,变量,管理单元, 模块和Windows PowerShell驱动器。您也可以将其他 特定于会话的元素添加到您的配置文件中,以便在每个会话中都可用,而无需导入或重新创建它们。

Get-Help about_Variables

默认情况下,变量仅在 创建它们的范围是可用的。

例如,您在函数中创建的变量为 仅在该函数中可用。 在脚本中创建的变量仅在脚本中可用(,除非 用点源代码将该脚本添加到当前范围)。

Get-Help about_Operators

。点源操作员 在当前范围内运行脚本,以便将脚本创建的所有功能, 别名和变量添加到当前的 范围内。

Get-Help about_Scopes

但是,可以使用点 源符号添加脚本或者函数到当前范围。然后,当脚本在当前作用域中运行时,脚本创建的任何 函数,别名和变量在当前作用域中可用 。

要将函数添加到当前作用域,请在函数调用中函数的路径和名称前输入一个点(。)和空格。

+0

谢谢您的回答,并为了更好地回答问题而修改答案。你做得很好。让我指出一个问题,我发现我以前的解决方法(使用快照和比较对象)。当我加载一个模块,并创建一个全局变量。这个变量稍后会被这个操作删除。这就是为什么我正在寻求一种“更好的方式”来做到这一点,并希望适当的范围能够解决它。再次感谢你! –

+0

我也很好奇,如果你有第一段的源代码**“PowerShell配置文件是由设计点源的,因为这就是允许其中包含的定义(别名,函数......)在全球范围内可用”* *。 –

+0

感谢指针重新加载模块 - 我已经更新了一个警告的答案。您仍然可以使用该技术,只需在加载模块并点击其他脚本之后仔细放置可变快照获取命令即可。我也很好奇你在配置文件中实际做了些什么,如果它适合你简单地用'&'调用另一个脚本,它不能创建_global_元素。 – mklement0

0

所以它听起来像Powershell点源的配置文件。我找不到特别说明的资源,或者其他提出此问题的论坛。

我找到了答案,并且想在此发布。

我已将我的配置文件更改为只调用脚本文件。脚本现在有自己的范围,只要变量不是全局变量,一旦配置文件加载完成,它们就会超出范围。

所以现在我的个人资料已经一行:

& (Split-Path $Path $profile -Parent | Join-Path "Microsoft.PowerShell_profile_v2.ps1") 

Microsoft.PowerShell_profile_v2.ps1现在可以包含适当范围:

$Global:myGlobalVar = "A variable that will be available during the current session" 
$Script:myVar = "A variable that will disappear after script finishes." 
$myVar2 = "Another variable that will disappear after script finishes." 

这是什么允许,是天寒脚本导入包含全局变量的模块。这些变量在本届会议期间将继续存在。

我仍然很好奇为什么微软决定以这种方式调用配置文件。如果有人知道,并希望分享。我很想在这里看到答案。

+1

mklement0已经为您的问题提供了答案。这些配置文件是点源的,因此定义可在全球范围内使用。 –

+0

我开始看到你来自哪里:你关注的是全局_variables_,然而,它并不是典型的 元素放置在配置文件中;定义别名,函数和驱动器映射,以及加载模块/管理单元更为典型。 因此,将这些元素设置为global_by default_(通过点源)比在任何时候指定一个范围更方便。 相反,问题是:为什么您需要在配置文件中定义脚本级变量? 为了创建上述典型元素,您不需要脚本级别的变量。 – mklement0