Environment.cs 7.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193
  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.Runtime.CompilerServices;
  9. using Internal.Runtime.Augments;
  10. namespace System
  11. {
  12. public static partial class Environment
  13. {
  14. public static string GetEnvironmentVariable(string variable)
  15. {
  16. return EnvironmentAugments.GetEnvironmentVariable(variable);
  17. }
  18. public static string GetEnvironmentVariable(string variable, EnvironmentVariableTarget target)
  19. {
  20. return EnvironmentAugments.GetEnvironmentVariable(variable, target);
  21. }
  22. public static IDictionary GetEnvironmentVariables()
  23. {
  24. // To maintain complete compatibility with prior versions we need to return a Hashtable.
  25. // We did ship a prior version of Core with LowLevelDictionary, which does iterate the
  26. // same (e.g. yields DictionaryEntry), but it is not a public type.
  27. //
  28. // While we could pass Hashtable back from CoreCLR the type is also defined here. We only
  29. // want to surface the local Hashtable.
  30. return EnvironmentAugments.EnumerateEnvironmentVariables().ToHashtable();
  31. }
  32. public static IDictionary GetEnvironmentVariables(EnvironmentVariableTarget target)
  33. {
  34. // See comments in GetEnvironmentVariables()
  35. return EnvironmentAugments.EnumerateEnvironmentVariables(target).ToHashtable();
  36. }
  37. private static Hashtable ToHashtable(this IEnumerable<KeyValuePair<string, string>> pairs)
  38. {
  39. Hashtable hashTable = new Hashtable();
  40. foreach (KeyValuePair<string, string> pair in pairs)
  41. {
  42. try
  43. {
  44. hashTable.Add(pair.Key, pair.Value);
  45. }
  46. catch (ArgumentException)
  47. {
  48. // Throw and catch intentionally to provide non-fatal notification about corrupted environment block
  49. }
  50. }
  51. return hashTable;
  52. }
  53. public static void SetEnvironmentVariable(string variable, string value)
  54. {
  55. EnvironmentAugments.SetEnvironmentVariable(variable, value);
  56. }
  57. public static void SetEnvironmentVariable(string variable, string value, EnvironmentVariableTarget target)
  58. {
  59. EnvironmentAugments.SetEnvironmentVariable(variable, value, target);
  60. }
  61. public static string CommandLine
  62. {
  63. get
  64. {
  65. return PasteArguments.Paste(GetCommandLineArgs(), pasteFirstArgumentUsingArgV0Rules: true);
  66. }
  67. }
  68. public static string CurrentDirectory
  69. {
  70. get { return CurrentDirectoryCore; }
  71. set
  72. {
  73. if (value == null)
  74. {
  75. throw new ArgumentNullException(nameof(value));
  76. }
  77. if (value.Length == 0)
  78. {
  79. throw new ArgumentException(SR.Argument_PathEmpty, nameof(value));
  80. }
  81. CurrentDirectoryCore = value;
  82. }
  83. }
  84. public static int CurrentManagedThreadId => EnvironmentAugments.CurrentManagedThreadId;
  85. public static void Exit(int exitCode) => EnvironmentAugments.Exit(exitCode);
  86. public static void FailFast(string message) => FailFast(message, exception: null);
  87. public static void FailFast(string message, Exception exception) => EnvironmentAugments.FailFast(message, exception);
  88. public static string ExpandEnvironmentVariables(string name)
  89. {
  90. if (name == null)
  91. {
  92. throw new ArgumentNullException(nameof(name));
  93. }
  94. if (name.Length == 0)
  95. {
  96. return name;
  97. }
  98. return ExpandEnvironmentVariablesCore(name);
  99. }
  100. public static string[] GetCommandLineArgs() => EnvironmentAugments.GetCommandLineArgs();
  101. public static string GetFolderPath(SpecialFolder folder) => GetFolderPath(folder, SpecialFolderOption.None);
  102. public static string GetFolderPath(SpecialFolder folder, SpecialFolderOption option)
  103. {
  104. if (!Enum.IsDefined(typeof(SpecialFolder), folder))
  105. {
  106. throw new ArgumentOutOfRangeException(nameof(folder), folder, SR.Format(SR.Arg_EnumIllegalVal, folder));
  107. }
  108. if (option != SpecialFolderOption.None && !Enum.IsDefined(typeof(SpecialFolderOption), option))
  109. {
  110. throw new ArgumentOutOfRangeException(nameof(option), option, SR.Format(SR.Arg_EnumIllegalVal, option));
  111. }
  112. return GetFolderPathCore(folder, option);
  113. }
  114. public static bool HasShutdownStarted => EnvironmentAugments.HasShutdownStarted;
  115. public static bool Is64BitProcess => IntPtr.Size == 8;
  116. public static bool Is64BitOperatingSystem => Is64BitProcess || Is64BitOperatingSystemWhen32BitProcess;
  117. public static OperatingSystem OSVersion => s_osVersion.Value;
  118. public static int ProcessorCount => EnvironmentAugments.ProcessorCount;
  119. public static string StackTrace
  120. {
  121. [MethodImpl(MethodImplOptions.NoInlining)] // Prevent inlining from affecting where the stacktrace starts
  122. get
  123. {
  124. return EnvironmentAugments.StackTrace;
  125. }
  126. }
  127. public static int TickCount => EnvironmentAugments.TickCount;
  128. public static bool UserInteractive => true;
  129. public static Version Version
  130. {
  131. // 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
  132. // 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
  133. // scheme that matched the product version. In order to preserve compatibility with existing libraries, this needs to be hard-coded.
  134. get { return new Version(4, 0, 30319, 42000); }
  135. }
  136. public static long WorkingSet
  137. {
  138. get
  139. {
  140. // Use reflection to access the implementation in System.Diagnostics.Process.dll. While far from ideal,
  141. // we do this to avoid duplicating the Windows, Linux, macOS, and potentially other platform-specific implementations
  142. // present in Process. If it proves important, we could look at separating that functionality out of Process into
  143. // Common files which could also be included here.
  144. Type processType = Type.GetType("System.Diagnostics.Process, System.Diagnostics.Process, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a", throwOnError: false);
  145. IDisposable currentProcess = processType?.GetMethod("GetCurrentProcess")?.Invoke(null, BindingFlags.DoNotWrapExceptions, null, null, null) as IDisposable;
  146. if (currentProcess != null)
  147. {
  148. using (currentProcess)
  149. {
  150. object result = processType.GetMethod("get_WorkingSet64")?.Invoke(currentProcess, BindingFlags.DoNotWrapExceptions, null, null, null);
  151. if (result is long) return (long)result;
  152. }
  153. }
  154. // Could not get the current working set.
  155. return 0;
  156. }
  157. }
  158. }
  159. }