Powershell Profile脚本是否源点源?

时间:2016-04-14 20:41:45

标签: powershell

我正在使用的 Microsoft.PowerShell_profile.ps1 脚本在运行时会创建很多变量。我已经设置了所有变量'范围到"脚本",但脚本中使用的变量永远不会超出范围。

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

如果我比较全局,本地和脚本变量的数量,我会得到相同的数字。

示例:

# 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

2 个答案:

答案 0 :(得分:2)

是的, PowerShell配置文件是点源按设计 ,因为允许包含在其中的定义(别名,函数,等等)。 ..)默认情况下全球可用 - 这毕竟是个人档案文件的主要目的。

不幸的是,没有范围修饰符允许您为配置文件加载 时只想存在的变量创建临时范围 - 甚至范围{{1在配置文件脚本中是有效的全局;同样,使用范围local也不是一种选择,因为配置文件的脚本范围 - 由于是点源的 - 全局范围。

一般来说,您可以将private(调用运算符)与脚本块一起用于在该块中创建限定为该块的变量,但这通常与创建全局可用< / em>配置文件中的定义,至少默认情况下 同样地,调用另一个没有点源的脚本,就像你自己的答案一样,默认情况下不会使其定义全局可用 可以通过明确指定全局范围 来创建 -dot-sourced脚本块/脚本的全局元素强>;例如:&& { $global:foo = 'Going global' }

那就是说,点源配置文件背后的基本原理可能是更容易使所有定义全局默认 ,从而定义概要文件的典型元素 - 别名,函数,驱动器映射,模块加载 - 更简单(无需指定显式范围)。
相比之下,全局变量不太常见,为了定义上面列出的典型元素,您通常不需要在配置文件中使用脚本级(以及全局)变量。

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

简单的解决方法在配置文件脚本中使用奇异的变量名称前缀,例如& { function global:bar { 'global func' } },以降低意外引用的风险(例如,__) 换句话说:变量仍然存在全局,但它们的外来名称通常不会导致问题。

然而,您的方法,即使它需要一些额外的工作,听起来像是一个强大的解决方法,这就是它的完整外观(使用PSv3 +语法):

$__profileVar1 = ...

请注意,我依赖于# 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 的默认行为,即仅在对象之间报告差异,并假设您没有尝试删除任何变量,仅报告添加的变量

请注意,虽然可以从配置文件的实际行为中推断,但它们确实是点源的 - 因为点源是将元素添加到当前范围的唯一方法(全球范围,在个人资料的情况下) - 这个事实并没有明确记录

以下是各种帮助主题(从PSv5开始)的片段,提供线索(强调我的):

来自Compare-Object

  

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

来自Get-Help about_Profiles

  

默认情况下,变量仅在其范围内可用   他们被创造了。

     

例如,您在函数中创建的变量是   仅在功能内可用。你的变量   脚本中的create仅在脚本中可用(除非   你点源脚本,将其添加到当前范围)。

来自Get-Help about_Variables

  

。点采购运营商      在当前范围内运行脚本以便执行任何功能,      别名和脚本创建的变量将添加到当前      范围。

来自Get-Help about_Operators

  

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

     

要向当前范围添加函数,请在前面键入点(。)和空格   函数调用中函数的路径和名称。

答案 1 :(得分: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."

这允许配置文件脚本导入包含全局变量的模块。这些变量将在当前会话期间继续存在。

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