Update setting PSModulePath to concatenate the process + machine env var (#11276)

This commit is contained in:
Steve Lee
2019-12-09 16:25:08 -08:00
committed by Dongbo Wang
parent f8a321ae2b
commit 20a236b228
2 changed files with 33 additions and 26 deletions
@@ -1152,6 +1152,11 @@ namespace System.Management.Automation
else
result.Append(Path.PathSeparator + subPathToAdd);
}
else if (insertPosition > result.Length)
{
// handle case where path is a singleton with no path seperator already
result.Append(Path.PathSeparator).Append(subPathToAdd);
}
else // insert at the requested location (this is used by DSC (<Program Files> location) and by 'user-specific location' (SpecialFolder.MyDocuments or EVT.User))
{
result.Insert(insertPosition, subPathToAdd + Path.PathSeparator);
@@ -1164,9 +1169,7 @@ namespace System.Management.Automation
}
/// <summary>
/// Checks the various PSModulePath environment string and returns PSModulePath string as appropriate. Note - because these
/// strings go through the provider, we need to escape any wildcards before passing them
/// along.
/// Checks the various PSModulePath environment string and returns PSModulePath string as appropriate.
/// </summary>
public static string GetModulePath(string currentProcessModulePath, string hklmMachineModulePath, string hkcuUserModulePath)
{
@@ -1196,11 +1199,6 @@ namespace System.Management.Automation
{
currentProcessModulePath += hklmMachineModulePath; // += EVT.Machine
}
#if !UNIX
// Add Windows Modules path
currentProcessModulePath = $"{currentProcessModulePath}{Path.PathSeparator}{s_windowsPowerShellPSHomeModulePath}";
#endif
}
// EVT.Process exists
// Now handle the case where the environment variable is already set.
@@ -1281,9 +1279,16 @@ namespace System.Management.Automation
private static string SetModulePath()
{
string currentModulePath = GetExpandedEnvironmentVariable(Constants.PSModulePathEnvVar, EnvironmentVariableTarget.Process);
#if !UNIX
// if the current process and user env vars are the same, it means we need to append the machine one as it's incomplete
// otherwise, the user modified it and we should use the process one
if (string.CompareOrdinal(GetExpandedEnvironmentVariable(Constants.PSModulePathEnvVar, EnvironmentVariableTarget.User), currentModulePath) == 0)
{
currentModulePath = currentModulePath + Path.PathSeparator + GetExpandedEnvironmentVariable(Constants.PSModulePathEnvVar, EnvironmentVariableTarget.Machine);
}
#endif
string allUsersModulePath = PowerShellConfig.Instance.GetModulePath(ConfigScope.AllUsers);
string personalModulePath = PowerShellConfig.Instance.GetModulePath(ConfigScope.CurrentUser);
string newModulePathString = GetModulePath(currentModulePath, allUsersModulePath, personalModulePath);
if (!string.IsNullOrEmpty(newModulePathString))
@@ -70,12 +70,19 @@ Describe "SxS Module Path Basic Tests" -tags "CI" {
$env:PSModulePath = ""
$defaultModulePath = & $powershell -nopro -c '$env:PSModulePath'
$pathSeparator = [System.IO.Path]::PathSeparator
$paths = $defaultModulePath -split [System.IO.Path]::PathSeparator
$paths = $defaultModulePath.Replace("$pathSeparator$pathSeparator", "$pathSeparator") -split $pathSeparator
if ($IsWindows)
{
$paths.Count | Should -Be 4
$expectedPaths = 3 # user, shared, pshome
$userPaths = [System.Environment]::GetEnvironmentVariable("PSModulePath", [System.EnvironmentVariableTarget]::User)
$expectedPaths += $userPaths ? $userPaths.Split($pathSeparator).Count : 0
$machinePaths = [System.Environment]::GetEnvironmentVariable("PSModulePath", [System.EnvironmentVariableTarget]::Machine)
$expectedPaths += $machinePaths ? $machinePaths.Split($pathSeparator).Count : 0
$paths.Count | Should -Be $expectedPaths
}
else
{
@@ -85,10 +92,7 @@ Describe "SxS Module Path Basic Tests" -tags "CI" {
$paths[0].TrimEnd([System.IO.Path]::DirectorySeparatorChar) | Should -Be $expectedUserPath
$paths[1].TrimEnd([System.IO.Path]::DirectorySeparatorChar) | Should -Be $expectedSharedPath
$paths[2].TrimEnd([System.IO.Path]::DirectorySeparatorChar) | Should -Be $expectedSystemPath
if ($IsWindows)
{
$paths[3].TrimEnd([System.IO.Path]::DirectorySeparatorChar) | Should -Be $expectedWindowsPowerShellPSHomePath
}
$defaultModulePath | Should -BeLike "*$expectedWindowsPowerShellPSHomePath*"
}
It "Works with pshome module path derived from a different PowerShell instance" -Skip:(!$IsCoreCLR -or $skipNoPwsh) {
@@ -104,18 +108,11 @@ Describe "SxS Module Path Basic Tests" -tags "CI" {
$env:PSModulePath = $fakePSHomeModuleDir
$newModulePath = & $powershell -nopro -c '$env:PSModulePath'
$paths = $newModulePath -split [System.IO.Path]::PathSeparator
$paths.Count | Should -Be 4
$paths[0] | Should -Be $expectedUserPath
$paths[1] | Should -Be $expectedSharedPath
$paths[2] | Should -Be $expectedSystemPath
$paths[3] | Should -Be $fakePSHomeModuleDir
if ($IsWindows)
{
$expectedWindowsPowerShellPSHomePath | Should -Not -BeIn $paths
}
} finally {
## Remove 'powershell' and 'pwsh.deps.json' from the fake PSHome folder
@@ -180,9 +177,14 @@ Describe "SxS Module Path Basic Tests" -tags "CI" {
}
It 'Windows PowerShell does not inherit path defined in powershell.config.json' -Skip:(!$IsWindows) {
$userConfig = '{ "PSModulePath": "myUserPath" }'
Set-Content -Path $userConfigPath -Value $userConfig -Force
$out = pwsh -noprofile -command 'powershell.exe -noprofile -command $env:PSModulePath'
$out | Should -Not -BeLike 'myUserPath;*'
try {
$userConfig = '{ "PSModulePath": "myUserPath" }'
Set-Content -Path $userConfigPath -Value $userConfig -Force
$out = pwsh -noprofile -command 'powershell.exe -noprofile -command $env:PSModulePath'
$out | Should -Not -BeLike 'myUserPath;*'
}
finally {
Remove-Item -Path $userConfigPath -Force
}
}
}