diff --git a/src/System.Management.Automation/engine/Modules/ModuleIntrinsics.cs b/src/System.Management.Automation/engine/Modules/ModuleIntrinsics.cs index fde3618e568..b687e502763 100644 --- a/src/System.Management.Automation/engine/Modules/ModuleIntrinsics.cs +++ b/src/System.Management.Automation/engine/Modules/ModuleIntrinsics.cs @@ -967,7 +967,7 @@ internal static string GetPersonalModulePath() #if UNIX return Platform.SelectProductNameForDirectory(Platform.XDG_Type.USER_MODULES); #else - string myDocumentsPath = Environment.GetFolderPath(Environment.SpecialFolder.MyDocuments); + string myDocumentsPath = InternalTestHooks.SetMyDocumentsSpecialFolderToBlank ? string.Empty : Environment.GetFolderPath(Environment.SpecialFolder.MyDocuments); return string.IsNullOrEmpty(myDocumentsPath) ? null : Path.Combine(myDocumentsPath, Utils.ModuleDirectory); #endif } @@ -1259,26 +1259,30 @@ public static string GetModulePath(string currentProcessModulePath, string hklmM // personalModulePath // sharedModulePath // systemModulePath - currentProcessModulePath = AddToPath(currentProcessModulePath, personalModulePathToUse, 0); - int insertIndex = currentProcessModulePath.IndexOf(Path.PathSeparator, PathContainsSubstring(currentProcessModulePath, personalModulePathToUse)); - if (insertIndex != -1) - { - // advance past the path separator - insertIndex++; - } - currentProcessModulePath = AddToPath(currentProcessModulePath, sharedModulePath, insertIndex); - insertIndex = currentProcessModulePath.IndexOf(Path.PathSeparator, PathContainsSubstring(currentProcessModulePath, sharedModulePath)); + int insertIndex = 0; + + currentProcessModulePath = UpdatePath(currentProcessModulePath, personalModulePathToUse, ref insertIndex); + currentProcessModulePath = UpdatePath(currentProcessModulePath, sharedModulePath, ref insertIndex); + currentProcessModulePath = UpdatePath(currentProcessModulePath, systemModulePathToUse, ref insertIndex); + } + + return currentProcessModulePath; + } + + private static string UpdatePath(string path, string pathToAdd, ref int insertIndex) + { + if (!string.IsNullOrEmpty(pathToAdd)) + { + path = AddToPath(path, pathToAdd, insertIndex); + insertIndex = path.IndexOf(Path.PathSeparator, PathContainsSubstring(path, pathToAdd)); if (insertIndex != -1) { // advance past the path separator insertIndex++; } - - currentProcessModulePath = AddToPath(currentProcessModulePath, systemModulePathToUse, insertIndex); } - - return currentProcessModulePath; + return path; } /// diff --git a/src/System.Management.Automation/engine/Utils.cs b/src/System.Management.Automation/engine/Utils.cs index 680d03e2c6e..46cc6312b53 100644 --- a/src/System.Management.Automation/engine/Utils.cs +++ b/src/System.Management.Automation/engine/Utils.cs @@ -1559,6 +1559,9 @@ public static class InternalTestHooks internal static bool SetConsoleWidthToZero; internal static bool SetConsoleHeightToZero; + // Simulate 'MyDocuments' returning empty string + internal static bool SetMyDocumentsSpecialFolderToBlank; + internal static bool SetDate; // A location to test PSEdition compatibility functionality for Windows PowerShell modules with diff --git a/test/powershell/engine/Module/ModulePath.Tests.ps1 b/test/powershell/engine/Module/ModulePath.Tests.ps1 index aabbb289500..5bf3b4e4c89 100644 --- a/test/powershell/engine/Module/ModulePath.Tests.ps1 +++ b/test/powershell/engine/Module/ModulePath.Tests.ps1 @@ -247,3 +247,21 @@ Describe "ModuleIntrinsics.GetPSModulePath API tests" -tag @('CI', 'RequireAdmin $currentModulePathElements | Should -Contain $mPath } } + +Describe 'ModuleIntrinsics.GetModulePath environment interaction' -tag @('CI') { + + It "GetModulePath does not crash when MyDocuments special folder is empty" { + try { + [System.Management.Automation.Internal.InternalTestHooks]::SetTestHook('SetMyDocumentsSpecialFolderToBlank', $true) + [System.Management.Automation.ModuleIntrinsics]::GetModulePath($null, $null, $null) + } + finally { + [System.Management.Automation.Internal.InternalTestHooks]::SetTestHook('SetMyDocumentsSpecialFolderToBlank', $false) + } + } + + It "GetModulePath does not crash when MyDocuments special folder is not empty" { + [System.Management.Automation.ModuleIntrinsics]::GetModulePath($null, $null, $null) + } + +}