Rss

Common Get-ScriptDirectory in Powershell doesn’t always work

This function has been written dozens of times, in dozens of places, by dozens of bloggers, but I keep finding myself looking for it, so I thought I’d make myself a note. But I also discovered that there’s a problem with it.

If you’re writing a script in a module, it’s easy to use $PsScriptRoot  to get the current script path. For others situations there’s:

This function, and ones like it, appear in loads of blog posts, and it generally solves the problem, but it doesn’t always work, though, as it contains a flaw.

The problem is  -Scope 1. The this switch tells the script to look at the parent scope. This works as long as you have the Get-ScriptDirectory function at the top level of your script and you call it from that top level.

Here’s an example script demonstrating the problem:

Invoked as: PS> ./invoctest.ps1you get:

In Script (scope 1): []
In Script (scope 0): [F:tempinvoctest.ps1]
In Script (scope script): [F:tempinvoctest.ps1]
In t() (scope 1): [F:tempinvoctest.ps1]
in q()
In t() (scope 1): []
In t2() (scope script): [F:tempinvoctest.ps1]
in q2()
In t2() (scope script): [F:tempinvoctest.ps1]

Notice how when the call to t() is nested inside q() the function breaks, and you get nothing. The reason is that -Scope 1 is no longer looking at the script scope, but looking at the scope inside function t(). You’d need to have -Scope 2 if the function t() is invoked from inside q(). The higher the nesting level the higher the value to give to -Scope. 

You could look at the call stack, if you wanted to, but my script above already includes the answer. You need to use the “script” option for -Scope. That will ensure you always get the correct invocation variable.

This even works when the script is dot-sourced, or run in a debugger, like in PowerGUI.
The corrected function is therefore:

 

 

Share on Google+0Share on Facebook0Digg thisShare on Reddit0Share on StumbleUpon0Share on Tumblr0Tweet about this on TwitterPin on Pinterest0Share on LinkedIn0Email this to someone

Leave a Reply