PageRenderTime 40ms CodeModel.GetById 25ms RepoModel.GetById 0ms app.codeStats 0ms

/src/System.Management.Automation/namespaces/EnvironmentProvider.cs

https://gitlab.com/unofficial-mirrors/PowerShell
C# | 259 lines | 122 code | 33 blank | 104 comment | 12 complexity | 52143485d03227034b35316d4ebc5474 MD5 | raw file
  1. // Copyright (c) Microsoft Corporation. All rights reserved.
  2. // Licensed under the MIT License.
  3. using System;
  4. using Dbg = System.Management.Automation;
  5. using System.Collections;
  6. using System.Collections.Generic;
  7. using System.Collections.ObjectModel;
  8. using System.Management.Automation;
  9. using System.Management.Automation.Provider;
  10. namespace Microsoft.PowerShell.Commands
  11. {
  12. /// <summary>
  13. /// This provider is the data accessor for environment variables. It uses
  14. /// the SessionStateProviderBase as the base class to produce a view on
  15. /// session state data.
  16. /// </summary>
  17. [CmdletProvider(EnvironmentProvider.ProviderName, ProviderCapabilities.ShouldProcess)]
  18. public sealed class EnvironmentProvider : SessionStateProviderBase
  19. {
  20. /// <summary>
  21. /// Gets the name of the provider
  22. /// </summary>
  23. public const string ProviderName = "Environment";
  24. #region Constructor
  25. /// <summary>
  26. /// The constructor for the provider that exposes environment variables to the user
  27. /// as drives.
  28. /// </summary>
  29. public EnvironmentProvider()
  30. {
  31. } // constructor
  32. #endregion Constructor
  33. #region DriveCmdletProvider overrides
  34. /// <summary>
  35. /// Initializes the alias drive
  36. /// </summary>
  37. ///
  38. /// <returns>
  39. /// An array of a single PSDriveInfo object representing the alias drive.
  40. /// </returns>
  41. ///
  42. protected override Collection<PSDriveInfo> InitializeDefaultDrives()
  43. {
  44. string description = SessionStateStrings.EnvironmentDriveDescription;
  45. PSDriveInfo envDrive =
  46. new PSDriveInfo(
  47. DriveNames.EnvironmentDrive,
  48. ProviderInfo,
  49. String.Empty,
  50. description,
  51. null);
  52. Collection<PSDriveInfo> drives = new Collection<PSDriveInfo>();
  53. drives.Add(envDrive);
  54. return drives;
  55. } // InitializeDefaultDrives
  56. #endregion DriveCmdletProvider overrides
  57. #region protected members
  58. /// <summary>
  59. /// Gets a environment variable from session state
  60. /// </summary>
  61. ///
  62. /// <param name="name">
  63. /// The name of the environment variable to retrieve.
  64. /// </param>
  65. ///
  66. /// <returns>
  67. /// A DictionaryEntry that represents the value of the environment variable.
  68. /// </returns>
  69. ///
  70. internal override object GetSessionStateItem(string name)
  71. {
  72. Dbg.Diagnostics.Assert(
  73. !String.IsNullOrEmpty(name),
  74. "The caller should verify this parameter");
  75. object result = null;
  76. string value = Environment.GetEnvironmentVariable(name);
  77. if (value != null)
  78. {
  79. result = new DictionaryEntry(name, value);
  80. }
  81. return result;
  82. } // GetSessionStateItem
  83. /// <summary>
  84. /// Sets the environment variable of the specified name to the specified value
  85. /// </summary>
  86. ///
  87. /// <param name="name">
  88. /// The name of the environment variable to set.
  89. /// </param>
  90. ///
  91. /// <param name="value">
  92. /// The new value for the environment variable.
  93. /// </param>
  94. ///
  95. /// <param name="writeItem">
  96. /// If true, the item that was set should be written to WriteItemObject.
  97. /// </param>
  98. ///
  99. internal override void SetSessionStateItem(string name, object value, bool writeItem)
  100. {
  101. Dbg.Diagnostics.Assert(
  102. !String.IsNullOrEmpty(name),
  103. "The caller should verify this parameter");
  104. if (value == null)
  105. {
  106. Environment.SetEnvironmentVariable(name, null);
  107. }
  108. else
  109. {
  110. // First see if we got a DictionaryEntry which represents
  111. // an item for this provider. If so, use the value from
  112. // the dictionary entry.
  113. if (value is DictionaryEntry)
  114. {
  115. value = ((DictionaryEntry)value).Value;
  116. }
  117. string stringValue = value as string;
  118. if (stringValue == null)
  119. {
  120. // try using ETS to convert to a string.
  121. PSObject wrappedObject = PSObject.AsPSObject(value);
  122. stringValue = wrappedObject.ToString();
  123. }
  124. Environment.SetEnvironmentVariable(name, stringValue);
  125. DictionaryEntry item = new DictionaryEntry(name, stringValue);
  126. if (writeItem)
  127. {
  128. WriteItemObject(item, name, false);
  129. }
  130. }
  131. } // SetSessionStateItem
  132. /// <summary>
  133. /// Removes the specified environment variable from session state.
  134. /// </summary>
  135. ///
  136. /// <param name="name">
  137. /// The name of the environment variable to remove from session state.
  138. /// </param>
  139. ///
  140. internal override void RemoveSessionStateItem(string name)
  141. {
  142. Dbg.Diagnostics.Assert(
  143. !String.IsNullOrEmpty(name),
  144. "The caller should verify this parameter");
  145. Environment.SetEnvironmentVariable(name, null);
  146. } // RemoveSessionStateItem
  147. /// <summary>
  148. /// Gets a flattened view of the environment variables in session state
  149. /// </summary>
  150. ///
  151. /// <returns>
  152. /// An IDictionary representing the flattened view of the environment variables in
  153. /// session state.
  154. /// </returns>
  155. ///
  156. internal override IDictionary GetSessionStateTable()
  157. {
  158. // Environment variables are case-sensitive on Unix and
  159. // case-insensitive on Windows
  160. #if UNIX
  161. Dictionary<string, DictionaryEntry> providerTable =
  162. new Dictionary<string, DictionaryEntry>(StringComparer.Ordinal);
  163. #else
  164. Dictionary<string, DictionaryEntry> providerTable =
  165. new Dictionary<string, DictionaryEntry>(StringComparer.OrdinalIgnoreCase);
  166. #endif
  167. // The environment variables returns a dictionary of keys and values that are
  168. // both strings. We want to return a dictionary with the key as a string and
  169. // the value as the DictionaryEntry containing both the name and env variable
  170. // value.
  171. IDictionary environmentTable = Environment.GetEnvironmentVariables();
  172. foreach (DictionaryEntry entry in environmentTable)
  173. {
  174. if (!providerTable.TryAdd((string)entry.Key, entry))
  175. { // Windows only: duplicate key (variable name that differs only in case)
  176. // NOTE: Even though this shouldn't happen, it can, e.g. when npm
  177. // creates duplicate environment variables that differ only in case -
  178. // see https://github.com/PowerShell/PowerShell/issues/6305.
  179. // However, because retrieval *by name* later is invariably
  180. // case-INsensitive, in effect only a *single* variable exists.
  181. // We simply ask Environment.GetEnvironmentVariable() for the effective value
  182. // and use that as the only entry, because for a given key 'foo' (and all its case variations),
  183. // that is guaranteed to match what $env:FOO and [environment]::GetEnvironmentVariable('foo') return.
  184. // (If, by contrast, we just used `entry` as-is every time a duplicate is encountered,
  185. // it could - intermittently - represent a value *other* than the effective one.)
  186. string effectiveValue = Environment.GetEnvironmentVariable((string)entry.Key);
  187. if (((string)entry.Value).Equals(effectiveValue, StringComparison.Ordinal)) { // We've found the effective definition.
  188. // Note: We *recreate* the entry so that the specific name casing of the
  189. // effective definition is also reflected. However, if the case variants
  190. // define the same value, it is unspecified which name variant is reflected
  191. // in Get-Item env: output; given the always case-insensitive nature of the retrieval,
  192. // that shouldn't matter.
  193. providerTable.Remove((string)entry.Key);
  194. providerTable.Add((string)entry.Key, entry);
  195. }
  196. }
  197. }
  198. return providerTable;
  199. } // GetSessionStateTable
  200. /// <summary>
  201. /// Gets the Value property of the DictionaryEntry item
  202. /// </summary>
  203. ///
  204. /// <param name="item">
  205. /// The item to get the value from.
  206. /// </param>
  207. ///
  208. /// <returns>
  209. /// The value of the item.
  210. /// </returns>
  211. ///
  212. internal override object GetValueOfItem(object item)
  213. {
  214. Dbg.Diagnostics.Assert(
  215. item != null,
  216. "Caller should verify the item parameter");
  217. object value = item;
  218. if (item is DictionaryEntry)
  219. {
  220. value = ((DictionaryEntry)item).Value;
  221. }
  222. return value;
  223. } // GetValueOfItem
  224. #endregion protected members
  225. } // EnvironmentProvider
  226. }