1 minute read

In this post we’ll see how to resolve a file or directory path, even if it does not exist.

Backstory

While testing my tiPS PowerShell module with Pester, I ran into a scenario where I wanted to mock out a function which returned a path to a configuration file. Pester has a built-in PSDrive (see MS docs) called TestDrive, which is a temporary drive that is created for the duration of the test (see the docs here) and automatically cleaned up when the tests complete. So rather than hardcoding a local path on disk, you can use a path like TestDrive:/config.json.

The problem was that the .NET methods, like System.IO.File.WriteAllText() and System.IO.File.ReadAllText(), do not work with the TestDrive: PSDrive, as they are unable to resolve the path. The Set-Content and Get-Content cmdlets work fine with TestDrive:, but I wanted to use the .NET methods for performance reasons.

I thought an easy fix would be to just use Resolve-Path or Join-Path -Resolve to get the full path, but they return an error when the file or directory does not exist. I did not want to manually create the file in my mock or my test, as I wanted my Pester test to ensure the module created the file properly.

The solution

This is when I stumbled upon the GetUnresolvedProviderPathFromPSPath method, which can be used to resolve a file or directory path, even if it does not exist. Here is an example of how to use it:

[string] $configPath = $ExecutionContext.SessionState.Path.GetUnresolvedProviderPathFromPSPath('TestDrive:/config.json')

This resolved the path to the Windows temp directory on the C drive, and I was able to use it with the .NET System.IO.File methods.

This method works with any path, not just PSDrive paths. For example, it also resolves this non-existent path:

$ExecutionContext.SessionState.Path.GetUnresolvedProviderPathFromPSPath("$Env:Temp/FileThatDoesNotExist.txt")

to C:\Users\DAN~1.SCH\AppData\Local\Temp\FileThatDoesNotExist.txt.

A better solution for Pester PSDrive paths

Later I fully read the Pester TestDrive documentation and found that it actually has a built-in $TestDrive variable that is compatible with the .NET methods 🤦‍♂️. So instead of using TestDrive:/config.json, I could just use $TestDrive/config.json. I ended up changing my Pester mock to use this instead, as it is much cleaner:

[string] $configPath = "$TestDrive/config.json"

Oh well, I learned something new about PowerShell, so it was worth it. I’m sure I’ll run into another situation down the road where GetUnresolvedProviderPathFromPSPath will come in handy. Hopefully you’ve learned something new too.

Happy coding!

Leave a Comment

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

Loading...