Environment.cs 7.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195
  1. // Licensed to the .NET Foundation under one or more agreements.
  2. // The .NET Foundation licenses this file to you under the MIT license.
  3. // See the LICENSE file in the project root for more information.
  4. using System.Collections;
  5. using System.Collections.Generic;
  6. using System.Diagnostics;
  7. using System.Reflection;
  8. using System.Threading;
  9. namespace System
  10. {
  11. public static partial class Environment
  12. {
  13. public static string GetEnvironmentVariable(string variable)
  14. {
  15. if (variable == null)
  16. throw new ArgumentNullException(nameof(variable));
  17. return GetEnvironmentVariableCore(variable);
  18. }
  19. public static string GetEnvironmentVariable(string variable, EnvironmentVariableTarget target)
  20. {
  21. if (target == EnvironmentVariableTarget.Process)
  22. return GetEnvironmentVariable(variable);
  23. if (variable == null)
  24. throw new ArgumentNullException(nameof(variable));
  25. bool fromMachine = ValidateAndConvertRegistryTarget(target);
  26. return GetEnvironmentVariableFromRegistry(variable, fromMachine);
  27. }
  28. public static IDictionary GetEnvironmentVariables(EnvironmentVariableTarget target)
  29. {
  30. if (target == EnvironmentVariableTarget.Process)
  31. return GetEnvironmentVariables();
  32. bool fromMachine = ValidateAndConvertRegistryTarget(target);
  33. return GetEnvironmentVariablesFromRegistry(fromMachine);
  34. }
  35. public static void SetEnvironmentVariable(string variable, string value)
  36. {
  37. ValidateVariableAndValue(variable, ref value);
  38. SetEnvironmentVariableCore(variable, value);
  39. }
  40. public static void SetEnvironmentVariable(string variable, string value, EnvironmentVariableTarget target)
  41. {
  42. if (target == EnvironmentVariableTarget.Process)
  43. {
  44. SetEnvironmentVariable(variable, value);
  45. return;
  46. }
  47. ValidateVariableAndValue(variable, ref value);
  48. bool fromMachine = ValidateAndConvertRegistryTarget(target);
  49. SetEnvironmentVariableFromRegistry(variable, value, fromMachine: fromMachine);
  50. }
  51. public static string CommandLine => PasteArguments.Paste(GetCommandLineArgs(), pasteFirstArgumentUsingArgV0Rules: true);
  52. public static string CurrentDirectory
  53. {
  54. get => CurrentDirectoryCore;
  55. set
  56. {
  57. if (value == null)
  58. throw new ArgumentNullException(nameof(value));
  59. if (value.Length == 0)
  60. throw new ArgumentException(SR.Argument_PathEmpty, nameof(value));
  61. CurrentDirectoryCore = value;
  62. }
  63. }
  64. public static string ExpandEnvironmentVariables(string name)
  65. {
  66. if (name == null)
  67. throw new ArgumentNullException(nameof(name));
  68. if (name.Length == 0)
  69. return name;
  70. return ExpandEnvironmentVariablesCore(name);
  71. }
  72. private static string[] s_commandLineArgs;
  73. internal static void SetCommandLineArgs(string[] cmdLineArgs) // invoked from VM
  74. {
  75. s_commandLineArgs = cmdLineArgs;
  76. }
  77. public static string GetFolderPath(SpecialFolder folder) => GetFolderPath(folder, SpecialFolderOption.None);
  78. public static string GetFolderPath(SpecialFolder folder, SpecialFolderOption option)
  79. {
  80. if (!Enum.IsDefined(typeof(SpecialFolder), folder))
  81. throw new ArgumentOutOfRangeException(nameof(folder), folder, SR.Format(SR.Arg_EnumIllegalVal, folder));
  82. if (option != SpecialFolderOption.None && !Enum.IsDefined(typeof(SpecialFolderOption), option))
  83. throw new ArgumentOutOfRangeException(nameof(option), option, SR.Format(SR.Arg_EnumIllegalVal, option));
  84. return GetFolderPathCore(folder, option);
  85. }
  86. public static bool Is64BitProcess => IntPtr.Size == 8;
  87. public static bool Is64BitOperatingSystem => Is64BitProcess || Is64BitOperatingSystemWhen32BitProcess;
  88. private static OperatingSystem s_osVersion;
  89. public static OperatingSystem OSVersion
  90. {
  91. get
  92. {
  93. if (s_osVersion == null)
  94. {
  95. Interlocked.CompareExchange(ref s_osVersion, GetOSVersion(), null);
  96. }
  97. return s_osVersion;
  98. }
  99. }
  100. public static bool UserInteractive => true;
  101. // Previously this represented the File version of mscorlib.dll. Many other libraries in the framework and outside took dependencies on the first three parts of this version
  102. // remaining constant throughout 4.x. From 4.0 to 4.5.2 this was fine since the file version only incremented the last part. Starting with 4.6 we switched to a file versioning
  103. // scheme that matched the product version. In order to preserve compatibility with existing libraries, this needs to be hard-coded.
  104. public static Version Version => new Version(4, 0, 30319, 42000);
  105. public static long WorkingSet
  106. {
  107. get
  108. {
  109. // Use reflection to access the implementation in System.Diagnostics.Process.dll. While far from ideal,
  110. // we do this to avoid duplicating the Windows, Linux, macOS, and potentially other platform-specific implementations
  111. // present in Process. If it proves important, we could look at separating that functionality out of Process into
  112. // Common files which could also be included here.
  113. Type processType = Type.GetType("System.Diagnostics.Process, System.Diagnostics.Process, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a", throwOnError: false);
  114. IDisposable currentProcess = processType?.GetMethod("GetCurrentProcess")?.Invoke(null, BindingFlags.DoNotWrapExceptions, null, null, null) as IDisposable;
  115. if (currentProcess != null)
  116. {
  117. using (currentProcess)
  118. {
  119. object result = processType.GetMethod("get_WorkingSet64")?.Invoke(currentProcess, BindingFlags.DoNotWrapExceptions, null, null, null);
  120. if (result is long) return (long)result;
  121. }
  122. }
  123. // Could not get the current working set.
  124. return 0;
  125. }
  126. }
  127. private static bool ValidateAndConvertRegistryTarget(EnvironmentVariableTarget target)
  128. {
  129. Debug.Assert(target != EnvironmentVariableTarget.Process);
  130. if (target == EnvironmentVariableTarget.Machine)
  131. return true;
  132. if (target == EnvironmentVariableTarget.User)
  133. return false;
  134. throw new ArgumentOutOfRangeException(nameof(target), target, SR.Format(SR.Arg_EnumIllegalVal, target));
  135. }
  136. private static void ValidateVariableAndValue(string variable, ref string value)
  137. {
  138. if (variable == null)
  139. throw new ArgumentNullException(nameof(variable));
  140. if (variable.Length == 0)
  141. throw new ArgumentException(SR.Argument_StringZeroLength, nameof(variable));
  142. if (variable[0] == '\0')
  143. throw new ArgumentException(SR.Argument_StringFirstCharIsZero, nameof(variable));
  144. if (variable.Contains('='))
  145. throw new ArgumentException(SR.Argument_IllegalEnvVarName, nameof(variable));
  146. if (string.IsNullOrEmpty(value) || value[0] == '\0')
  147. {
  148. // Explicitly null out value if it's empty
  149. value = null;
  150. }
  151. }
  152. }
  153. }