7

Is it possible to test for the existence of a script-scoped variable in PowerShell?

I've been using the PowerShell Community Extensions (PSCX) but I've noticed that if you import the module while Set-PSDebug -Strict is set, an error is produced:

The variable '$SCRIPT:helpCache' cannot be retrieved because it has not been set.
At C:\Users\...\Modules\Pscx\Modules\GetHelp\Pscx.GetHelp.psm1:5 char:24

While investigating how I might fix this, I found this piece of code in Pscx.GetHelp.psm1:

#requires -version 2.0

param([string[]]$PreCacheList)

if ((!$SCRIPT:helpCache) -or $RefreshCache) {
    $SCRIPT:helpCache = @{}
}

This is pretty straight forward code; if the cache doesn't exist or needs to be refreshed, create a new, empty cache. The problem is that calling $SCRIPT:helpCache while Set-PSDebug -Strict is in force casues the error because the variable hasn't been defined yet.

Ideally, we could use a Test-Variable cmdlet but such a thing doesn't exist! I thought about looking in the variable: provider but I don't know how to determine the scope of a variable.

So my question is: how can I test for the existence of a variable while Set-PSDebug -Strict is in force, without causing an error?

1
  • 3
    If you're on PowerShell 2.0, I would recommend using Set-StrictMode -version 2.0 as it will catch additional potential issues. Commented May 4, 2010 at 15:12

3 Answers 3

5

Use test-path variable:SCRIPT:helpCache

if (!(test-path variable:script:helpCache)) {
  $script:helpCache = @{}
}

This works for me without problems. Checked using this code:

@'
Set-PsDebug -strict
write-host (test-path variable:script:helpCache)
$script:helpCache = "this is test"
write-host (test-path variable:script:helpCache) and value is $script:helpCache
'@ | set-content stricttest.ps1

.\stricttest.ps1
Sign up to request clarification or add additional context in comments.

4 Comments

I added an example that really works for me. If you have any problems, I need to know what the problems are ;)
This is probably the best way. The trick with [h]elpCache is faster (just a little bit) but it is hacky. Also, Test-Path way is much better when a variable’s name is a variable itself, i.e. Test-Path variable:script:$name
FWIW, using test-path variable: is the approach we usually take in PSCX. I'll take a look at this issue later tonight.
@stej That does not work with the $env:OS variable. How do I test if $env:OS is defined ?
4

Try this trick:

Get-Variable [h]elpCache -Scope Script

It should not throw or emit any errors because we use a wildcard [h]elpCache. On the other hand this kind of a wildcard is a literal name de facto.

1 Comment

Yes, this way is hacky. @stej proposes a better solution. Still, the trick with fake wildcard is useful in many cases, e.g. for Get-Process (there is no Test-Path alternative for processes).
1

You can use Get-Variable with the -Scope parameter. This cmdlet will (by default at least) not return only the variable's value but a PSVariable object and will throw an exception if the variable isn't found:

Get-Variable foo -Scope script

3 Comments

@Johannes Thanks for the answer. It's the exception that's thrown by Get-Variable that I'm trying to avoid though. I can do that with try/catch obviously, but I'd like to know if there's a more readable way that doesn't splurge red text into my output window. :)
Get-Variable -ErrorAction SilentlyContinue should do the trick. You can check the result of the command call. N.B. The error is still added to the $Error list, unfortunately.
@Roman Kuzmin The -ErrorAction trick didn't help. Shame, because that seems like a good solution.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.