在运行时临时在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开关,可以简单地用另一个加密脚本替换显示此应用已被禁用的消息)
答案 0 :(得分:5)
最有效的方法是让垃圾收集完成它的工作。请记住,Powershell是所有.NET,其着名的内存管理。始终控制范围并确保变量在不需要时立即超出范围。例如,如果循环内部需要临时变量,它们将在循环结束时自动失效,因此无需担心等等。
编辑:关于您的更新,为什么不做$yourPasswordVariable = $null
?我认为这将更容易理解。它应该是最快的方式。由于Remove-Item
和Clear-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