PowerShell companion file paths: Script folder: PSScriptRoot, Build the companion path, Test from another folder

Load a File Beside a PowerShell Script with PSScriptRoot, Not the Current Folder

Fix relative file lookups in PowerShell scripts by anchoring a companion file to PSScriptRoot, then test from a different working folder.

If a PowerShell script can read its companion file only when you first change into the script’s folder, the lookup probably depends on the current location. Use $PSScriptRoot when the intended file lives beside the executing script. That makes the lookup independent of the folder from which you launch it; it does not grant access or make the file trustworthy.

Separate the script folder from the current location

Consider a script named Read-Companion.ps1 stored in a Tools folder, with a text file named settings.txt beside it. A relative lookup such as .\settings.txt refers to the current PowerShell location. Launching the script by its full path does not mean that location becomes the Tools folder.

Microsoft’s automatic variables documentation defines $PSScriptRoot as the full path of the executing script’s parent directory. It separately defines $PWD as the current location for the runspace. Those values answer different questions. Neither should be overwritten to repair this problem.

Build and read the companion path explicitly

Save the following example as Read-Companion.ps1 in your own disposable test folder. Create a plain text settings.txt beside it containing a harmless marker such as demo-setting. The script reads that file but does not create or modify it.

$configPath = Join-Path -Path $PSScriptRoot -ChildPath 'settings.txt'

if (-not (Test-Path -LiteralPath $configPath -PathType Leaf -ErrorAction Stop)) {
    throw "Companion file is missing or is not a file: $configPath"
}

$configText = Get-Content -LiteralPath $configPath -Raw -ErrorAction Stop
$configText

Join-Path constructs the intended path rather than relying on manual separator concatenation. -LiteralPath avoids interpreting square brackets in a parent folder name as wildcard syntax. The leaf check rejects a directory called settings.txt; an unreadable file can still fail at the read step. Stopping on errors prevents the script from quietly carrying on with absent configuration.

The last line emits text for this demonstration. In a real application, do not print configuration containing passwords or tokens. Reading text also does not validate a configuration format: parse and validate the required fields separately before acting on them. Never execute a downloaded settings file as a shortcut to parsing it.

Test from a different folder without changing the caller’s location

After saving the script and companion file, open another PowerShell window in a different filesystem folder. Invoke the script using its actual full path with the call operator. A quoted path alone is a string, not an invocation. For the invocation syntax, see using an explicit executable path in PowerShell; the same call operator also invokes a script path.

Confirm that the script reads the marker beside itself, even if the launch folder contains a different settings.txt. Then rename only the disposable companion file and repeat: the script should stop instead of falling back to another directory. Restore the test filename afterward. Finally, confirm that the caller’s location has not changed. This example never calls Set-Location, so it has no location change to undo.

Common questions and boundaries

Can I paste the example directly into the console? Save it as a script for this test. An interactive prompt does not provide the same executing-script context. A blank script-root value there is not evidence that the variable is broken.

Should I use MyInvocation instead? Not interchangeably. Microsoft distinguishes the automatic script-root variable from the PSScriptRoot property on MyInvocation, which describes the calling script rather than the current one.

Does this fix scheduled-task permissions? No. It fixes the intended base directory. The account running the task still needs read access, and the file must exist on that machine. It also does not override script execution policy; do not weaken organisational policy to run a test.

What about user-selected files? A file beside the script and a path deliberately supplied by a user are different interfaces. Keep user input explicit rather than silently redirecting every path to the script directory.

This tutorial is for educational purposes. Test with disposable files before production use. The site owner is not responsible for misuse, damage, data loss, or production issues. Delete only the test files you created once you finish.

Leave a Reply

Your email address will not be published. Required fields are marked *