From c97a56582f026f9c77274ba6c931a51415aefdc3 Mon Sep 17 00:00:00 2001 From: "Steve Lee (POWERSHELL)" Date: Thu, 5 Dec 2019 17:41:20 -0800 Subject: [PATCH 1/5] Update setting PSModulePath to concatenate the process + machine env var --- .../engine/Modules/ModuleIntrinsics.cs | 23 ++++++++------ .../engine/Module/ModulePath.Tests.ps1 | 30 ++++++++----------- 2 files changed, 27 insertions(+), 26 deletions(-) diff --git a/src/System.Management.Automation/engine/Modules/ModuleIntrinsics.cs b/src/System.Management.Automation/engine/Modules/ModuleIntrinsics.cs index 9a0511a93cc..07bdbbec8a1 100644 --- a/src/System.Management.Automation/engine/Modules/ModuleIntrinsics.cs +++ b/src/System.Management.Automation/engine/Modules/ModuleIntrinsics.cs @@ -1152,6 +1152,11 @@ private static string AddToPath(string basePath, string pathToAdd, int insertPos 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 + subPathToAdd); + } else // insert at the requested location (this is used by DSC ( location) and by 'user-specific location' (SpecialFolder.MyDocuments or EVT.User)) { result.Insert(insertPosition, subPathToAdd + Path.PathSeparator); @@ -1164,9 +1169,7 @@ private static string AddToPath(string basePath, string pathToAdd, int insertPos } /// - /// 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. /// public static string GetModulePath(string currentProcessModulePath, string hklmMachineModulePath, string hkcuUserModulePath) { @@ -1196,11 +1199,6 @@ public static string GetModulePath(string currentProcessModulePath, string hklmM { 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 @@ internal static string GetWindowsPowerShellModulePath() 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 += 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)) diff --git a/test/powershell/engine/Module/ModulePath.Tests.ps1 b/test/powershell/engine/Module/ModulePath.Tests.ps1 index c124a8ed17b..286f03a04d5 100644 --- a/test/powershell/engine/Module/ModulePath.Tests.ps1 +++ b/test/powershell/engine/Module/ModulePath.Tests.ps1 @@ -70,12 +70,13 @@ 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 + $paths.Count | Should -Be 6 } else { @@ -85,10 +86,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 +102,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 +171,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 + } } } From 6bd6dd6ff6c3999045239e59bdf08754a9ac666b Mon Sep 17 00:00:00 2001 From: "Steve Lee (POWERSHELL)" Date: Thu, 5 Dec 2019 19:19:25 -0800 Subject: [PATCH 2/5] add some tracing --- test/powershell/engine/Module/ModulePath.Tests.ps1 | 1 + 1 file changed, 1 insertion(+) diff --git a/test/powershell/engine/Module/ModulePath.Tests.ps1 b/test/powershell/engine/Module/ModulePath.Tests.ps1 index 286f03a04d5..d4646eef31b 100644 --- a/test/powershell/engine/Module/ModulePath.Tests.ps1 +++ b/test/powershell/engine/Module/ModulePath.Tests.ps1 @@ -76,6 +76,7 @@ Describe "SxS Module Path Basic Tests" -tags "CI" { if ($IsWindows) { +write-verbose -verbose ($paths | out-string) $paths.Count | Should -Be 6 } else From 3926930400a878bae6b2c3b7bd57c53b25b350f6 Mon Sep 17 00:00:00 2001 From: "Steve Lee (POWERSHELL)" Date: Thu, 5 Dec 2019 19:52:02 -0800 Subject: [PATCH 3/5] fix test to be dynamic to the system --- test/powershell/engine/Module/ModulePath.Tests.ps1 | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) diff --git a/test/powershell/engine/Module/ModulePath.Tests.ps1 b/test/powershell/engine/Module/ModulePath.Tests.ps1 index d4646eef31b..ccd7a04f00f 100644 --- a/test/powershell/engine/Module/ModulePath.Tests.ps1 +++ b/test/powershell/engine/Module/ModulePath.Tests.ps1 @@ -76,8 +76,13 @@ Describe "SxS Module Path Basic Tests" -tags "CI" { if ($IsWindows) { -write-verbose -verbose ($paths | out-string) - $paths.Count | Should -Be 6 + $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 { From 55b8daaf6b9b7dcf50d693f10984c0c65b08d20d Mon Sep 17 00:00:00 2001 From: Steve Lee Date: Thu, 5 Dec 2019 22:33:32 -0800 Subject: [PATCH 4/5] Update src/System.Management.Automation/engine/Modules/ModuleIntrinsics.cs Co-Authored-By: Ilya --- .../engine/Modules/ModuleIntrinsics.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/System.Management.Automation/engine/Modules/ModuleIntrinsics.cs b/src/System.Management.Automation/engine/Modules/ModuleIntrinsics.cs index 07bdbbec8a1..b5dd0d33689 100644 --- a/src/System.Management.Automation/engine/Modules/ModuleIntrinsics.cs +++ b/src/System.Management.Automation/engine/Modules/ModuleIntrinsics.cs @@ -1284,7 +1284,7 @@ private static string SetModulePath() // otherwise, the user modified it and we should use the process one if (string.CompareOrdinal(GetExpandedEnvironmentVariable(Constants.PSModulePathEnvVar, EnvironmentVariableTarget.User), currentModulePath) == 0) { - currentModulePath += Path.PathSeparator + GetExpandedEnvironmentVariable(Constants.PSModulePathEnvVar, EnvironmentVariableTarget.Machine); + currentModulePath = currentModulePath + Path.PathSeparator + GetExpandedEnvironmentVariable(Constants.PSModulePathEnvVar, EnvironmentVariableTarget.Machine); } #endif string allUsersModulePath = PowerShellConfig.Instance.GetModulePath(ConfigScope.AllUsers); From b7c8bc391749897dc18e828b70e53644c72f569d Mon Sep 17 00:00:00 2001 From: Steve Lee Date: Mon, 9 Dec 2019 14:36:41 -0800 Subject: [PATCH 5/5] Update src/System.Management.Automation/engine/Modules/ModuleIntrinsics.cs Co-Authored-By: Dongbo Wang --- .../engine/Modules/ModuleIntrinsics.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/System.Management.Automation/engine/Modules/ModuleIntrinsics.cs b/src/System.Management.Automation/engine/Modules/ModuleIntrinsics.cs index b5dd0d33689..feb511d109e 100644 --- a/src/System.Management.Automation/engine/Modules/ModuleIntrinsics.cs +++ b/src/System.Management.Automation/engine/Modules/ModuleIntrinsics.cs @@ -1155,7 +1155,7 @@ private static string AddToPath(string basePath, string pathToAdd, int insertPos else if (insertPosition > result.Length) { // handle case where path is a singleton with no path seperator already - result.Append(Path.PathSeparator + subPathToAdd); + result.Append(Path.PathSeparator).Append(subPathToAdd); } else // insert at the requested location (this is used by DSC ( location) and by 'user-specific location' (SpecialFolder.MyDocuments or EVT.User)) {