Import PowerShell module after install
Asked Answered
H

2

6

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?

Handfasting answered 18/7, 2014 at 20:28 Comment(3)
which folder are the modules installed into? Is it in $env:psmodulepath?Bihari
They're installed into C:\Program Files\AppFabric 1.1 for Windows Server\PowershellModules` If $env:psmodulepath` changes, how does one "refresh" to get the latest value?Handfasting
There lies your problem. @Adi-Inbar provided you with the way to update $PSModulePathBihari
Y
7

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.)

Yim answered 18/7, 2014 at 21:56 Comment(0)
C
0

You can use the .NET System.Environment library to access your environment variables. Your new module is most likely added to your "User" environment variable. You can also experiment with specifying "Machine" and "Process" targets. See Environment.GetEnvironmentVariable for more info. Here is a good article on modifying your paths, including adding to and removing entries. It can be easily adapted to the PSModulePath environment variable.

This example adds the PSModulePath environment variable for the User to the end of the PSModulePath environment variable in your session. It will result in some duplicate entries, but should work just fine.

$env:PSModulePath = $env:PSModulePath+';'+[System.Environment]::GetEnvironmentVariable("PSModulePath","User")

Your code would now look like this:

Start-Process "C:\provision\WindowsServerAppFabricSetup_x64.exe" -ArgumentList "/i /GAC" -Wait
$env:PSModulePath = $env:PSModulePath+';'+[System.Environment]::GetEnvironmentVariable("PSModulePath","User")
Import-Module DistributedCacheConfiguration
# ...do configuration things...
Ciri answered 19/2, 2015 at 21:42 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.