18

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

目前我正在做Remove-Variable -Name *,但它也试图删除所有系统变量,导致很多错误消息。

还有什么办法吗?

4

10 回答 10

32

由于所有系统变量都是只读或常量,因此您可以将错误静音:

Remove-Variable * -ErrorAction SilentlyContinue

但诚然,您可能应该排除一些:

Get-Variable -Exclude PWD,*Preference | Remove-Variable -EA 0
于 2013-07-16T15:07:07.220 回答
4

调用 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 $_})
于 2018-08-21T21:20:39.673 回答
2

不要删除所有用户变量,而是启动一个新的 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. 您可以在单独的脚本中对该命令进行编码,然后只调用该脚本,而不是使用真实代码调用相应的脚本。
于 2013-07-18T05:46:48.860 回答
1

这是一个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,您不必担心这一点。

于 2013-07-18T03:46:04.533 回答
1

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

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

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

于 2013-07-16T18:23:14.140 回答
0

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

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

于 2016-10-26T15:32:14.403 回答
0

使用乔伊的答案效果很好......也许太好了。例如,当我在 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
}

说的是...

  1. 记住我开始之前范围内的每个变量。
  2. 启动我的脚本。
  3. 删除我留在范围内的所有内容。

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


也许值得一提的是,在范围内留下重要变量的 VS Code 集成终端并不完美,对提出的问题的一些回应说,它们可能会更改$psEditor为某种常量,这样Remove-Variable就不会做这种意外破坏性的事情。

于 2021-12-10T22:17:51.330 回答
0

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

于 2021-04-05T19:46:20.033 回答
-1

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

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

然后删除不在 Don't Delete 列表中的变量。

于 2013-07-16T14:53:18.833 回答
-4

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

于 2013-07-16T14:51:07.470 回答