Revert "Bump corlib version"
[mono-project.git] / mcs / class / corlib / System / Environment.cs
blobaa32d3a24a655c8be3fa0f80a4b3bc8144576b1f
1 //------------------------------------------------------------------------------
2 //
3 // System.Environment.cs
4 //
5 // Copyright (C) 2001 Moonlight Enterprises, All Rights Reserved
6 //
7 // Author: Jim Richardson, develop@wtfo-guru.com
8 // Dan Lewis (dihlewis@yahoo.co.uk)
9 // Created: Saturday, August 11, 2001
11 //------------------------------------------------------------------------------
13 // Copyright (C) 2004-2005 Novell, Inc (http://www.novell.com)
15 // Permission is hereby granted, free of charge, to any person obtaining
16 // a copy of this software and associated documentation files (the
17 // "Software"), to deal in the Software without restriction, including
18 // without limitation the rights to use, copy, modify, merge, publish,
19 // distribute, sublicense, and/or sell copies of the Software, and to
20 // permit persons to whom the Software is furnished to do so, subject to
21 // the following conditions:
22 //
23 // The above copyright notice and this permission notice shall be
24 // included in all copies or substantial portions of the Software.
25 //
26 // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
27 // EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
28 // MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
29 // NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
30 // LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
31 // OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
32 // WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
35 using System.IO;
36 using System.Collections;
37 using System.Runtime.CompilerServices;
38 using System.Security;
39 using System.Security.Permissions;
40 using System.Text;
41 using System.Runtime.InteropServices;
42 using System.Threading;
43 using System.Diagnostics.Contracts;
45 namespace System {
47 [ComVisible (true)]
48 public static partial class Environment {
51 * This is the version number of the corlib-runtime interface. When
52 * making changes to this interface (by changing the layout
53 * of classes the runtime knows about, changing icall signature or
54 * semantics etc), increment this variable. Also increment the
55 * pair of this variable in the runtime in metadata/appdomain.c.
56 * Changes which are already detected at runtime, like the addition
57 * of icalls, do not require an increment.
59 #pragma warning disable 169
60 private const int mono_corlib_version = 164;
61 #pragma warning restore 169
63 [ComVisible (true)]
64 public enum SpecialFolder
66 MyDocuments = 0x05,
67 Desktop = 0x00,
68 MyComputer = 0x11,
69 Programs = 0x02,
70 Personal = 0x05,
71 Favorites = 0x06,
72 Startup = 0x07,
73 Recent = 0x08,
74 SendTo = 0x09,
75 StartMenu = 0x0b,
76 MyMusic = 0x0d,
77 DesktopDirectory = 0x10,
78 Templates = 0x15,
79 ApplicationData = 0x1a,
80 LocalApplicationData = 0x1c,
81 InternetCache = 0x20,
82 Cookies = 0x21,
83 History = 0x22,
84 CommonApplicationData = 0x23,
85 System = 0x25,
86 ProgramFiles = 0x26,
87 MyPictures = 0x27,
88 CommonProgramFiles = 0x2b,
89 MyVideos = 0x0e,
90 NetworkShortcuts = 0x13,
91 Fonts = 0x14,
92 CommonStartMenu = 0x16,
93 CommonPrograms = 0x17,
94 CommonStartup = 0x18,
95 CommonDesktopDirectory = 0x19,
96 PrinterShortcuts = 0x1b,
97 Windows = 0x24,
98 UserProfile = 0x28,
99 SystemX86 = 0x29,
100 ProgramFilesX86 = 0x2a,
101 CommonProgramFilesX86 = 0x2c,
102 CommonTemplates = 0x2d,
103 CommonDocuments = 0x2e,
104 CommonAdminTools = 0x2f,
105 AdminTools = 0x30,
106 CommonMusic = 0x35,
107 CommonPictures = 0x36,
108 CommonVideos = 0x37,
109 Resources = 0x38,
110 LocalizedResources = 0x39,
111 CommonOemLinks = 0x3a,
112 CDBurning = 0x3b,
115 public
116 enum SpecialFolderOption {
117 None = 0,
118 DoNotVerify = 0x4000,
119 Create = 0x8000
122 /// <summary>
123 /// Gets the command line for this process
124 /// </summary>
125 public static string CommandLine {
126 // note: security demand inherited from calling GetCommandLineArgs
127 get {
128 StringBuilder sb = new StringBuilder ();
129 foreach (string str in GetCommandLineArgs ()) {
130 bool escape = false;
131 string quote = "";
132 string s = str;
133 for (int i = 0; i < s.Length; i++) {
134 if (quote.Length == 0 && Char.IsWhiteSpace (s [i])) {
135 quote = "\"";
136 } else if (s [i] == '"') {
137 escape = true;
140 if (escape && quote.Length != 0) {
141 s = s.Replace ("\"", "\\\"");
143 sb.AppendFormat ("{0}{1}{0} ", quote, s);
145 if (sb.Length > 0)
146 sb.Length--;
147 return sb.ToString ();
151 /// <summary>
152 /// Gets or sets the current directory. Actually this is supposed to get
153 /// and/or set the process start directory acording to the documentation
154 /// but actually test revealed at beta2 it is just Getting/Setting the CurrentDirectory
155 /// </summary>
156 public static string CurrentDirectory
158 get {
159 return Directory.GetCurrentDirectory ();
161 set {
162 Directory.SetCurrentDirectory (value);
166 public static int CurrentManagedThreadId {
167 get {
168 return Thread.CurrentThread.ManagedThreadId;
172 /// <summary>
173 /// Gets or sets the exit code of this process
174 /// </summary>
175 public extern static int ExitCode
177 [MethodImplAttribute (MethodImplOptions.InternalCall)]
178 get;
179 [MethodImplAttribute (MethodImplOptions.InternalCall)]
180 set;
183 static public extern bool HasShutdownStarted
185 [MethodImplAttribute (MethodImplOptions.InternalCall)]
186 get;
190 /// <summary>
191 /// Gets the name of the local computer
192 /// </summary>
193 public extern static string MachineName {
194 [MethodImplAttribute (MethodImplOptions.InternalCall)]
195 [EnvironmentPermission (SecurityAction.Demand, Read="COMPUTERNAME")]
196 [SecurityPermission (SecurityAction.Demand, UnmanagedCode=true)]
197 get;
200 [MethodImplAttribute (MethodImplOptions.InternalCall)]
201 extern static string GetNewLine ();
203 static string nl;
204 /// <summary>
205 /// Gets the standard new line value
206 /// </summary>
207 public static string NewLine {
208 get {
209 if (nl != null)
210 return nl;
212 nl = GetNewLine ();
213 return nl;
218 // Support methods and fields for OSVersion property
220 static OperatingSystem os;
222 static extern PlatformID Platform {
223 [MethodImplAttribute (MethodImplOptions.InternalCall)]
224 get;
227 [MethodImplAttribute (MethodImplOptions.InternalCall)]
228 internal static extern string GetOSVersionString ();
230 /// <summary>
231 /// Gets the current OS version information
232 /// </summary>
233 public static OperatingSystem OSVersion {
234 get {
235 if (os == null) {
236 Version v = CreateVersionFromString (GetOSVersionString ());
237 PlatformID p = Platform;
238 if (p == PlatformID.MacOSX)
239 p = PlatformID.Unix;
240 os = new OperatingSystem (p, v);
242 return os;
247 // a very gentle way to construct a Version object which takes
248 // the first four numbers in a string as the version
249 internal static Version CreateVersionFromString (string info)
251 int major = 0;
252 int minor = 0;
253 int build = 0;
254 int revision = 0;
255 int state = 1;
256 int number = -1; // string may not begin with a digit
258 if (info == null)
259 return new Version (0, 0, 0, 0);
261 for (int i=0; i < info.Length; i++) {
262 char c = info [i];
263 if (Char.IsDigit (c)) {
264 if (number < 0) {
265 number = (c - '0');
267 else {
268 number = (number * 10) + (c - '0');
271 else if (number >= 0) {
272 // assign
273 switch (state) {
274 case 1:
275 major = number;
276 break;
277 case 2:
278 minor = number;
279 break;
280 case 3:
281 build = number;
282 break;
283 case 4:
284 revision = number;
285 break;
287 number = -1;
288 state ++;
290 // ignore end of string
291 if (state == 5)
292 break;
295 // Last number
296 if (number >= 0) {
297 switch (state) {
298 case 1:
299 major = number;
300 break;
301 case 2:
302 minor = number;
303 break;
304 case 3:
305 build = number;
306 break;
307 case 4:
308 revision = number;
309 break;
312 return new Version (major, minor, build, revision);
315 /// <summary>
316 /// Get StackTrace
317 /// </summary>
318 public static string StackTrace {
319 [EnvironmentPermission (SecurityAction.Demand, Unrestricted=true)]
320 get {
321 System.Diagnostics.StackTrace trace = new System.Diagnostics.StackTrace (0, true);
322 return trace.ToString ();
326 /// <summary>
327 /// Get a fully qualified path to the system directory
328 /// </summary>
329 public static string SystemDirectory {
330 get {
331 return GetFolderPath (SpecialFolder.System);
335 /// <summary>
336 /// Get the number of milliseconds that have elapsed since the system was booted
337 /// </summary>
338 public extern static int TickCount {
339 [MethodImplAttribute (MethodImplOptions.InternalCall)]
340 get;
343 /// <summary>
344 /// Get UserDomainName
345 /// </summary>
346 public static string UserDomainName {
347 // FIXME: this variable doesn't exist (at least not on WinXP) - reported to MS as FDBK20562
348 [EnvironmentPermission (SecurityAction.Demand, Read="USERDOMAINNAME")]
349 get {
350 return MachineName;
354 /// <summary>
355 /// Gets a flag indicating whether the process is in interactive mode
356 /// </summary>
357 [MonoTODO ("Currently always returns false, regardless of interactive state")]
358 public static bool UserInteractive {
359 get {
360 return false;
364 /// <summary>
365 /// Get the user name of current process is running under
366 /// </summary>
367 public extern static string UserName {
368 [MethodImplAttribute (MethodImplOptions.InternalCall)]
369 [EnvironmentPermission (SecurityAction.Demand, Read="USERNAME;USER")]
370 get;
373 /// <summary>
374 /// Get the version of the common language runtime
375 /// </summary>
376 public static Version Version {
377 get {
378 return new Version (Consts.EnvironmentVersion);
382 /// <summary>
383 /// Get the amount of physical memory mapped to process
384 /// </summary>
385 [MonoTODO ("Currently always returns zero")]
386 public static long WorkingSet {
387 [EnvironmentPermission (SecurityAction.Demand, Unrestricted=true)]
388 get { return 0; }
391 [MethodImplAttribute (MethodImplOptions.InternalCall)]
392 [SecurityPermission (SecurityAction.Demand, UnmanagedCode=true)]
393 public extern static void Exit (int exitCode);
395 internal static void _Exit (int exitCode)
397 Exit (exitCode);
400 /// <summary>
401 /// Substitute environment variables in the argument "name"
402 /// </summary>
403 public static string ExpandEnvironmentVariables (string name)
405 if (name == null)
406 throw new ArgumentNullException ("name");
408 int off1 = name.IndexOf ('%');
409 if (off1 == -1)
410 return name;
412 int len = name.Length;
413 int off2 = 0;
414 if (off1 == len - 1 || (off2 = name.IndexOf ('%', off1 + 1)) == -1)
415 return name;
417 StringBuilder result = new StringBuilder ();
418 result.Append (name, 0, off1);
419 Hashtable tbl = null;
420 do {
421 string var = name.Substring (off1 + 1, off2 - off1 - 1);
422 string value = GetEnvironmentVariable (var);
423 if (value == null && Environment.IsRunningOnWindows) {
424 // On windows, env. vars. are case insensitive
425 if (tbl == null)
426 tbl = GetEnvironmentVariablesNoCase ();
428 value = tbl [var] as string;
431 // If value not found, add %FOO to stream,
432 // and use the closing % for the next iteration.
433 // If value found, expand it in place of %FOO%
434 int realOldOff2 = off2;
435 if (value == null) {
436 result.Append ('%');
437 result.Append (var);
438 off2--;
439 } else {
440 result.Append (value);
442 int oldOff2 = off2;
443 off1 = name.IndexOf ('%', off2 + 1);
444 // If no % found for off1, don't look for one for off2
445 off2 = (off1 == -1 || off2 > len-1)? -1 :name.IndexOf ('%', off1 + 1);
446 // textLen is the length of text between the closing % of current iteration
447 // and the starting % of the next iteration if any. This text is added to output
448 int textLen;
449 // If no new % found, use all the remaining text
450 if (off1 == -1 || off2 == -1)
451 textLen = len - oldOff2 - 1;
452 // If value found in current iteration, use text after current closing % and next %
453 else if(value != null)
454 textLen = off1 - oldOff2 - 1;
455 // If value not found in current iteration, but a % was found for next iteration,
456 // use text from current closing % to the next %.
457 else
458 textLen = off1 - realOldOff2;
459 if(off1 >= oldOff2 || off1 == -1)
460 result.Append (name, oldOff2+1, textLen);
461 } while (off2 > -1 && off2 < len);
463 return result.ToString ();
467 /// <summary>
468 /// Return an array of the command line arguments of the current process
469 /// </summary>
470 [MethodImplAttribute (MethodImplOptions.InternalCall)]
471 [EnvironmentPermissionAttribute (SecurityAction.Demand, Read = "PATH")]
472 public extern static string[] GetCommandLineArgs ();
474 [MethodImplAttribute (MethodImplOptions.InternalCall)]
475 internal extern static string internalGetEnvironmentVariable_native (IntPtr variable);
477 internal static string internalGetEnvironmentVariable (string variable) {
478 if (variable == null)
479 return null;
480 using (var h = Mono.RuntimeMarshal.MarshalString (variable)) {
481 return internalGetEnvironmentVariable_native (h.Value);
485 /// <summary>
486 /// Return a string containing the value of the environment
487 /// variable identifed by parameter "variable"
488 /// </summary>
489 public static string GetEnvironmentVariable (string variable)
491 #if !MOBILE
492 if (SecurityManager.SecurityEnabled) {
493 new EnvironmentPermission (EnvironmentPermissionAccess.Read, variable).Demand ();
495 #endif
496 return internalGetEnvironmentVariable (variable);
499 static Hashtable GetEnvironmentVariablesNoCase ()
501 Hashtable vars = new Hashtable (CaseInsensitiveHashCodeProvider.Default,
502 CaseInsensitiveComparer.Default);
504 foreach (string name in GetEnvironmentVariableNames ()) {
505 vars [name] = internalGetEnvironmentVariable (name);
508 return vars;
511 /// <summary>
512 /// Return a set of all environment variables and their values
513 /// </summary>
514 #if !MOBILE
515 public static IDictionary GetEnvironmentVariables ()
517 StringBuilder sb = null;
518 if (SecurityManager.SecurityEnabled) {
519 // we must have access to each variable to get the lot
520 sb = new StringBuilder ();
521 // but (performance-wise) we do not want a stack-walk
522 // for each of them so we concatenate them
525 Hashtable vars = new Hashtable ();
526 foreach (string name in GetEnvironmentVariableNames ()) {
527 vars [name] = internalGetEnvironmentVariable (name);
528 if (sb != null) {
529 sb.Append (name);
530 sb.Append (";");
534 if (sb != null) {
535 new EnvironmentPermission (EnvironmentPermissionAccess.Read, sb.ToString ()).Demand ();
537 return vars;
539 #else
540 [EnvironmentPermission (SecurityAction.Demand, Unrestricted=true)]
541 public static IDictionary GetEnvironmentVariables ()
543 Hashtable vars = new Hashtable ();
544 foreach (string name in GetEnvironmentVariableNames ()) {
545 vars [name] = internalGetEnvironmentVariable (name);
547 return vars;
549 #endif
551 /// <summary>
552 /// Returns the fully qualified path of the
553 /// folder specified by the "folder" parameter
554 /// </summary>
555 public static string GetFolderPath (SpecialFolder folder)
557 return GetFolderPath (folder, SpecialFolderOption.None);
560 #if !MONOTOUCH
561 [MethodImplAttribute (MethodImplOptions.InternalCall)]
562 private extern static string GetWindowsFolderPath (int folder);
564 public
565 static string GetFolderPath(SpecialFolder folder, SpecialFolderOption option)
567 SecurityManager.EnsureElevatedPermissions (); // this is a no-op outside moonlight
569 string dir = null;
571 if (Environment.IsRunningOnWindows)
572 dir = GetWindowsFolderPath ((int) folder);
573 else
574 dir = UnixGetFolderPath (folder, option);
576 #if !MOBILE
577 if ((dir != null) && (dir.Length > 0) && SecurityManager.SecurityEnabled) {
578 new FileIOPermission (FileIOPermissionAccess.PathDiscovery, dir).Demand ();
580 #endif
581 return dir;
584 private static string ReadXdgUserDir (string config_dir, string home_dir, string key, string fallback)
586 string env_path = internalGetEnvironmentVariable (key);
587 if (env_path != null && env_path != String.Empty) {
588 return env_path;
591 string user_dirs_path = Path.Combine (config_dir, "user-dirs.dirs");
593 if (!File.Exists (user_dirs_path)) {
594 return Path.Combine (home_dir, fallback);
597 try {
598 using(StreamReader reader = new StreamReader (user_dirs_path)) {
599 string line;
600 while ((line = reader.ReadLine ()) != null) {
601 line = line.Trim ();
602 int delim_index = line.IndexOf ('=');
603 if(delim_index > 8 && line.Substring (0, delim_index) == key) {
604 string path = line.Substring (delim_index + 1).Trim ('"');
605 bool relative = false;
607 if (path.StartsWithOrdinalUnchecked ("$HOME/")) {
608 relative = true;
609 path = path.Substring (6);
610 } else if (!path.StartsWithOrdinalUnchecked ("/")) {
611 relative = true;
614 return relative ? Path.Combine (home_dir, path) : path;
618 } catch (FileNotFoundException) {
621 return Path.Combine (home_dir, fallback);
625 // the security runtime (and maybe other parts of corlib) needs the
626 // information to initialize themselves before permissions can be checked
627 internal static string UnixGetFolderPath (SpecialFolder folder, SpecialFolderOption option)
629 string home = internalGetHome ();
631 // http://freedesktop.org/Standards/basedir-spec/basedir-spec-0.6.html
633 // note: skip security check for environment variables
634 string data = internalGetEnvironmentVariable ("XDG_DATA_HOME");
635 if ((data == null) || (data == String.Empty)) {
636 data = Path.Combine (home, ".local");
637 data = Path.Combine (data, "share");
640 // note: skip security check for environment variables
641 string config = internalGetEnvironmentVariable ("XDG_CONFIG_HOME");
642 if ((config == null) || (config == String.Empty)) {
643 config = Path.Combine (home, ".config");
646 switch (folder) {
647 // MyComputer is a virtual directory
648 case SpecialFolder.MyComputer:
649 return String.Empty;
651 // personal == ~
652 case SpecialFolder.Personal:
653 return home;
655 // use FDO's CONFIG_HOME. This data will be synced across a network like the windows counterpart.
656 case SpecialFolder.ApplicationData:
657 return config;
659 //use FDO's DATA_HOME. This is *NOT* synced
660 case SpecialFolder.LocalApplicationData:
661 return data;
663 case SpecialFolder.Desktop:
664 case SpecialFolder.DesktopDirectory:
665 return ReadXdgUserDir (config, home, "XDG_DESKTOP_DIR", "Desktop");
667 case SpecialFolder.MyMusic:
668 if (Platform == PlatformID.MacOSX)
669 return Path.Combine (home, "Music");
670 else
671 return ReadXdgUserDir (config, home, "XDG_MUSIC_DIR", "Music");
673 case SpecialFolder.MyPictures:
674 if (Platform == PlatformID.MacOSX)
675 return Path.Combine (home, "Pictures");
676 else
677 return ReadXdgUserDir (config, home, "XDG_PICTURES_DIR", "Pictures");
679 case SpecialFolder.Templates:
680 return ReadXdgUserDir (config, home, "XDG_TEMPLATES_DIR", "Templates");
681 case SpecialFolder.MyVideos:
682 return ReadXdgUserDir (config, home, "XDG_VIDEOS_DIR", "Videos");
683 case SpecialFolder.CommonTemplates:
684 return "/usr/share/templates";
685 case SpecialFolder.Fonts:
686 if (Platform == PlatformID.MacOSX)
687 return Path.Combine (home, "Library", "Fonts");
689 return Path.Combine (home, ".fonts");
690 // these simply dont exist on Linux
691 // The spec says if a folder doesnt exist, we
692 // should return ""
693 case SpecialFolder.Favorites:
694 if (Platform == PlatformID.MacOSX)
695 return Path.Combine (home, "Library", "Favorites");
696 else
697 return String.Empty;
699 case SpecialFolder.ProgramFiles:
700 if (Platform == PlatformID.MacOSX)
701 return "/Applications";
702 else
703 return String.Empty;
705 case SpecialFolder.InternetCache:
706 if (Platform == PlatformID.MacOSX)
707 return Path.Combine (home, "Library", "Caches");
708 else
709 return String.Empty;
711 // #2873
712 case SpecialFolder.UserProfile:
713 return home;
715 case SpecialFolder.Programs:
716 case SpecialFolder.SendTo:
717 case SpecialFolder.StartMenu:
718 case SpecialFolder.Startup:
719 case SpecialFolder.Cookies:
720 case SpecialFolder.History:
721 case SpecialFolder.Recent:
722 case SpecialFolder.CommonProgramFiles:
723 case SpecialFolder.System:
724 case SpecialFolder.NetworkShortcuts:
725 case SpecialFolder.CommonStartMenu:
726 case SpecialFolder.CommonPrograms:
727 case SpecialFolder.CommonStartup:
728 case SpecialFolder.CommonDesktopDirectory:
729 case SpecialFolder.PrinterShortcuts:
730 case SpecialFolder.Windows:
731 case SpecialFolder.SystemX86:
732 case SpecialFolder.ProgramFilesX86:
733 case SpecialFolder.CommonProgramFilesX86:
734 case SpecialFolder.CommonDocuments:
735 case SpecialFolder.CommonAdminTools:
736 case SpecialFolder.AdminTools:
737 case SpecialFolder.CommonMusic:
738 case SpecialFolder.CommonPictures:
739 case SpecialFolder.CommonVideos:
740 case SpecialFolder.Resources:
741 case SpecialFolder.LocalizedResources:
742 case SpecialFolder.CommonOemLinks:
743 case SpecialFolder.CDBurning:
744 return String.Empty;
745 // This is where data common to all users goes
746 case SpecialFolder.CommonApplicationData:
747 return "/usr/share";
748 default:
749 throw new ArgumentException ("Invalid SpecialFolder");
752 #endif
755 [EnvironmentPermission (SecurityAction.Demand, Unrestricted=true)]
756 public static string[] GetLogicalDrives ()
758 return GetLogicalDrivesInternal ();
761 #if !MOBILE
762 [MethodImplAttribute (MethodImplOptions.InternalCall)]
763 private static extern void internalBroadcastSettingChange ();
765 public static string GetEnvironmentVariable (string variable, EnvironmentVariableTarget target)
767 switch (target) {
768 case EnvironmentVariableTarget.Process:
769 return GetEnvironmentVariable (variable);
770 case EnvironmentVariableTarget.Machine:
771 new EnvironmentPermission (PermissionState.Unrestricted).Demand ();
772 if (!IsRunningOnWindows)
773 return null;
774 using (Microsoft.Win32.RegistryKey env = Microsoft.Win32.Registry.LocalMachine.OpenSubKey (@"SYSTEM\CurrentControlSet\Control\Session Manager\Environment")) {
775 object regvalue = env.GetValue (variable);
776 return (regvalue == null) ? null : regvalue.ToString ();
778 case EnvironmentVariableTarget.User:
779 new EnvironmentPermission (PermissionState.Unrestricted).Demand ();
780 if (!IsRunningOnWindows)
781 return null;
782 using (Microsoft.Win32.RegistryKey env = Microsoft.Win32.Registry.CurrentUser.OpenSubKey ("Environment", false)) {
783 object regvalue = env.GetValue (variable);
784 return (regvalue == null) ? null : regvalue.ToString ();
786 default:
787 throw new ArgumentException ("target");
791 public static IDictionary GetEnvironmentVariables (EnvironmentVariableTarget target)
793 IDictionary variables = (IDictionary)new Hashtable ();
794 switch (target) {
795 case EnvironmentVariableTarget.Process:
796 variables = GetEnvironmentVariables ();
797 break;
798 case EnvironmentVariableTarget.Machine:
799 new EnvironmentPermission (PermissionState.Unrestricted).Demand ();
800 if (IsRunningOnWindows) {
801 using (Microsoft.Win32.RegistryKey env = Microsoft.Win32.Registry.LocalMachine.OpenSubKey (@"SYSTEM\CurrentControlSet\Control\Session Manager\Environment")) {
802 string[] value_names = env.GetValueNames ();
803 foreach (string value_name in value_names)
804 variables.Add (value_name, env.GetValue (value_name));
807 break;
808 case EnvironmentVariableTarget.User:
809 new EnvironmentPermission (PermissionState.Unrestricted).Demand ();
810 if (IsRunningOnWindows) {
811 using (Microsoft.Win32.RegistryKey env = Microsoft.Win32.Registry.CurrentUser.OpenSubKey ("Environment")) {
812 string[] value_names = env.GetValueNames ();
813 foreach (string value_name in value_names)
814 variables.Add (value_name, env.GetValue (value_name));
817 break;
818 default:
819 throw new ArgumentException ("target");
821 return variables;
824 [EnvironmentPermission (SecurityAction.Demand, Unrestricted=true)]
825 public static void SetEnvironmentVariable (string variable, string value)
827 SetEnvironmentVariable (variable, value, EnvironmentVariableTarget.Process);
830 [EnvironmentPermission (SecurityAction.Demand, Unrestricted = true)]
831 public static void SetEnvironmentVariable (string variable, string value, EnvironmentVariableTarget target)
833 if (variable == null)
834 throw new ArgumentNullException ("variable");
835 if (variable == String.Empty)
836 throw new ArgumentException ("String cannot be of zero length.", "variable");
837 if (variable.IndexOf ('=') != -1)
838 throw new ArgumentException ("Environment variable name cannot contain an equal character.", "variable");
839 if (variable[0] == '\0')
840 throw new ArgumentException ("The first char in the string is the null character.", "variable");
842 switch (target) {
843 case EnvironmentVariableTarget.Process:
844 InternalSetEnvironmentVariable (variable, value);
845 break;
846 case EnvironmentVariableTarget.Machine:
847 if (!IsRunningOnWindows)
848 return;
849 using (Microsoft.Win32.RegistryKey env = Microsoft.Win32.Registry.LocalMachine.OpenSubKey (@"SYSTEM\CurrentControlSet\Control\Session Manager\Environment", true)) {
850 if (String.IsNullOrEmpty (value))
851 env.DeleteValue (variable, false);
852 else
853 env.SetValue (variable, value);
854 internalBroadcastSettingChange ();
856 break;
857 case EnvironmentVariableTarget.User:
858 if (!IsRunningOnWindows)
859 return;
860 using (Microsoft.Win32.RegistryKey env = Microsoft.Win32.Registry.CurrentUser.OpenSubKey ("Environment", true)) {
861 if (String.IsNullOrEmpty (value))
862 env.DeleteValue (variable, false);
863 else
864 env.SetValue (variable, value);
865 internalBroadcastSettingChange ();
867 break;
868 default:
869 throw new ArgumentException ("target");
872 #else
873 public static string GetEnvironmentVariable (string variable, EnvironmentVariableTarget target)
875 if (target == EnvironmentVariableTarget.Process)
876 return GetEnvironmentVariable (variable);
878 return null;
881 public static IDictionary GetEnvironmentVariables (EnvironmentVariableTarget target)
883 if (target == EnvironmentVariableTarget.Process)
884 return GetEnvironmentVariables ();
886 return (IDictionary)new Hashtable ();
889 public static void SetEnvironmentVariable (string variable, string value)
891 if (variable == null)
892 throw new ArgumentNullException ("variable");
893 if (variable == String.Empty)
894 throw new ArgumentException ("String cannot be of zero length.", "variable");
895 if (variable.IndexOf ('=') != -1)
896 throw new ArgumentException ("Environment variable name cannot contain an equal character.", "variable");
897 if (variable[0] == '\0')
898 throw new ArgumentException ("The first char in the string is the null character.", "variable");
900 InternalSetEnvironmentVariable (variable, value);
903 public static void SetEnvironmentVariable (string variable, string value, EnvironmentVariableTarget target)
905 if (target == EnvironmentVariableTarget.Process)
906 SetEnvironmentVariable (variable, value);
908 // other targets ignored
910 #endif
911 [MethodImplAttribute (MethodImplOptions.InternalCall)]
912 internal static extern void InternalSetEnvironmentVariable (string variable, string value);
914 [SecurityPermission (SecurityAction.LinkDemand, UnmanagedCode=true)]
915 public static void FailFast (string message)
917 throw new NotImplementedException ();
920 internal static void FailFast (String message, uint exitCode)
922 throw new NotImplementedException ();
925 [SecurityCritical]
926 public static void FailFast (string message, Exception exception)
928 #pragma warning disable 618
929 throw new ExecutionEngineException (message, exception);
930 #pragma warning restore
933 [MethodImplAttribute (MethodImplOptions.InternalCall)]
934 extern static bool GetIs64BitOperatingSystem ();
936 public static bool Is64BitOperatingSystem {
937 get { return GetIs64BitOperatingSystem (); }
940 public static int SystemPageSize {
941 get { return GetPageSize (); }
944 public
945 static bool Is64BitProcess {
946 get { return IntPtr.Size == 8; }
949 public static extern int ProcessorCount {
950 [EnvironmentPermission (SecurityAction.Demand, Read="NUMBER_OF_PROCESSORS")]
951 [MethodImplAttribute (MethodImplOptions.InternalCall)]
952 get;
955 // private methods
956 #if (MONOTOUCH || MONODROID || XAMMAC)
957 internal const bool IsRunningOnWindows = false;
958 #else
959 internal static bool IsRunningOnWindows {
960 get { return ((int) Platform < 4); }
962 #endif
964 #if !MOBILE
966 // Used by gacutil.exe
968 #pragma warning disable 169
969 private static string GacPath {
970 get {
971 if (Environment.IsRunningOnWindows) {
972 /* On windows, we don't know the path where mscorlib.dll will be installed */
973 string corlibDir = new DirectoryInfo (Path.GetDirectoryName (typeof (int).Assembly.Location)).Parent.Parent.FullName;
974 return Path.Combine (Path.Combine (corlibDir, "mono"), "gac");
977 return Path.Combine (Path.Combine (internalGetGacPath (), "mono"), "gac");
980 #pragma warning restore 169
981 [MethodImplAttribute (MethodImplOptions.InternalCall)]
982 internal extern static string internalGetGacPath ();
983 #endif
984 [MethodImplAttribute (MethodImplOptions.InternalCall)]
985 private extern static string [] GetLogicalDrivesInternal ();
987 [MethodImplAttribute (MethodImplOptions.InternalCall)]
988 private extern static string [] GetEnvironmentVariableNames ();
990 [MethodImplAttribute (MethodImplOptions.InternalCall)]
991 internal extern static string GetMachineConfigPath ();
993 [MethodImplAttribute (MethodImplOptions.InternalCall)]
994 internal extern static string internalGetHome ();
996 [MethodImplAttribute (MethodImplOptions.InternalCall)]
997 internal extern static int GetPageSize ();
999 [MethodImplAttribute(MethodImplOptions.InternalCall)]
1000 extern private static string get_bundled_machine_config ();
1002 internal static string GetBundledMachineConfig ()
1004 return get_bundled_machine_config ();
1007 static internal bool IsUnix {
1008 get {
1009 int platform = (int) Environment.Platform;
1011 return (platform == 4 || platform == 128 || platform == 6);
1014 static internal bool IsMacOS {
1015 get {
1016 return Environment.Platform == PlatformID.MacOSX;
1020 internal static bool IsCLRHosted {
1021 get {
1022 return false;
1026 internal static void TriggerCodeContractFailure(ContractFailureKind failureKind, String message, String condition, String exceptionAsString)
1031 // Copied from referencesource Environment
1032 internal static String GetStackTrace(Exception e, bool needFileInfo)
1034 System.Diagnostics.StackTrace st;
1035 if (e == null)
1036 st = new System.Diagnostics.StackTrace(needFileInfo);
1037 else
1038 st = new System.Diagnostics.StackTrace(e, needFileInfo);
1040 // Do not include a trailing newline for backwards compatibility
1041 return st.ToString( System.Diagnostics.StackTrace.TraceFormat.Normal );
1044 // Copied from referencesource Environment
1045 internal static bool IsWinRTSupported
1049 return true;