powershellappfabricappfabric-cache

Import PowerShell module after install


I'm working on automating an AppFabric installation using PowerShell, and I've run into a problem where the script is calling the installer, waiting for it to complete, but I am unable to import the installed modules after from the same context. i.e:

Start-Process "C:\provision\WindowsServerAppFabricSetup_x64.exe" -ArgumentList "/i /GAC" -Wait
Import-Module DistributedCacheConfiguration
# ...do configuration things...

Which errors: The specified module 'DistributedCacheConfiguration' was not loaded because no valid module file was found in any module directory.

If you close and re-open PowerShell, the script runs fine. Adding a Start-Sleep 60 between the installer and the configuration didn't help, so I tried calling it as though powershell were restarting:

C:\WINDOWS\system32\windowspowershell\v1.0\powershell.exe C:\provision\appfabric_config.ps1

The same errors were thrown. How do I get PowerShell to recognize the newly installed modules?


Solution

  • PowerShell looks for modules in subdirectories of the directories listed in the PSModulePath environment variable. Environment variables are read from the registry key HKEY_LOCAL_MACHINE\System\CurrentControlSet\Control\Session Manager\Environment when the session is initialized.

    If the installer places the new module in a directory that's not already in PSModulePath and then adds that directory to the environment variable, it's modifying the environment variable in the registry, not in the current PowerShell console session's environment, so only PowerShell sessions started after the installation will have the updated PSModulePath.

    You can manually update the value from the registry by adding the following line after the installation and before attempting to import the module:

    $env:PSModulePath = (Get-ItemProperty -Path 'HKLM:\System\CurrentControlSet\Control\Session Manager\Environment' -Name PSModulePath).PSModulePath
    

    Note that although it may appear redundant, the reason you need

    (Get-ItemProperty -Path [...] -Name PSModulePath).PSModulePath
    

    rather than just

    Get-ItemProperty -Path [...] -Name PSModulePath
    

    is that Get-ItemProperty doesn't return the data of the named registry value, it returns a PSCustomObject that contains information about the registry value, and the data is in a property of that PSCustomObject that has the name of the registry value (i.e. PSModulePath in this case). If you prefer, you could also do it this way:

    $env:PSModulePath = Get-ItemProperty -Path 'HKLM:\System\CurrentControlSet\Control\Session Manager\Environment' -Name PSModulePath | select -ExpandProperty PSModulePath
    

    (There's no practical difference, it's six or a half dozen.)