Импортировать модуль PowerShell после установки
Я работаю над автоматизацией установки AppFabric с помощью PowerShell и столкнулся с проблемой, когда скрипт вызывает установщик, ожидая его завершения, но я не могу импортировать установленные модули после того же контекста. то есть:
Start-Process "C:\provision\WindowsServerAppFabricSetup_x64.exe" -ArgumentList "/i /GAC" -Wait
Import-Module DistributedCacheConfiguration
# ...do configuration things...
Какие ошибки: The specified module 'DistributedCacheConfiguration' was not loaded because no valid module file was found in any module directory.
Если вы закроете и снова откроете PowerShell, скрипт будет работать нормально. Добавление Start-Sleep 60
между установщиком и конфигурацией не помогло, поэтому я попытался вызвать его так, как будто перезапускается PowerShell:
C:\WINDOWS\system32\windowspowershell\v1.0\powershell.exe C:\provision\appfabric_config.ps1
Те же ошибки были брошены. Как заставить PowerShell распознавать недавно установленные модули?
2 ответа
PowerShell ищет модули в подкаталогах каталогов, перечисленных в переменной среды PSModulePath. Переменные среды считываются из раздела реестра HKEY_LOCAL_MACHINE\System\CurrentControlSet\Control\Session Manager\Environment при инициализации сеанса.
Если установщик помещает новый модуль в каталог, которого еще нет в PSModulePath, а затем добавляет этот каталог в переменную среды, он изменяет переменную среды в реестре, а не в среде текущего сеанса консоли PowerShell, поэтому только сеансы PowerShell запускаются после установка будет иметь обновленный PSModulePath.
Вы можете вручную обновить значение из реестра, добавив следующую строку после установки и перед попыткой импорта модуля:
$env:PSModulePath = (Get-ItemProperty -Path 'HKLM:\System\CurrentControlSet\Control\Session Manager\Environment' -Name PSModulePath).PSModulePath
Обратите внимание, что хотя это может показаться излишним, причина, по которой вам нужно
(Get-ItemProperty -Path [...] -Name PSModulePath).PSModulePath
а не просто
Get-ItemProperty -Path [...] -Name PSModulePath
является то, что Get-ItemProperty не возвращает данные именованного значения реестра, он возвращает PSCustomObject, который содержит информацию о значении реестра, и данные находятся в свойстве этого PSCustomObject, у которого есть имя значения реестра (то есть PSModulePath в этом случае). Если вы предпочитаете, вы также можете сделать это следующим образом:
$env:PSModulePath = Get-ItemProperty -Path 'HKLM:\System\CurrentControlSet\Control\Session Manager\Environment' -Name PSModulePath | select -ExpandProperty PSModulePath
(Практической разницы нет, шесть с половиной десятков.)
Вы можете использовать библиотеку.NET System.Environment для доступа к переменным среды. Ваш новый модуль, скорее всего, добавлен в вашу переменную среды "Пользователь". Вы также можете поэкспериментировать с указанием целей "Машина" и "Процесс". См. Environment.GetEnvironmentVariable для получения дополнительной информации. Вот хорошая статья об изменении ваших путей, включая добавление и удаление записей. Его можно легко адаптировать к переменной среды PSModulePath.
В этом примере добавляется переменная среды PSModulePath для пользователя в конец переменной среды PSModulePath в сеансе. Это приведет к дублированию записей, но должно работать нормально.
$env:PSModulePath = $env:PSModulePath+';'+[System.Environment]::GetEnvironmentVariable("PSModulePath","User")
Ваш код теперь будет выглядеть так:
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...