Powershell-”的;清除项目变量:";vs";删除变量";

Powershell-”的;清除项目变量:";vs";删除变量";,powershell,resource-cleanup,Powershell,Resource Cleanup,在运行时将文本临时存储在powershell变量中时,当不再需要时,从内存中删除变量内容的最有效方法是什么 我使用了Clear Item variable:和Remove variable,但是使用后者从内存中删除某些内容与使用前者清空内存内容的速度有多快 编辑:我应该说得更清楚一点我为什么要问这个问题 我正在为一堆应用程序虚拟机(应用程序不是作为服务运行的,外包的开发人员,说来话长)自动化RDP登录 因此,我正在开发(基本完成)一个脚本,将启动会话分组到每个虚拟机 其思想是,存储凭据的脚本函数

在运行时将文本临时存储在powershell变量中时,当不再需要时,从内存中删除变量内容的最有效方法是什么

我使用了
Clear Item variable:
Remove variable
,但是使用后者从内存中删除某些内容与使用前者清空内存内容的速度有多快

编辑:我应该说得更清楚一点我为什么要问这个问题

我正在为一堆应用程序虚拟机(应用程序不是作为服务运行的,外包的开发人员,说来话长)自动化RDP登录

因此,我正在开发(基本完成)一个脚本,将启动会话分组到每个虚拟机

其思想是,存储凭据的脚本函数使用
读取主机
提示输入主机名,然后
获取凭据
获取域/用户/密码

然后使用256位密钥(存储Cred并运行组启动的计算机/用户唯一的运行时密钥)从安全字符串转换密码

VMs名称、域、用户和加密密码存储在一个文件中。启动会话时,将读取详细信息,对密码进行解密,并将详细信息传递到
cmdkey.exe
以存储该VM的
\generic:TERMSRV
凭据,清除明文pass变量,将mstsc启动到该主机,几秒钟后从windows凭据存储中删除凭据。 (如果我以明文以外的任何形式向cmdkey.exe传递密码,RDP会话将接收不正确或没有凭据)

因此,问题就来了,我需要明文密码在内存中存在尽可能短的时间


为了让安全人员高兴,脚本本身是aes256加密的,并且有一个带有自己ps主机的c#包装器读取、解密并运行脚本,因此运行该脚本的机器上没有明文源。(文件共享上的加密源非常有效,我有一个kill开关,可以简单地用另一个显示此应用已禁用消息的脚本替换加密脚本)

您可以使用秒表获取commandlet的执行时间。我认为这两个cmdlet之间实际上没有时间差。我通常使用“删除项”,因为在我看来,最好删除一个完整的变量

$a = "TestA"
$b = "TestB"
$c = "TestC"
$d = "TestD"

$time = New-Object system.Diagnostics.Stopwatch  

Start-Sleep 1
$time.Start() 
$time.Stop()
$system = $time.Elapsed.TotalMilliseconds
Write-Host "Stopwatch StartStop" $system
$time.Reset()

Start-Sleep 1
$time.Start() 
Clear-Item Variable:a
$time.Stop()
$aTime = $time.Elapsed.TotalMilliseconds - $system
Write-Host "Clear-Item in " $aTime
$time.Reset()

Start-Sleep 1
$time.Start() 
Remove-Variable b
$time.Stop()
$bTime  = $time.Elapsed.TotalMilliseconds - $system
Write-Host "Remove-Variable in " $bTime
$time.Reset()

Start-Sleep 1
$time.Start() 
Clear-Item Variable:c
$time.Stop()
$cTime = $time.Elapsed.TotalMilliseconds - $system
Write-Host "Clear-Item in " $cTime
$time.Reset()

Start-Sleep 1
$time.Start() 
Remove-Variable d
$time.Stop()
$dTime  = $time.Elapsed.TotalMilliseconds - $system
Write-Host "Remove-Variable in " $dTime
$time.Reset()

最有效的方法是让垃圾收集完成它的工作。请记住,Powershell完全是.NET,具有著名的内存管理功能。始终控制您的范围,并确保变量在不需要时立即超出范围。例如,若在循环中需要临时变量,它们将在循环结束时自动失效,所以无需担心,等等


编辑:关于您的更新,为什么不直接执行
$yourPasswordVariable=$null
?我想这会更容易理解。这应该是最快的方法。由于
Remove Item
Clear Item
是一种多功能处理程序,因此它们需要先处理一些内容,然后才能确定是否确实要删除变量。

这两种方法都能有效地删除对.NET对象的“a”引用。现在,如果该引用是对该对象的最后一次引用,那么GC将确定何时收集该对象的内存。但是,如果不再需要该变量,则使用
删除变量
也允许最终收集与
System.Management.Automation.PSVariable
对象关联的内存。

测量运行脚本块和cmdlet所需的时间,使用
Measure命令

清除变量数据/内容的唯一方法是使用以下命令删除当前会话中运行的所有变量:

Remove-Variable -Name * -ErrorAction SilentlyContinue
这会立即删除所有变量。事实上,我将此添加到一些脚本的末尾,这样我就可以确保运行另一个可能具有相同名称的脚本时,不会添加新数据并导致不希望的结果


缺点:如果您只需要清除一个变量,这是我几分钟前的情况,那么您需要重新实例化脚本所需的输入变量。

我回到办公室后会处理这个问题,请参见编辑我的问题以了解为什么速度很重要:-)在您的特殊情况下,我的建议是覆盖变量。您可以使用[System.gc]::Collect()触发gc,但这不是一个好主意。因此,我认为覆盖变量是最好的解决方案:-)回到办公室后,我会玩弄范围界定,请参见编辑我的问题,以了解为什么速度很重要:-)酷,当您解释清楚项和删除变量的工作原理时是有意义的!我认为这是关键,如果是的话,你能强迫GC立即运行一个或多个变量,并确保它们不再在内存中吗?有关其重要性的信息,请参见编辑:-)您完全没有抓住要点-这与cmdlet的运行速度无关,而是与命令执行后内存的清除速度有关-这不是measure命令可以测量的。