Powershell - “Clear-Item变量:”vs“Remove-Variable”

时间:2012-12-08 22:56:18

标签: powershell resource-cleanup

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

我已经同时使用了Clear-Item variable:Remove-Variable,但是使用后者将内存内容从内存中移除后,有多快会将内容删除?

编辑:我应该让我更清楚为什么要问。

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

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

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

然后使用256位密钥从安全字符串转换传递(对于存储信用卡并运行组启动的机器/用户唯一的运行时密钥)。

VM名称,域,用户和加密的传递存储在文件中。启动会话时,会读入详细信息,解密密码,将详细信息传递给cmdkey.exe以存储该VM的凭据\generic:TERMSRV,清除明文传递变量,将mstsc启动到该主机,几秒钟后删除来自Windows凭证存储的凭据。 (如果我将密码作为明文以外的其他任何内容传递给cmdkey.exe,则RDP会话将收到错误或无凭据。)

因此,问题是,我需要密码以明文的形式存在于内存中尽可能短的时间。

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

5 个答案:

答案 0 :(得分:5)

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

编辑:关于您的更新,为什么不做$yourPasswordVariable = $null?我认为这将更容易理解。它应该是最快的方式。由于Remove-ItemClear-Item是一体化处理程序,因此在确定您确实要删除变量之前,需要先处理一些内容。

答案 1 :(得分:5)

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

Remove-Variable -Name * -ErrorAction SilentlyContinue

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

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

答案 2 :(得分:4)

您可以使用秒表来获取命令行开关的执行时间。我认为这两个cmdlet之间没有真正的时间差异。我通常使用“Remove-Item”,因为在我看来最好删除变量。

$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()

答案 3 :(得分:2)

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

答案 4 :(得分:0)

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