Author Posts

September 24, 2015 at 12:03 pm

So I've been working on a VERY specific functionality "need" to tie into a custom Provider i'm writing in C#.

Basically I set out to find a way to replicate the A: B: etc functions defined when PowerShell loads so instead of having to type CD A: you can just do the aforementioned A:

I tried first to have my provider inject the functions into the runspace but it seems i'm completely missing the timing of how to get that to work so I went another route.

Basically i have a VERY simple PSM1 file UseColons.psm1


function Use-ColonsForPSDrives
{
[CmdletBinding()] Param()

Write-Verbose "Looping Through Installed PowerShell Providers"
Get-PSProvider | % `
{
Write-Verbose "Found $($_.Name) checking its drives"
$_.Drives | ? { (Get-Command | ? Name -eq "$($_.Name):") -eq $null } | % `
{
Write-Verbose "Setting up: `"function $($_.Name):() {Set-Location $($_.Name):}`""
if ($Verbose)
{
. Invoke-Expression -Command "function $($_.Name):() {Set-Location $($_.Name):}"
}
else
{
. Invoke-Expression -Command "function $($_.Name):() {Set-Location $($_.Name):}" -ErrorAction SilentlyContinue
}
Write-Verbose "Finished with drive $($_.Name)"
}
}
# Cert and WSMan do not show up as providers until you try to naviagte to their drives
# As a result we will add their functions manually but we will check if they are already set anyways
if ((Get-Command | ? Name -eq "Cert:") -eq $null) { . Invoke-Expression -Command "function Cert:() {Set-Location Cert:}" }
if ((Get-Command | ? Name -eq "WSMan:") -eq $null) { . Invoke-Expression -Command "function WSMan:() {Set-Location WSMan:}" }
}

. Use-ColonsForPSDrives

In simple terms it loops through all loaded providers, then through all the drives of each provider, then it checks if the Function: drive contains a function matching the {DriveName}: format and if one is not found it creates one.

The psd1 file is nothing more than export all functions

This is stored in the %ProgramFiles%\WindowsPowerShell\Modules path under its own folder

And finally I have profile.ps1 under the %windir%\system32\windowspowershell\v1.0 directory that just does


Remove-Module UseColons -ErrorAction SilentlyContinue
Import-Module UseColons

So when i load powershell or the ISE if i want to get to say dir through the variables i can just call

Variable:

Which when you are working with multiple providers typing that CD over and over as you switch is just annoying.

Now to the problem i'm still working on developing the actual PowerShell provider this was originally intended for. But when i debug it the UseColons module loads BEFORE visual studio turns around and loads the new provider so if i manually remove and import the module again it does its thing and i have all my drive functions for my provider.

I wanted to know after that LONG explanation how can I either:

  • Setup my UseColons module to load LAST
  • Find a way to have my Custom Provider (technically a module since it has the provider AND custom Cmdlets) load the UseColons module when it initializes
    1. I don't want to remove it from my standard profile because it is very helpful when i'm not working on the new provider and just tooling around using powershell for administrative stuff.

      Hopefully someone can give me some ideas or point me in the direction of some good deeper dive powershell provider documentations and how-tos.

      Thanks in advance for the help!