繁体   English   中英

powershell - 删除所有变量

[英]powershell - Remove all variables

我想在脚本开始时删除所有用户创建的变量。

目前我正在执行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:\>

您的变量也不会返回到调用实例中。

关于如何实际实现这一点,您有几种选择。

  1. 当然,您始终可以自己启动新实例:

    powershell -ExecutionPolicy Unrestricted -File myscript

  2. 您可以在单独的脚本中对该命令进行编码,然后仅调用该脚本,而不是带有真实代码的伴随脚本。

你不应该依赖这些变量。 任何未声明的东西都不会被使用。 如果您需要传递信息,请使用参数。

如果您遵守这一原则,您只需覆盖用户创建的变量并像从未存在过一样使用它。

这是企业最佳实践,可让您无限扩展脚本。 不仅在 Powershell 中,而且在任何可以具有全局变量的语言中,例如 Javascript。

这是一个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}}

警告:这不会删除 Powershell 主机创建的变量,这些变量指定了加载模块或执行创建变量的脚本的 InitialSessionState。 但是对于普通的 Powershell 和 powershell_ise,您不必担心。

我会将现有变量名称列表拉入脚本开头的数组中,然后删除脚本末尾的任何新添加的变量:

 ### 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!" }

您还可以考虑更改变量的范围。 例如,包含在循环或函数中的变量仅存在于该范围内。 只要变量不是在全局或脚本范围内创建的,它们就不会在脚本完成后持续存在。 然后您可以删除全局/脚本范围变量。 https://docs.microsoft.com/en-us/powershell/module/microsoft.powershell.core/about/about_scopes?view=powershell-7.1

使用乔伊的答案效果很好......也许太好了。 例如,当我在 Visual Studio Code 中使用时,它的$psEditor变量被删除,它的集成终端开始抛出错误

需要明确的是,我使用的是Get-Variable -Exclude PWD,*Preference | Remove-Variable -EA 0 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
}

说的是...

  1. 记住我开始之前作用域中的每个变量。
  2. 开始我的工作。
  3. 删除我留在范围内的所有内容。

这是一个很好的“让它不比你发现的更糟”的解决方法。


也许值得一提的是,将重要变量留在范围内的 VS Code 集成终端并不完美, 对所提出问题的一些回应表示,他们可能会将$psEditor更改$psEditor常量,以便Remove-Variable无法执行此操作意外破坏。

我想你可以列出你不想删除的所有变量。

$DontDelete = '$','?','^','args',...,'WhatIfPreference'

然后删除不在不要删除列表中的变量。

你不能。 您必须在脚本启动之前跟踪可用变量,并删除脚本执行后添加的任何变量。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM