Runspace Contamination: What is it and how do I avoid it?

We are all creatures of habit. People who write code are even more so because we have copy-and-paste. As a result, any code you write usually reuses the same variable names.

For a counter, you use $ctr; for a flag, you might use $bFlag. A variable to determine if you need to exit a loop may be called $bExitLoop in virtually all of your scripts. That can be a problem.

Start up the ISE and do this:
image

After you hit Enter, any trace that ever happened is gone from the screen. Now imagine that, instead of typing that statement, you ran a 3000+ line script that sets a number of variables, including bExitLoop. And that script ran three hours ago, before lunch, and you ran two others after that, which are entirely unrelated. Would you remember every variable that was set? Did you restart the ISE?

Now load a script doing this:

image

When you run this script, it does nothing—nothing at all. In this little example, it is very easy to see why and what you need to do. If the script you loaded is another 3000 or more line script, and somewhere deep in there this variable is used, it is much harder to find.

So, your runspace is contaminated. It is littered with variables set by any previous script you ran. Any script you run in this same runspace is compromised by this. Your script running correctly here does not mean it will run correctly elsewhere. This scenario is not limited to the ISE. You can produce the same effect in a console—the ISE and console reuse the same runspace. Yes, I know the ISE has a ‘File’ -> ‘New PowerShell Tab’ item, which creates a new runspace. But that requires you to know that you need a new runspace.

If this is a complex script, you may spend an afternoon debugging, only to find out that restarting the ISE or console would have helped the issue. None of this is intended to make the ISE, PowerShell, the console, or any other tool look bad. They all do what they were designed to do—avoiding runspace contamination was just not on that list.

The points outlined above illustrate why PowerShell Studio and PrimalScript always run your script in a new process and, therefore, in a new runspace. If your script relies on previously initialized variables, you will find out quickly that these variables have not been set. If previously set variables can influence your script, packaging it as an executable will avoid that. Of course, if you select “Run in console” in our products, you will get the contamination effect. But since that requires extra effort, we assume you know why you are doing that.

But, you say, it is very convenient to preset variables in the ISE for testing. You can set variables to different values, run your script and see what it does, which is precisely why the ISE does not reset your runspace—to allow you to experiment.

How can you do that in SAPIEN products? It is actually pretty simple. You can add a little piece of code to the top of your script.

A while back we introduced variables which allow you to distinguish how and where your script is running. Please see this article.

image

When debugging, this code will set your variables to your desired test values, and you can easily change them at will for each run.

This code can stay in place and will not affect your script in any way when you run it in a console, the ISE, packaged as an executable, or even when running on another computer. When you return to it in six months, you will see what you used to test this script, whereas your console or ISE presets will be long forgotten. Unless, of course, you still have that Post-It note.

Having this in your script will also benefit the next person having to edit your code. Of course, you could use comments, but comments do not affect code behavior. Because this piece of code is in a particular script and specific to that script, it will also not influence or contaminate any other script you create. Each script can have its own testing or debugging presets and will not create unwanted side effects.

Feedback

Please let us know in the comments if you have ever experienced this issue or if there is anything else we can do to make this better.