Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Powershell - "Clear-Item variable:" vs "Remove-Variable"

When storing text temporarily in powershell variables at runtime, what is the most efficient way of removing a variables contents from memory when no longer needed?

I've used both Clear-Item variable: and Remove-Variable but how quickly does something get removed from memory with the latter vs nulling the memory contents with the former?

EDIT: I should have made it a little clearer why I am asking.

I am automating RDP login for a bunch of application VMs (application doesn't run as a service, outsourced developers, long story).

So, I am developing (largely finished) a script to group launch sessions to each of the VMs.

Idea is that the script function that stores credentials uses read-host to prompt for hostname then get-credentials to pick up domain/user/password.

The pass is then converted from secure-string using 256-bit key (runtime key unique to machine/user that stored the creds and runs the group launch).

The VMs name, domain, user and encrypted pass are stored in a file. When launching a session, the details are read in, password decrypted, details passed to cmdkey.exe to store \generic:TERMSRV credential for that VM, clear plaintext pass variable, launch mstsc to that host, a few seconds later remove the credential from windows credential store. (If I passed password to cmdkey.exe as anything other than plaintext, the RDP session would either receive incorrect or no credentials).

So, hence the question, I need the password In plaintext to exist in memory for as short a time as possible.

To keep security guys happy, the script itself is aes256 encrypted and a c# wrapper with its own ps host reads, decrypts and runs the script, so there is no plaintext source on the machine that runs this. (Encrypted source on a file share so effectively I have a kill switch, can simply replace encrypted script with another displaying a message that this app has been disabled)

like image 518
Graham Gold Avatar asked Dec 08 '12 22:12

Graham Gold


People also ask

How do you clear a variable value in PowerShell?

To delete a variable, along with its value, use Remove-Variable or Remove-Item . This cmdlet does not delete the values of variables that are set as constants or owned by the system, even if you use the Force parameter. If the variable that you are clearing does not exist, the cmdlet has no effect.

What is the $_ variable in PowerShell?

indicates that $_. is a variable. However, this is no ordinary variable. Instead, it is often referred to as a variable in the pipeline. In PowerShell, the word pipeline generally refers to a series of commands that have been joined together.


3 Answers

The only way I have been able to, with certainty, to clear variable data/content is to remove all variables running in the current session using:

Remove-Variable -Name * -ErrorAction SilentlyContinue

This removes all variables immediately. In fact, I add this to the end of some of my scripts, so that I can be sure that running another script with potentially the same name, will not have new data added and cause undesired results.

DRAWBACK: If you only need one variable cleared, which was in my case a few minutes ago, then you need to re-instantiate input variables required by your script.

like image 103
itmadez Avatar answered Oct 21 '22 10:10

itmadez


The most efficient way is to let garbage collection do its job. Remember, Powershell is all .NET, with its famous memory management. Always control your scope and make sure variables get out of scope as soon as they are not needed. For example, if temporary variables are needed inside loops, they will invalidate at loop's end automatically, so no need to worry about that, etc.

EDIT: Regarding your update, why not just do $yourPasswordVariable = $null? I think it would be much easier to understand. And it should be the fastest way to do it. Because Remove-Item and Clear-Item are kind of all-in-one handlers, they need to process some stuff first, before determining you really wanted to erase a variable.

like image 30
Neolisk Avatar answered Oct 21 '22 08:10

Neolisk


You can use a stopwatch to get the execution time for the commandlets. I think there is not really a time difference between these two cmdlets. I´m using normally "Remove-Item" because in my eyes it´s better to remove a variable complete.

$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()
like image 21
LaPhi Avatar answered Oct 21 '22 08:10

LaPhi