I’m not going to ENABLE-RANT today.   Anybody that uses System Center Configuration Manager knows one thing, you need to MANUALLY add in the Cmdlets to use them using this line

Import-Module ‘C:\Program Files (x86)\Microsoft Configuration Manager\AdminConsole\bin\ConfigurationManager.psd1’

True, it’s irritating that I can just do something like this in a modern server

Import-Module ConfigurationManager

If this were there not only would it be EASIER to access the module locally, it would also allow me to create and establish Remote PowerShell sessions to EASILY work with Configuration Manager and make Implicit remoting far smoother.

But rather than get upset, I decided to sit down and find out why.  Why if I do THIS

Get-Module –listavailable ConfigurationManager

Does it NOT find the module?

The answer was surprisingly easy (and a bit silly it got missed by somebody)

For your module to be discoverable it needs to follow two rules

  1. The PSD1 file must be in a folder of the same name
  2. This Folder must be added to the System Environment variable “PSModulePath”

So examining my default PSModulePath on a Configuration Manager 1606 server It was DEFINITELY not there (yes, fully patched, rebooted multiple times)

$ENV:PSModulePath

C:\Users\Administrator.SYSTEMCTR\Documents\WindowsPowerShell\Modules;C:\Program Files\WindowsPowerShell\Modules;C:\Windows\system32\WindowsPowerShell\v1.0\Modules;C:\Program Files (x86)\Microsoft SQL Server\110\Tools\PowerShell\Modules\

So initially I thought I would just add it to the PSModulePath in the following fashion while in a PowerShell prompt as Administrator.

$ENV:PSModulePath=($ENV:PSModulePath) + ‘;C:\Program Files (x86)\Microsoft Configuration Manager\AdminConsole\bin\’

Tried that and looked and still nothing…. oh right forgot the FIRST rule

The PSD1 file must be in a folder of the same name

Our problem is that all of the needed files and content exist in the BIN folder and it needs to be renamed to ConfigurationManager.  But obviously we can’t do THAT or things will break.

We COULD just make a copy of that folder called “ConfigurationManager” and add THAT to the path.  That might work too. But that offers up other scary words.

  • “Supportability” (Microsoft probably won’t support that)
  • “Patching” (If it DID work, we’d have to dupe that folder EACH and EVERY TIME we patched)
  • “Works?” (Moving supporting Binaries in ANY major application is just Ripe with Risk)

The it dawned on me.  Since VISTA (Stop cringing) we’ve had Junctions.   A Junction is a “Pseudo Folder” which ACTS like a Directory but points off to another Directory.

We COULD create a Junction called “ConfigurationManager” and point it RIGHT BACK to the folder with all of the goodies needed in the Configuration Manager module.

Well guess what… it works! Here’s the Script in PowerShell to make this useful for you as well.

# Create a Junction to act as a folder called “Configuration Manager” pointing to the
# ‘Bin’ folder which has the Actual Configuration Manager module
# This provides a “Pseudo Folder” to match the Module Name needed
$TargetFolder=’C:\Program Files (x86)\Microsoft Configuration Manager\AdminConsole\bin\’
$TargetPath=’C:\Program Files (x86)\Microsoft Configuration Manager\AdminConsole\PSModule\’
# Verify this has not been done yet, if it has go ahead
If (!(Test-Path “$($TargetPath)ConfigurationManager\”))
{
New-Item -ItemType Directory -Path $TargetPath -Force
CMD.EXE /C MKLINK /J “$($TargetPath)ConfigurationManager” $TargetFolder
# You can use the line below instead of MKLINK if you are using PowerShell 5
#New-Item -ItemType Junction -Name ConfigurationManager -Value $TargetFolder -Path $TargetPath
}
# Permanently update the PSModulePath Environment variable
# With the parent path holding the Configuration Manager folder
# This will make it fully discoverable
$OldPSPath=(Get-ItemProperty -Path ‘Registry::HKEY_LOCAL_MACHINE\System\CurrentControlSet\Control\Session Manager\Environment’ -Name PSModulePath).PSModulePath
# Verify this has not been done yet, if it has go ahead
IF (!($OldPSPath | Select-String -SimpleMatch “$($TargetPath)ConfigurationManager”))
{
$NewPSPath=$OldPSPath+’;’+$TargetPath+’ConfigurationManager’
Set-ItemProperty -Path ‘Registry::HKEY_LOCAL_MACHINE\System\CurrentControlSet\Control\Session Manager\Environment’ -Name PSModulePath –Value $NewPSPath
}
$ENV:PSModulePath=$NewPSPath

 

Now I can just run Import-Module ConfigurationManager and Woohoo! I’m off to races!

Here it is on the Technet Gallery if you’d like a clean copy 🙂

Share and Enjoy!

Sean
The Energized Tech
Honorary Scripting Guy