8

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

我已经使用了两者Clear-Item variable:Remove-Variable但是使用后者从内存中删除某些内容与使用前者将内存内容清零的速度有多快?

编辑:我应该更清楚地说明我为什么要问。

我正在为一堆应用程序虚拟机自动 RDP 登录(应用程序不作为服务运行,外包开发人员,长篇大论)。

因此,我正在开发(基本完成)一个脚本,用于将启动会话分组到每个 VM。

想法是存储凭据的脚本函数read-host用于提示输入主机名,然后get-credentials获取域/用户/密码。

然后使用 256 位密钥(存储凭据并运行组启动的机器/用户独有的运行时密钥)从安全字符串转换通行证。

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

所以,因此问题是,我需要明文密码尽可能短地存在于内存中。

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

4

5 回答 5

7

我能够确定地清除变量数据/内容的唯一方法是使用以下方法删除当前会话中运行的所有变量:

Remove-Variable -Name * -ErrorAction SilentlyContinue

这会立即删除所有变量。事实上,我将它添加到我的一些脚本的末尾,以便我可以确定运行另一个可能具有相同名称的脚本,不会添加新数据并导致不希望的结果。

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

于 2016-03-02T18:21:18.197 回答
5

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

编辑:关于您的更新,为什么不这样做$yourPasswordVariable = $null呢?我认为这会更容易理解。这应该是最快的方法。因为Remove-ItemandClear-Item是一种多合一的处理程序,它们需要先处理一些东西,然后才能确定你真的想删除一个变量。

于 2012-12-09T00:46:11.370 回答
4

您可以使用秒表来获取命令行开关的执行时间。我认为这两个 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()
于 2012-12-09T00:32:30.017 回答
2

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

于 2012-12-09T01:48:25.713 回答
0

要测量运行脚本块和 cmdlet 所需的时间,请使用Measure-Command

于 2014-04-11T07:19:00.177 回答