8

実行時にPowerShell変数にテキストを一時的に保存する場合、不要になったときに変数の内容をメモリから削除する最も効率的な方法は何ですか?

私は両方を使用Clear-Item variable:しましRemove-Variableたが、前者でメモリの内容を無効にするのに対して、後者で何かがメモリから削除されるのはどれくらいの速さですか?

編集:私が尋ねている理由をもう少し明確にすべきでした。

多数のアプリケーションVMのRDPログインを自動化しています(アプリケーションはサービスとして実行されない、外部委託された開発者、長い話)。

そのため、各VMへの起動セッションをグループ化するスクリプトを開発しています(ほぼ完成しています)。

クレデンシャルを保存するスクリプト関数はread-host、ホスト名の入力を求めてからget-credentials、ドメイン/ユーザー/パスワードを取得するために使用するという考え方です。

次に、パスは256ビットキー(資格情報を保存してグループ起動を実行するマシン/ユーザーに固有のランタイムキー)を使用してセキュア文字列から変換されます。

VMの名前、ドメイン、ユーザー、および暗号化されたパスはファイルに保存されます。セッションを起動すると、詳細が読み込まれ、パスワードが復号化され、そのVMのクレデンシャルcmdkey.exeを保存するために詳細が渡され\generic:TERMSRV、プレーンテキストのパス変数がクリアされ、そのホストに対してmstscが起動され、数秒後にWindowsクレデンシャルストアからクレデンシャルが削除されます。(パスワードをプレーンテキスト以外のものとしてcmdkey.exeに渡した場合、RDPセッションは誤った資格情報を受け取るか、資格情報を受け取りません)。

したがって、質問です。可能な限り短時間メモリに存在するために、平文のパスワードが必要です。

セキュリティ担当者を満足させるために、スクリプト自体はaes256で暗号化され、ac#ラッパーと独自のpsホストがスクリプトを読み取り、復号化して実行するため、これを実行するマシンにはプレーンテキストソースはありません。(ファイル共有の暗号化されたソースなので、効果的にキルスイッチがあり、暗号化されたスクリプトを、このアプリが無効になっているというメッセージを表示する別のスクリプトに置き換えることができます)

4

5 に答える 5

7

変数のデータ/コンテンツを確実にクリアできる唯一の方法は、以下を使用して現在のセッションで実行されているすべての変数を削除することです。

Remove-Variable -Name * -ErrorAction SilentlyContinue

これにより、すべての変数がすぐに削除されます。実際、これを一部のスクリプトの最後に追加しているので、同じ名前の可能性がある別のスクリプトを実行しても、新しいデータが追加されて、望ましくない結果が生じることはありません。

ドローバック: 1つの変数のみをクリアする必要がある場合(私の場合は数分前)、スクリプトに必要な入力変数を再インスタンス化する必要があります。

于 2016-03-02T18:21:18.197 に答える
5

最も効率的な方法は、ガベージコレクションにその仕事をさせることです。Powershellはすべて.NETであり、有名なメモリ管理機能を備えていることを忘れないでください。常にスコープを制御し、変数が不要になったらすぐにスコープから外れるようにします。たとえば、ループ内で一時変数が必要な場合、ループの最後で自動的に無効になるため、心配する必要はありません。

編集:あなたのアップデートに関して、なぜそれをしないの$yourPasswordVariable = $nullですか?ずっとわかりやすいと思います。そして、それはそれを行うための最速の方法でなければなりません。Remove-ItemClear-Itemは一種のオールインワンハンドラーであるため、変数を本当に消去したいかどうかを判断する前に、まずいくつかのものを処理する必要があります。

于 2012-12-09T00:46:11.370 に答える
4

ストップウォッチを使用して、コマンドレットの実行時間を取得できます。これら2つのコマンドレットの間に実際には時間差はないと思います。私の目には変数を完全に削除する方が良いので、私は通常「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()
于 2012-12-09T00:32:30.017 に答える
2

どちらも、.NETオブジェクトへの「a」参照を効率的に削除します。これで、その参照がオブジェクトへの最後の参照である場合、GCはそのオブジェクトのメモリがいつ収集されるかを決定します。ただし、変数が不要になった場合は、を使用Remove-Variableして、オブジェクトに関連付けられたメモリSystem.Management.Automation.PSVariableも最終的に収集できるようにします。

于 2012-12-09T01:48:25.713 に答える
0

スクリプトブロックとコマンドレットの実行にかかる時間を測定するには、次を使用します。Measure-Command

于 2014-04-11T07:19:00.177 に答える