From b291e2006cd8db3934113a4e45ba8dd27d8d16b5 Mon Sep 17 00:00:00 2001 From: Mike Richmond Date: Wed, 3 Aug 2016 11:52:07 -0700 Subject: [PATCH] Fixing implementation of GetModulePath to conform to the requirements of #1184. --- .../engine/Modules/ModuleIntrinsics.cs | 4 +- .../engine/PropertyAccessor.cs | 66 ++++++++++--------- 2 files changed, 37 insertions(+), 33 deletions(-) diff --git a/src/System.Management.Automation/engine/Modules/ModuleIntrinsics.cs b/src/System.Management.Automation/engine/Modules/ModuleIntrinsics.cs index 3efd866e9a..a1028dc53e 100644 --- a/src/System.Management.Automation/engine/Modules/ModuleIntrinsics.cs +++ b/src/System.Management.Automation/engine/Modules/ModuleIntrinsics.cs @@ -886,8 +886,8 @@ namespace System.Management.Automation internal static string SetModulePath() { string currentModulePath = GetExpandedEnvironmentVariable("PSMODULEPATH", EnvironmentVariableTarget.Process); - string systemWideModulePath = GetExpandedEnvironmentVariable("PSMODULEPATH", EnvironmentVariableTarget.Machine); - string personalModulePath = GetExpandedEnvironmentVariable("PSMODULEPATH", EnvironmentVariableTarget.User); + string systemWideModulePath = ConfigPropertyAccessor.Instance.GetModulePath(ConfigPropertyAccessor.PropertyScope.SystemWide); + string personalModulePath = ConfigPropertyAccessor.Instance.GetModulePath(ConfigPropertyAccessor.PropertyScope.CurrentUser); string newModulePathString = GetModulePath(currentModulePath, systemWideModulePath, personalModulePath); diff --git a/src/System.Management.Automation/engine/PropertyAccessor.cs b/src/System.Management.Automation/engine/PropertyAccessor.cs index 027e054c21..dbc8d10ce5 100644 --- a/src/System.Management.Automation/engine/PropertyAccessor.cs +++ b/src/System.Management.Automation/engine/PropertyAccessor.cs @@ -72,16 +72,6 @@ namespace System.Management.Automation CurrentUser = 1 } - /// - /// Describes the desired module path during a GetModulePath call. - /// - internal enum ModulePathTarget - { - CurrentUser = 0, - SharedCommon = 1, - VersionSpecific = 2 - } - #endregion // Enums #region Interface Methods @@ -93,7 +83,7 @@ namespace System.Management.Automation /// Note: There is no setter because this value is immutable. /// /// Module path values from the config file. - internal abstract string GetModulePath(ModulePathTarget target); + internal abstract string GetModulePath(PropertyScope scope); /// /// Existing Key = HKCU and HKLM\SOFTWARE\Microsoft\PowerShell\1\ShellIds\Microsoft.PowerShell @@ -172,27 +162,28 @@ namespace System.Management.Automation } /// - /// Note: This value is not writable, so it MUST be set during post-install configuration. - /// Also, it will only be written to the $PSHOME configuration file (not the per-user file). + /// This value is not writable via the API and must be set using a text editor. /// - /// - /// Value if found, null otherwise. The behavior matches Environment.GetEnvironmentVariable(). - internal override string GetModulePath(ModulePathTarget target) + /// + /// Value if found, null otherwise. The behavior matches ModuleIntrinsics.GetExpandedEnvironmentVariable(). + internal override string GetModulePath(PropertyScope scope) { - string fileName = Path.Combine(psHomeConfigDirectory, configFileName); - if (ModulePathTarget.CurrentUser == target) + string scopeDirectory = psHomeConfigDirectory; + + // Defaults to system wide. + if (PropertyScope.CurrentUser == scope) { - // TODO: This feels unnecessary since it can be calculated based on the current user... - return ReadValueFromFile(fileName, "UserModulePath"); + scopeDirectory = appDataConfigDirectory; } - else if (ModulePathTarget.SharedCommon == target) + + string fileName = Path.Combine(scopeDirectory, configFileName); + + string modulePath = ReadValueFromFile(fileName, "PsModulePath"); + if (!string.IsNullOrEmpty(modulePath)) { - return ReadValueFromFile(fileName, "SharedCommonModulePath"); - } - else - { - return null; + modulePath = Environment.ExpandEnvironmentVariables(modulePath); } + return modulePath; } /// @@ -497,12 +488,25 @@ namespace System.Management.Automation /// This method is not supported for systems when reading from the registry. Its value is /// known at compile time for inbox PowerShell. /// - /// - /// - internal override string GetModulePath(ModulePathTarget target) + /// + /// The specified module path. Null if not present. + internal override string GetModulePath(PropertyScope scope) { - // TODO: Better way to handle this? - throw new ArgumentException(); + RegistryKey scopedKey = Registry.LocalMachine; + string regKeyName = @"System\CurrentControlSet\Control\Session Manager\Environment"; + + if (scope == PropertyScope.CurrentUser) + { + scopedKey = Registry.CurrentUser; + regKeyName = "Environment"; + } + + string modulePath = GetRegistryString(scopedKey, regKeyName, "PSMODULEPATH"); + if ( ! string.IsNullOrEmpty(modulePath)) + { + modulePath = Environment.ExpandEnvironmentVariables(modulePath); + } + return modulePath; } ///