Powershell Profile脚本是否源点源?

我正在使用的Microsoft.Power
Shell_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

最佳答案 是的,PowerShell配置文件是按设计点源的,因为这是允许它们中包含的定义(别名,函数,…)默认全局可用的 – 毕竟这是配置文件的主要用途.

遗憾的是,没有范围修饰符允许您为加载配置文件时只想存在的变量创建临时范围 – 即使范围本地在配置文件脚本中实际上是全局的;类似地,使用范围私有也不是一个选项,因为配置文件的脚本范围 – 由于是点源的 – 是全局范围.

一般来说,你可以使用& (调用操作符)带有一个脚本块,用于在该块中创建作用于该块的变量,但这通常与在配置文件中创建全局可用定义不一致,至少在默认情况下是这样.
同样,调用另一个没有点源的脚本,就像你自己的答案一样,默认情况下不会使其定义全局可用.
但是,您可以通过明确指定全局范围,从非点源脚本块/脚本创建全局元素;例如:& {$global:foo =’走向全球’},或者& {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:

A Windows PowerShell profile is a script that runs when Windows PowerShell
starts. You can use the profile as a logon script to customize the
environment. You can add commands, aliases, functions, variables, snap-ins,
modules, and Windows PowerShell drives.
You can also add other
session-specific elements to your profile so they are available in every
session without having to import or re-create them.

来自Get-Help about_Variables:

By default, variables are available only in the scope in which
they are created.

For example, a variable that you create in a function is
available only within the function. A variable that you
create in a script is available only within the script (unless
you dot-source the script, which adds it to the current scope
).

来自Get-Help about_Operators:

. Dot sourcing operator
Runs a script in the current scope so that any functions,
aliases, and variables that the script creates are added to the current
scope.

来自Get-Help about_Scopes

But, you can add a script or function to the current scope by using dot
source notation. Then, when a script runs in the current scope, any
functions, aliases, and variables that the script creates are available
in the current scope
.

To add a function to the current scope, type a dot (.) and a space before
the path and name of the function in the function call.

点赞