我想在脚本开始时删除所有用户创建的变量。
目前我正在做Remove-Variable -Name *
,但它也试图删除所有系统变量,导致很多错误消息。
还有什么办法吗?
我想在脚本开始时删除所有用户创建的变量。
目前我正在做Remove-Variable -Name *
,但它也试图删除所有系统变量,导致很多错误消息。
还有什么办法吗?
由于所有系统变量都是只读或常量,因此您可以将错误静音:
Remove-Variable * -ErrorAction SilentlyContinue
但诚然,您可能应该排除一些:
Get-Variable -Exclude PWD,*Preference | Remove-Variable -EA 0
调用 PowerShell 的新实例,获取内置变量,然后删除不属于的所有其他内容。
$ps = [PowerShell]::Create()
$ps.AddScript('Get-Variable | Select-Object -ExpandProperty Name') | Out-Null
$builtIn = $ps.Invoke()
$ps.Dispose()
$builtIn += "profile","psISE","psUnsupportedConsoleApplications" # keep some ISE-specific stuff
Remove-Variable (Get-Variable | Select-Object -ExpandProperty Name | Where-Object {$builtIn -NotContains $_})
不要删除所有用户变量,而是启动一个新的 PowerShell 实例:
PS C:\> $x = 10
PS C:\> $y = 50
PS C:\> $blah = 'text'
PS C:\> Write-host $x $y $blah
10 50 text
PS C:\> powershell
Windows PowerShell
Copyright (C) 2009 Microsoft Corporation. All rights reserved.
PS C:\> Write-host $x $y $blah
PS C:\>
用户定义的变量不会延续到新实例中。
PS C:\> $bleh = 'blue'
PS C:\> Write-Host $bleh
blue
PS C:\> exit
PS C:\> Write-host $bleh
PS C:\>
您的变量也不会带回调用实例。
在如何实际实现这一点方面,您有几个选择。
当然,您始终可以自己启动新实例:
powershell -ExecutionPolicy Unrestricted -File myscript
这是一个hack,它将删除除 $profile 中创建的变量之外的所有变量。请注意,这需要几秒钟的运行时间,您很有可能以更有效的方式实现最终目标。您必须调整 select 语句中的“15”以对应于您的配置文件脚本吐出的行数。或者您可以修改它以从 gv (get-variable) 中搜索第一行。
$x=powershell -nologo -command "gv|out-string"
$y=($x|select -skip 15) -split "\s+",2
$varnames = $(for ($i=0;$i -lt $y.length; $i+=2) { $y[$i]})
rv i,x,y
gv | % {if ($varnames -notcontains $_.name) {rv $_.name -EA 0}}
警告:这不会删除由指定 InitialSessionState 的 Powershell 主机创建的变量,该 InitialSessionState 加载模块或执行创建变量的脚本。但是,对于普通的 Powershell 和 powershell_ise,您不必担心这一点。
你不应该依赖这些变量。任何未声明的内容都不会被使用。如果您需要传递东西,请使用参数。
如果您遵守此原则,您将覆盖您的用户创建的变量并像从未存在过一样使用它。
这是企业最佳实践,可让您无限扩展脚本。不仅在 Powershell 中,而且在任何可能具有全局变量的语言中,例如 Javascript。
我会在脚本开头将现有变量名称列表拉入一个数组,然后在脚本末尾删除所有新添加的变量:
### Start of script (store list of existing variable names)
$ExistingVariables = Get-Variable | Select-Object -ExpandProperty Name
<#
Script contents go here
#>
### End of script (remove new variables)
$NewVariables = Get-Variable | Select-Object -ExpandProperty Name | Where-Object {$ExistingVariables -notcontains $_ -and $_ -ne "ExistingVariables"}
if ($NewVariables)
{
Write-Host "Removing the following variables:`n`n$NewVariables"
Remove-Variable $NewVariables
}
else
{
Write-Host "No new variables to remove!"
}
使用乔伊的答案效果很好......也许太好了。例如,当我在 Visual Studio Code 中使用时,它的$psEditor
变量被删除,它的集成终端开始抛出错误。
需要明确的是,我Get-Variable -Exclude PWD,*Preference | Remove-Variable -EA 0
在启动脚本的其余部分之前将其用作脚本的一部分,以确保它处于干净的状态,但它过度清洁了。
我通过添加$psEditor
到例外列表中来解决这个问题,如下所示:
Get-Variable -Exclude PWD,*Preference,psEditor | Remove-Variable -EA 0
但这是一种打地鼠的方法,而且似乎有更好的方法,具体取决于您对相关脚本的控制程度。
例如,这是我在 GitHub 中提出的问题中来自 SeeminglyScience 的一个很好的解决方案,尽管它基本上简化了 ferrell_io 答案中的逻辑,并进行了一些重要的改进:
$existingVariables = Get-Variable
try {
# your script here
} finally {
Get-Variable |
Where-Object Name -notin $existingVariables.Name |
Remove-Variable
}
说的是...
这是一个很好的“让它不会比你发现的更糟”的解决方法。
也许值得一提的是,在范围内留下重要变量的 VS Code 集成终端并不完美,对提出的问题的一些回应说,它们可能会更改$psEditor
为某种常量,这样Remove-Variable
就不会做这种意外破坏性的事情。
您还可以考虑更改变量的范围。例如,包含在循环或函数中的变量仅存在于该范围内。只要变量不是在全局或脚本范围内创建的,它们就不会在脚本完成后持续存在。然后,您可以删除全局/脚本范围变量。https://docs.microsoft.com/en-us/powershell/module/microsoft.powershell.core/about/about_scopes?view=powershell-7.1
我想您可以列出所有不想删除的变量。
$DontDelete = '$','?','^','args',...,'WhatIfPreference'
然后删除不在 Don't Delete 列表中的变量。
你不能。您必须在脚本启动之前跟踪可用变量,并删除脚本执行后添加的任何变量。