1 //------------------------------------------------------------------------------
3 // System.Environment.cs
5 // Copyright (C) 2001 Moonlight Enterprises, All Rights Reserved
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:
23 // The above copyright notice and this permission notice shall be
24 // included in all copies or substantial portions of the Software.
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.
36 using System
.Collections
;
37 using System
.Runtime
.CompilerServices
;
38 using System
.Security
;
39 using System
.Security
.Permissions
;
41 using System
.Runtime
.InteropServices
;
46 public static class Environment
{
49 * This is the version number of the corlib-runtime interface. When
50 * making changes to this interface (by changing the layout
51 * of classes the runtime knows about, changing icall signature or
52 * semantics etc), increment this variable. Also increment the
53 * pair of this variable in the runtime in metadata/appdomain.c.
54 * Changes which are already detected at runtime, like the addition
55 * of icalls, do not require an increment.
57 #pragma warning disable 169
58 private const int mono_corlib_version
= 105 + 0x0210;
59 #pragma warning restore 169
62 public enum SpecialFolder
75 DesktopDirectory
= 0x10,
77 ApplicationData
= 0x1a,
78 LocalApplicationData
= 0x1c,
82 CommonApplicationData
= 0x23,
86 CommonProgramFiles
= 0x2b,
87 #if NET_4_0 || MOONLIGHT || MOBILE
91 NetworkShortcuts
= 0x13,
93 CommonStartMenu
= 0x16,
94 CommonPrograms
= 0x17,
96 CommonDesktopDirectory
= 0x19,
97 PrinterShortcuts
= 0x1b,
101 ProgramFilesX86
= 0x2a,
102 CommonProgramFilesX86
= 0x2c,
103 CommonTemplates
= 0x2d,
104 CommonDocuments
= 0x2e,
105 CommonAdminTools
= 0x2f,
108 CommonPictures
= 0x36,
111 LocalizedResources
= 0x39,
112 CommonOemLinks
= 0x3a,
122 enum SpecialFolderOption
{
124 DoNotVerify
= 0x4000,
129 /// Gets the command line for this process
131 public static string CommandLine
{
132 // note: security demand inherited from calling GetCommandLineArgs
134 StringBuilder sb
= new StringBuilder ();
135 foreach (string str
in GetCommandLineArgs ()) {
139 for (int i
= 0; i
< s
.Length
; i
++) {
140 if (quote
.Length
== 0 && Char
.IsWhiteSpace (s
[i
])) {
142 } else if (s
[i
] == '"') {
146 if (escape
&& quote
.Length
!= 0) {
147 s
= s
.Replace ("\"", "\\\"");
149 sb
.AppendFormat ("{0}{1}{0} ", quote
, s
);
153 return sb
.ToString ();
158 /// Gets or sets the current directory. Actually this is supposed to get
159 /// and/or set the process start directory acording to the documentation
160 /// but actually test revealed at beta2 it is just Getting/Setting the CurrentDirectory
162 public static string CurrentDirectory
165 return Directory
.GetCurrentDirectory ();
168 Directory
.SetCurrentDirectory (value);
173 /// Gets or sets the exit code of this process
175 public extern static int ExitCode
177 [MethodImplAttribute (MethodImplOptions
.InternalCall
)]
179 [MethodImplAttribute (MethodImplOptions
.InternalCall
)]
183 static public extern bool HasShutdownStarted
185 [MethodImplAttribute (MethodImplOptions
.InternalCall
)]
191 /// Gets the name of the local computer
193 public extern static string MachineName
{
194 [MethodImplAttribute (MethodImplOptions
.InternalCall
)]
195 [EnvironmentPermission (SecurityAction
.Demand
, Read
="COMPUTERNAME")]
196 [SecurityPermission (SecurityAction
.Demand
, UnmanagedCode
=true)]
200 [MethodImplAttribute (MethodImplOptions
.InternalCall
)]
201 extern static string GetNewLine ();
205 /// Gets the standard new line value
207 public static string NewLine
{
218 // Support methods and fields for OSVersion property
220 static OperatingSystem os
;
222 static extern PlatformID Platform
{
223 [MethodImplAttribute (MethodImplOptions
.InternalCall
)]
227 [MethodImplAttribute (MethodImplOptions
.InternalCall
)]
228 internal static extern string GetOSVersionString ();
231 /// Gets the current OS version information
233 public static OperatingSystem OSVersion
{
236 Version v
= Version
.CreateFromString (GetOSVersionString ());
237 PlatformID p
= Platform
;
238 if (p
== PlatformID
.MacOSX
)
240 os
= new OperatingSystem (p
, v
);
249 public static string StackTrace
{
250 [EnvironmentPermission (SecurityAction
.Demand
, Unrestricted
=true)]
252 System
.Diagnostics
.StackTrace trace
= new System
.Diagnostics
.StackTrace (0, true);
253 return trace
.ToString ();
258 /// Get a fully qualified path to the system directory
260 public static string SystemDirectory
{
262 return GetFolderPath (SpecialFolder
.System
);
267 /// Get the number of milliseconds that have elapsed since the system was booted
269 public extern static int TickCount
{
270 [MethodImplAttribute (MethodImplOptions
.InternalCall
)]
275 /// Get UserDomainName
277 public static string UserDomainName
{
278 // FIXME: this variable doesn't exist (at least not on WinXP) - reported to MS as FDBK20562
279 [EnvironmentPermission (SecurityAction
.Demand
, Read
="USERDOMAINNAME")]
286 /// Gets a flag indicating whether the process is in interactive mode
288 [MonoTODO ("Currently always returns false, regardless of interactive state")]
289 public static bool UserInteractive
{
296 /// Get the user name of current process is running under
298 public extern static string UserName
{
299 [MethodImplAttribute (MethodImplOptions
.InternalCall
)]
300 [EnvironmentPermission (SecurityAction
.Demand
, Read
="USERNAME;USER")]
305 /// Get the version of the common language runtime
307 public static Version Version
{
309 return new Version (Consts
.FxFileVersion
);
314 /// Get the amount of physical memory mapped to process
316 [MonoTODO ("Currently always returns zero")]
317 public static long WorkingSet
{
318 [EnvironmentPermission (SecurityAction
.Demand
, Unrestricted
=true)]
322 [MethodImplAttribute (MethodImplOptions
.InternalCall
)]
323 [SecurityPermission (SecurityAction
.Demand
, UnmanagedCode
=true)]
324 public extern static void Exit (int exitCode
);
327 /// Substitute environment variables in the argument "name"
329 public static string ExpandEnvironmentVariables (string name
)
332 throw new ArgumentNullException ("name");
334 int off1
= name
.IndexOf ('%');
338 int len
= name
.Length
;
340 if (off1
== len
- 1 || (off2
= name
.IndexOf ('%', off1
+ 1)) == -1)
343 StringBuilder result
= new StringBuilder ();
344 result
.Append (name
, 0, off1
);
345 Hashtable tbl
= null;
347 string var = name
.Substring (off1
+ 1, off2
- off1
- 1);
348 string value = GetEnvironmentVariable (var);
349 if (value == null && Environment
.IsRunningOnWindows
) {
350 // On windows, env. vars. are case insensitive
352 tbl
= GetEnvironmentVariablesNoCase ();
354 value = tbl
[var] as string;
357 // If value not found, add %FOO to stream,
358 // and use the closing % for the next iteration.
359 // If value found, expand it in place of %FOO%
365 result
.Append (value);
368 off1
= name
.IndexOf ('%', off2
+ 1);
369 // If no % found for off1, don't look for one for off2
370 off2
= (off1
== -1 || off2
> len
-1)? -1 :name
.IndexOf ('%', off1
+ 1);
371 // textLen is the length of text between the closing % of current iteration
372 // and the starting % of the next iteration if any. This text is added to output
374 // If no new % found, use all the remaining text
375 if (off1
== -1 || off2
== -1)
376 textLen
= len
- oldOff2
- 1;
377 // If value found in current iteration, use text after current closing % and next %
378 else if(value != null)
379 textLen
= off1
- oldOff2
- 1;
380 // If value not found in current iteration, but a % was found for next iteration,
381 // use text from current closing % to the next %.
383 textLen
= off1
- oldOff2
;
384 if(off1
>= oldOff2
|| off1
== -1)
385 result
.Append (name
, oldOff2
+1, textLen
);
386 } while (off2
> -1 && off2
< len
);
388 return result
.ToString ();
393 /// Return an array of the command line arguments of the current process
395 [MethodImplAttribute (MethodImplOptions
.InternalCall
)]
396 [EnvironmentPermissionAttribute (SecurityAction
.Demand
, Read
= "PATH")]
397 public extern static string[] GetCommandLineArgs ();
399 [MethodImplAttribute (MethodImplOptions
.InternalCall
)]
400 internal extern static string internalGetEnvironmentVariable (string variable
);
403 /// Return a string containing the value of the environment
404 /// variable identifed by parameter "variable"
406 public static string GetEnvironmentVariable (string variable
)
409 if (SecurityManager
.SecurityEnabled
) {
410 new EnvironmentPermission (EnvironmentPermissionAccess
.Read
, variable
).Demand ();
413 return internalGetEnvironmentVariable (variable
);
416 static Hashtable
GetEnvironmentVariablesNoCase ()
418 Hashtable vars
= new Hashtable (CaseInsensitiveHashCodeProvider
.Default
,
419 CaseInsensitiveComparer
.Default
);
421 foreach (string name
in GetEnvironmentVariableNames ()) {
422 vars
[name
] = internalGetEnvironmentVariable (name
);
429 /// Return a set of all environment variables and their values
432 public static IDictionary
GetEnvironmentVariables ()
434 StringBuilder sb
= null;
435 if (SecurityManager
.SecurityEnabled
) {
436 // we must have access to each variable to get the lot
437 sb
= new StringBuilder ();
438 // but (performance-wise) we do not want a stack-walk
439 // for each of them so we concatenate them
442 Hashtable vars
= new Hashtable ();
443 foreach (string name
in GetEnvironmentVariableNames ()) {
444 vars
[name
] = internalGetEnvironmentVariable (name
);
452 new EnvironmentPermission (EnvironmentPermissionAccess
.Read
, sb
.ToString ()).Demand ();
457 [EnvironmentPermission (SecurityAction
.Demand
, Unrestricted
=true)]
458 public static IDictionary
GetEnvironmentVariables ()
460 Hashtable vars
= new Hashtable ();
461 foreach (string name
in GetEnvironmentVariableNames ()) {
462 vars
[name
] = internalGetEnvironmentVariable (name
);
468 [MethodImplAttribute (MethodImplOptions
.InternalCall
)]
469 private extern static string GetWindowsFolderPath (int folder
);
472 /// Returns the fully qualified path of the
473 /// folder specified by the "folder" parameter
475 public static string GetFolderPath (SpecialFolder folder
)
477 return GetFolderPath (folder
, SpecialFolderOption
.None
);
482 static string GetFolderPath(SpecialFolder folder
, SpecialFolderOption option
)
484 SecurityManager
.EnsureElevatedPermissions (); // this is a no-op outside moonlight
488 if (Environment
.IsRunningOnWindows
)
489 dir
= GetWindowsFolderPath ((int) folder
);
491 dir
= UnixGetFolderPath (folder
, option
);
494 if ((dir
!= null) && (dir
.Length
> 0) && SecurityManager
.SecurityEnabled
) {
495 new FileIOPermission (FileIOPermissionAccess
.PathDiscovery
, dir
).Demand ();
501 private static string ReadXdgUserDir (string config_dir
, string home_dir
, string key
, string fallback
)
503 string env_path
= internalGetEnvironmentVariable (key
);
504 if (env_path
!= null && env_path
!= String
.Empty
) {
508 string user_dirs_path
= Path
.Combine (config_dir
, "user-dirs.dirs");
510 if (!File
.Exists (user_dirs_path
)) {
511 return Path
.Combine (home_dir
, fallback
);
515 using(StreamReader reader
= new StreamReader (user_dirs_path
)) {
517 while ((line
= reader
.ReadLine ()) != null) {
519 int delim_index
= line
.IndexOf ('=');
520 if(delim_index
> 8 && line
.Substring (0, delim_index
) == key
) {
521 string path
= line
.Substring (delim_index
+ 1).Trim ('"');
522 bool relative
= false;
524 if (path
.StartsWith ("$HOME/")) {
526 path
= path
.Substring (6);
527 } else if (!path
.StartsWith ("/")) {
531 return relative
? Path
.Combine (home_dir
, path
) : path
;
535 } catch (FileNotFoundException
) {
538 return Path
.Combine (home_dir
, fallback
);
542 // the security runtime (and maybe other parts of corlib) needs the
543 // information to initialize themselves before permissions can be checked
544 internal static string UnixGetFolderPath (SpecialFolder folder
, SpecialFolderOption option
)
546 string home
= internalGetHome ();
548 // http://freedesktop.org/Standards/basedir-spec/basedir-spec-0.6.html
550 // note: skip security check for environment variables
551 string data
= internalGetEnvironmentVariable ("XDG_DATA_HOME");
552 if ((data
== null) || (data
== String
.Empty
)) {
553 data
= Path
.Combine (home
, ".local");
554 data
= Path
.Combine (data
, "share");
557 // note: skip security check for environment variables
558 string config
= internalGetEnvironmentVariable ("XDG_CONFIG_HOME");
559 if ((config
== null) || (config
== String
.Empty
)) {
560 config
= Path
.Combine (home
, ".config");
564 // MyComputer is a virtual directory
565 case SpecialFolder
.MyComputer
:
569 case SpecialFolder
.Personal
:
571 return Path
.Combine (home
, "Documents");
575 // use FDO's CONFIG_HOME. This data will be synced across a network like the windows counterpart.
576 case SpecialFolder
.ApplicationData
:
579 string dir
= Path
.Combine (Path
.Combine (home
, "Documents"), ".config");
580 if (option
== SpecialFolderOption
.Create
){
581 if (!Directory
.Exists (dir
))
582 Directory
.CreateDirectory (dir
);
589 //use FDO's DATA_HOME. This is *NOT* synced
590 case SpecialFolder
.LocalApplicationData
:
593 string dir
= Path
.Combine (home
, "Documents");
594 if (!Directory
.Exists (dir
))
595 Directory
.CreateDirectory (dir
);
603 case SpecialFolder
.Desktop
:
604 case SpecialFolder
.DesktopDirectory
:
605 return ReadXdgUserDir (config
, home
, "XDG_DESKTOP_DIR", "Desktop");
607 case SpecialFolder
.MyMusic
:
608 if (Platform
== PlatformID
.MacOSX
)
609 return Path
.Combine (home
, "Music");
611 return ReadXdgUserDir (config
, home
, "XDG_MUSIC_DIR", "Music");
613 case SpecialFolder
.MyPictures
:
614 if (Platform
== PlatformID
.MacOSX
)
615 return Path
.Combine (home
, "Pictures");
617 return ReadXdgUserDir (config
, home
, "XDG_PICTURES_DIR", "Pictures");
619 case SpecialFolder
.Templates
:
620 return ReadXdgUserDir (config
, home
, "XDG_TEMPLATES_DIR", "Templates");
621 #if NET_4_0 || MOONLIGHT || MOBILE
622 case SpecialFolder
.MyVideos
:
623 return ReadXdgUserDir (config
, home
, "XDG_VIDEOS_DIR", "Videos");
626 case SpecialFolder
.CommonTemplates
:
627 return "/usr/share/templates";
628 case SpecialFolder
.Fonts
:
629 if (Platform
== PlatformID
.MacOSX
)
630 return Path
.Combine (home
, "Library", "Fonts");
632 return Path
.Combine (home
, ".fonts");
634 // these simply dont exist on Linux
635 // The spec says if a folder doesnt exist, we
637 case SpecialFolder
.Favorites
:
638 if (Platform
== PlatformID
.MacOSX
)
639 return Path
.Combine (home
, "Library", "Favorites");
643 case SpecialFolder
.ProgramFiles
:
644 if (Platform
== PlatformID
.MacOSX
)
645 return "/Applications";
649 case SpecialFolder
.InternetCache
:
650 if (Platform
== PlatformID
.MacOSX
)
651 return Path
.Combine (home
, "Library", "Caches");
657 case SpecialFolder
.UserProfile
:
661 case SpecialFolder
.Programs
:
662 case SpecialFolder
.SendTo
:
663 case SpecialFolder
.StartMenu
:
664 case SpecialFolder
.Startup
:
665 case SpecialFolder
.Cookies
:
666 case SpecialFolder
.History
:
667 case SpecialFolder
.Recent
:
668 case SpecialFolder
.CommonProgramFiles
:
669 case SpecialFolder
.System
:
671 case SpecialFolder
.NetworkShortcuts
:
672 case SpecialFolder
.CommonStartMenu
:
673 case SpecialFolder
.CommonPrograms
:
674 case SpecialFolder
.CommonStartup
:
675 case SpecialFolder
.CommonDesktopDirectory
:
676 case SpecialFolder
.PrinterShortcuts
:
677 case SpecialFolder
.Windows
:
678 case SpecialFolder
.SystemX86
:
679 case SpecialFolder
.ProgramFilesX86
:
680 case SpecialFolder
.CommonProgramFilesX86
:
681 case SpecialFolder
.CommonDocuments
:
682 case SpecialFolder
.CommonAdminTools
:
683 case SpecialFolder
.AdminTools
:
684 case SpecialFolder
.CommonMusic
:
685 case SpecialFolder
.CommonPictures
:
686 case SpecialFolder
.CommonVideos
:
687 case SpecialFolder
.Resources
:
688 case SpecialFolder
.LocalizedResources
:
689 case SpecialFolder
.CommonOemLinks
:
690 case SpecialFolder
.CDBurning
:
693 // This is where data common to all users goes
694 case SpecialFolder
.CommonApplicationData
:
697 throw new ArgumentException ("Invalid SpecialFolder");
702 [EnvironmentPermission (SecurityAction
.Demand
, Unrestricted
=true)]
703 public static string[] GetLogicalDrives ()
705 return GetLogicalDrivesInternal ();
709 [MethodImplAttribute (MethodImplOptions
.InternalCall
)]
710 private static extern void internalBroadcastSettingChange ();
712 public static string GetEnvironmentVariable (string variable
, EnvironmentVariableTarget target
)
715 case EnvironmentVariableTarget
.Process
:
716 return GetEnvironmentVariable (variable
);
717 case EnvironmentVariableTarget
.Machine
:
718 new EnvironmentPermission (PermissionState
.Unrestricted
).Demand ();
719 if (!IsRunningOnWindows
)
721 using (Microsoft
.Win32
.RegistryKey env
= Microsoft
.Win32
.Registry
.LocalMachine
.OpenSubKey (@"SYSTEM\CurrentControlSet\Control\Session Manager\Environment")) {
722 object regvalue
= env
.GetValue (variable
);
723 return (regvalue
== null) ? null : regvalue
.ToString ();
725 case EnvironmentVariableTarget
.User
:
726 new EnvironmentPermission (PermissionState
.Unrestricted
).Demand ();
727 if (!IsRunningOnWindows
)
729 using (Microsoft
.Win32
.RegistryKey env
= Microsoft
.Win32
.Registry
.CurrentUser
.OpenSubKey ("Environment", false)) {
730 object regvalue
= env
.GetValue (variable
);
731 return (regvalue
== null) ? null : regvalue
.ToString ();
734 throw new ArgumentException ("target");
738 public static IDictionary
GetEnvironmentVariables (EnvironmentVariableTarget target
)
740 IDictionary variables
= (IDictionary
)new Hashtable ();
742 case EnvironmentVariableTarget
.Process
:
743 variables
= GetEnvironmentVariables ();
745 case EnvironmentVariableTarget
.Machine
:
746 new EnvironmentPermission (PermissionState
.Unrestricted
).Demand ();
747 if (IsRunningOnWindows
) {
748 using (Microsoft
.Win32
.RegistryKey env
= Microsoft
.Win32
.Registry
.LocalMachine
.OpenSubKey (@"SYSTEM\CurrentControlSet\Control\Session Manager\Environment")) {
749 string[] value_names
= env
.GetValueNames ();
750 foreach (string value_name
in value_names
)
751 variables
.Add (value_name
, env
.GetValue (value_name
));
755 case EnvironmentVariableTarget
.User
:
756 new EnvironmentPermission (PermissionState
.Unrestricted
).Demand ();
757 if (IsRunningOnWindows
) {
758 using (Microsoft
.Win32
.RegistryKey env
= Microsoft
.Win32
.Registry
.CurrentUser
.OpenSubKey ("Environment")) {
759 string[] value_names
= env
.GetValueNames ();
760 foreach (string value_name
in value_names
)
761 variables
.Add (value_name
, env
.GetValue (value_name
));
766 throw new ArgumentException ("target");
771 [EnvironmentPermission (SecurityAction
.Demand
, Unrestricted
=true)]
772 public static void SetEnvironmentVariable (string variable
, string value)
774 SetEnvironmentVariable (variable
, value, EnvironmentVariableTarget
.Process
);
777 [EnvironmentPermission (SecurityAction
.Demand
, Unrestricted
= true)]
778 public static void SetEnvironmentVariable (string variable
, string value, EnvironmentVariableTarget target
)
780 if (variable
== null)
781 throw new ArgumentNullException ("variable");
782 if (variable
== String
.Empty
)
783 throw new ArgumentException ("String cannot be of zero length.", "variable");
784 if (variable
.IndexOf ('=') != -1)
785 throw new ArgumentException ("Environment variable name cannot contain an equal character.", "variable");
786 if (variable
[0] == '\0')
787 throw new ArgumentException ("The first char in the string is the null character.", "variable");
790 case EnvironmentVariableTarget
.Process
:
791 InternalSetEnvironmentVariable (variable
, value);
793 case EnvironmentVariableTarget
.Machine
:
794 if (!IsRunningOnWindows
)
796 using (Microsoft
.Win32
.RegistryKey env
= Microsoft
.Win32
.Registry
.LocalMachine
.OpenSubKey (@"SYSTEM\CurrentControlSet\Control\Session Manager\Environment", true)) {
797 if (String
.IsNullOrEmpty (value))
798 env
.DeleteValue (variable
, false);
800 env
.SetValue (variable
, value);
801 internalBroadcastSettingChange ();
804 case EnvironmentVariableTarget
.User
:
805 if (!IsRunningOnWindows
)
807 using (Microsoft
.Win32
.RegistryKey env
= Microsoft
.Win32
.Registry
.CurrentUser
.OpenSubKey ("Environment", true)) {
808 if (String
.IsNullOrEmpty (value))
809 env
.DeleteValue (variable
, false);
811 env
.SetValue (variable
, value);
812 internalBroadcastSettingChange ();
816 throw new ArgumentException ("target");
820 [MethodImplAttribute (MethodImplOptions
.InternalCall
)]
821 internal static extern void InternalSetEnvironmentVariable (string variable
, string value);
823 [SecurityPermission (SecurityAction
.LinkDemand
, UnmanagedCode
=true)]
824 public static void FailFast (string message
)
826 throw new NotImplementedException ();
829 #if NET_4_0 || MOONLIGHT || MOBILE
831 public static void FailFast (string message
, Exception exception
)
833 throw new NotImplementedException ();
838 public static bool Is64BitOperatingSystem
{
839 get { return IntPtr.Size == 8; }
// FIXME: is this good enough?
842 public static bool Is64BitProcess
{
843 get { return Is64BitOperatingSystem; }
846 public static int SystemPageSize
{
847 get { return GetPageSize (); }
851 public static extern int ProcessorCount
{
852 [EnvironmentPermission (SecurityAction
.Demand
, Read
="NUMBER_OF_PROCESSORS")]
853 [MethodImplAttribute (MethodImplOptions
.InternalCall
)]
859 internal static bool IsRunningOnWindows
{
860 get { return ((int) Platform < 4); }
864 // Used by gacutil.exe
866 #pragma warning disable 169
867 private static string GacPath
{
869 if (Environment
.IsRunningOnWindows
) {
870 /* On windows, we don't know the path where mscorlib.dll will be installed */
871 string corlibDir
= new DirectoryInfo (Path
.GetDirectoryName (typeof (int).Assembly
.Location
)).Parent
.Parent
.FullName
;
872 return Path
.Combine (Path
.Combine (corlibDir
, "mono"), "gac");
875 return Path
.Combine (Path
.Combine (internalGetGacPath (), "mono"), "gac");
878 #pragma warning restore 169
879 [MethodImplAttribute (MethodImplOptions
.InternalCall
)]
880 internal extern static string internalGetGacPath ();
882 [MethodImplAttribute (MethodImplOptions
.InternalCall
)]
883 private extern static string [] GetLogicalDrivesInternal ();
885 [MethodImplAttribute (MethodImplOptions
.InternalCall
)]
886 private extern static string [] GetEnvironmentVariableNames ();
888 [MethodImplAttribute (MethodImplOptions
.InternalCall
)]
889 internal extern static string GetMachineConfigPath ();
891 [MethodImplAttribute (MethodImplOptions
.InternalCall
)]
892 internal extern static string internalGetHome ();
894 [MethodImplAttribute (MethodImplOptions
.InternalCall
)]
895 internal extern static int GetPageSize ();
897 static internal bool IsUnix
{
899 int platform
= (int) Environment
.Platform
;
901 return (platform
== 4 || platform
== 128 || platform
== 6);
904 static internal bool IsMacOS
{
906 return Environment
.Platform
== PlatformID
.MacOSX
;