Running $PSScriptRoot in Selected Code

by Jul 15, 2022

One of the big pitfalls in PowerShell code is the automatic variable $PSScriptRoot which always holds the path to the folder the current script is located. This however requires that (a) the current script is in fact already saved to file, and (b) you are executing the entire file, i.e., by pressing F5.

When you execute only a selection of code using F8, even if you select the entire code, $PSScriptRoot is empty, and your selected code will run into errors because of this.

In the PowerShell ISE, however, it is simple to add a workaround to enable running $PSScriptRoot in selected code. Here is the code that you need to run:


function Invoke-Selection
{ 
    try
    {
        # get the selected text:
        $selectedText = $psise.CurrentFile.Editor.SelectedText
        # if no text was selected...
        if ($selectedText.Length -eq 0) {
            # ...select the line the caret is in and get this line instead: 
            $psise.CurrentFile.Editor.SelectCaretLine() 
            $selectedText = $psise.CurrentFile.Editor.SelectedText
        }

        # try and parse the code
        $sb = [ScriptBlock]::Create($selectedText)
    
        # get the missing variable content from the underlying file:
        $currentFile = $psise.CurrentFile.FullPath
        $currentFolder = Split-Path -Path $currentFile
    
        # append the selected code with these automatic variables, and set them:
        $runcode = @"
        `$PSCommandPath = '$currentFile'
        `$PSScriptRoot = '$currentFolder'
        $selectedText
"@
        # turn text into script block...
        $scriptblock = [ScriptBlock]::Create($runcode)
        # ...and execute it without private scope:
        . $scriptblock
    
    }
    catch
    {
        throw $_.Exception
    }

}
$null = $psise.CurrentPowerShellTab.AddOnsMenu.Submenus.Add('ExecuteSelection', {. Invoke-Selection}, 'SHIFT+F8') 

The code adds a new command to ISE that can be invoked by pressing CTRL+F8. Now, when you select code, and you would like to run it even though it contains $PSScriptRoot, simply press CTRL+F8 instead of F8, and it will run.

The key shortcut invokes the function Invoke-Selection. This function will take the currently selected text, add the missing automatic variables $PSScriptRoot and $PSCommandPath to the code and define these based on the current file path of the current script. Then it invokes the script block.

This way you now can debug and demo any selected code, even if it contains automatic variables. Just make sure you saved your script somewhere so PowerShell knows which locations your code is referring to.


Twitter This Tip! ReTweet this Tip!