The PoSH Student

April 29, 2009

Cleaning up mid-script

Filed under: PowerShell — Tags: , , — Nathan @ 4:49 pm

As some of my scripts have really started to grow, and often include some rather large datasets residing in variables, I noticed that the system would bog down after a while from all the memory in use. Simple enough, I thought, I’ll just get rid of those variables with Remove-Variable. Great in concept; but it doesn’t affect memory usage at all.

A little digging showed that PowerShell is not so great at Garbage Collection; it apparently waits to Collect until it needs to, and never seems to think it needs to. Great. Fortunately, it has direct access to .NET functions, so you can just run Garbage Collection with:

[gc]::Collect()

This has the nice benefit of speeding up your system, but it can take a while to run. So I added a simple Function to my functions.ps1 file which will allow me to run this when it’s needed:

function Clean {
	foreach ($arg in $args) {
		Remove-Variable $arg -Scope script
		}
	[gc]::Collect()
	}

You can send any number of variables to this function, but, like using Remove-Variable alone, you have to send it variables names without the leading “$”. (If you wonder why, run Get-Variable and look at the variable names, or consider the difference between “$variable” and ‘variable’.) It will remove all those variables, then run garbage collection. Not quite an everyday command, but useful after working with large datasets or other memory hogs.

April 22, 2009

Pause until “then”

Filed under: PowerShell — Tags: , , , , — Nathan @ 1:39 pm

When I’m testing things, sometimes I want to run a test, but not quite right now.

There are a lot of suggestions out there on how to use Scheduled Tasks to launch a .ps1 file; basic, wrapped in a .vbs, or even a self-scheduling script. That’s helpful, as long as you want to run it in a separate process.

If you want to just pause for n seconds in a script, there’s always:

Start-Sleep n

Or if you want to pause until a key is pressed, there are a few options:
$null = $Host.UI.RawUI.ReadKey("NoEcho,IncludeKeyDown")
$host.UI.RawUI.ReadKey() | Out-Null

But what I really wanted was to have the shell wait until a certain timeframe, then run. I got to thinking about Do…Until loops, which I usually see used to iterate through an array, and thought that with a Sleep command, I could make one just do nothing until a certain time. To make sure it would work, I tested it by having it tell me the time at each loop until it stopped:
do {get-date -displayhint time; sleep 10} until ((Get-Date) -ge "1:51 PM")
write-host "it worked"

Sure enough, it behaved as expected:
PS C:\> do {get-date -displayhint time; sleep 10} until ((Get-Date) -ge "1:51 PM")
1:49:55 PM
1:50:05 PM
1:50:15 PM
1:50:25 PM
1:50:35 PM
1:50:45 PM
1:50:55 PM
PS C:\> write-host "it worked"
it worked 

Sweet. Of course, I normally will want to wait more than 10 seconds per loop, and not actually say anything while waiting, but it’s pretty easy to make this into a function. This is a too-simple function that will wait until the time (or date) you send it. If you want the pause interval to be more or less than 600 seconds (10 minutes) you can send that as a secondary parameter. The downside to this: it won’t currently work for a time or date range, or for times after midnight. But it’s a fun hack anyway.
function Wait-Until {
	Param ($until,$interval = 600)
	do {sleep $interval} until ((Get-Date) -ge $until)
	}

Theme: Silver is the New Black. Blog at WordPress.com.

Follow

Get every new post delivered to your Inbox.