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 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.
37 //using System.Diagnostics;
38 using System
.Collections
;
39 using System
.Security
;
40 using System
.Security
.Permissions
;
41 using System
.Runtime
.CompilerServices
;
46 public sealed 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 semantics etc),
52 * 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 private const int mono_corlib_version
= 28;
59 private Environment ()
64 public enum SpecialFolder
65 { // TODO: Determine if these windoze style folder identifiers
66 // have unix/linux counterparts
80 DesktopDirectory
= 0x10,
82 ApplicationData
= 0x1a,
83 LocalApplicationData
= 0x1c,
87 CommonApplicationData
= 0x23,
91 CommonProgramFiles
= 0x2b,
94 // TODO: Make sure the security attributes do what I expect
97 /// Gets the command line for this process
99 public static string CommandLine
100 { // TODO: Coordinate with implementor of EnvironmentPermissionAttribute
101 // [EnvironmentPermissionAttribute(SecurityAction.Demand, Read = "COMMANDLINE")]
104 // FIXME: we may need to quote, but any sane person
105 // should use GetCommandLineArgs () instead.
106 return String
.Join (" ", GetCommandLineArgs ());
111 /// Gets or sets the current directory. Actually this is supposed to get
112 /// and/or set the process start directory acording to the documentation
113 /// but actually test revealed at beta2 it is just Getting/Setting the CurrentDirectory
115 public static string CurrentDirectory
117 // originally it was my thought that the external call would be made in
118 // the directory class however that class has additional security requirements
119 // so the Directory class will call this class for its get/set current directory
121 return Directory
.GetCurrentDirectory ();
124 Directory
.SetCurrentDirectory (value);
129 /// Gets or sets the exit code of this process
131 public extern static int ExitCode
133 [MethodImplAttribute (MethodImplOptions
.InternalCall
)]
135 [MethodImplAttribute (MethodImplOptions
.InternalCall
)]
142 public extern bool HasShutdownStarted
144 [MethodImplAttribute (MethodImplOptions
.InternalCall
)]
150 /// Gets the name of the local computer
152 public extern static string MachineName
{
153 [MethodImplAttribute (MethodImplOptions
.InternalCall
)]
158 /// Gets the standard new line value
160 public extern static string NewLine
{
161 [MethodImplAttribute (MethodImplOptions
.InternalCall
)]
166 // Support methods and fields for OSVersion property
168 static OperatingSystem os
;
170 internal static extern PlatformID Platform
{
171 [MethodImplAttribute (MethodImplOptions
.InternalCall
)]
175 [MethodImplAttribute (MethodImplOptions
.InternalCall
)]
176 internal static extern string GetOSVersionString ();
179 /// Gets the current OS version information
181 public static OperatingSystem OSVersion
{
184 Version v
= Version
.CreateFromString (GetOSVersionString ());
185 os
= new OperatingSystem (Platform
, v
);
194 public static string StackTrace
{
196 System
.Diagnostics
.StackTrace trace
= new System
.Diagnostics
.StackTrace (1);
197 return trace
.ToString ();
202 /// Get a fully qualified path to the system directory
204 public static string SystemDirectory
{
206 return GetFolderPath (SpecialFolder
.System
);
211 /// Get the number of milliseconds that have elapsed since the system was booted
213 public extern static int TickCount
{
214 [MethodImplAttribute (MethodImplOptions
.InternalCall
)]
219 /// Get UserDomainName
221 public static string UserDomainName
{
228 /// Gets a flag indicating whether the process is in interactive mode
231 public static bool UserInteractive
{
238 /// Get the user name of current process is running under
240 public extern static string UserName
242 [MethodImplAttribute (MethodImplOptions
.InternalCall
)]
247 /// Get the version of the common language runtime
249 public static Version Version
{
252 // FIXME: this is the version number for MS.NET 2.0 beta1.
253 // It must be changed when the final version is released.
254 return new Version (2, 0, 40607, 16);
256 return new Version (1, 1, 4322, 573);
258 return new Version (1, 0, 3705, 288);
264 /// Get the amount of physical memory mapped to process
267 public static long WorkingSet
274 [MethodImplAttribute (MethodImplOptions
.InternalCall
)]
275 public extern static void Exit (int exitCode
);
278 /// Substitute environment variables in the argument "name"
280 public static string ExpandEnvironmentVariables (string name
)
283 throw new ArgumentNullException ("name");
285 int off1
= name
.IndexOf ('%');
289 int len
= name
.Length
;
291 if (off1
== len
- 1 || (off2
= name
.IndexOf ('%', off1
+ 1)) == -1)
294 PlatformID platform
= Platform
;
295 StringBuilder result
= new StringBuilder ();
296 result
.Append (name
, 0, off1
);
297 Hashtable tbl
= null;
299 string var = name
.Substring (off1
+ 1, off2
- off1
- 1);
300 string value = GetEnvironmentVariable (var);
301 if (value == null && (int) platform
!= 128) {
302 // On windows, env. vars. are case insensitive
304 tbl
= GetEnvironmentVariablesNoCase ();
306 value = tbl
[var] as string;
309 // If value not found, add %FOO to stream,
310 // and use the closing % for the next iteration.
311 // If value found, expand it in place of %FOO%
317 result
.Append (value);
320 off1
= name
.IndexOf ('%', off2
+ 1);
321 // If no % found for off1, don't look for one for off2
322 off2
= (off1
== -1 || off2
> len
-1)? -1 :name
.IndexOf ('%', off1
+ 1);
323 // textLen is the length of text between the closing % of current iteration
324 // and the starting % of the next iteration if any. This text is added to output
326 // If no new % found, use all the remaining text
327 if (off1
== -1 || off2
== -1)
328 textLen
= len
- oldOff2
- 1;
329 // If value found in current iteration, use text after current closing % and next %
330 else if(value != null)
331 textLen
= off1
- oldOff2
- 1;
332 // If value not found in current iteration, but a % was found for next iteration,
333 // use text from current closing % to the next %.
335 textLen
= off1
- oldOff2
;
336 if(off1
>= oldOff2
|| off1
== -1)
337 result
.Append (name
.Substring (oldOff2
+1, textLen
));
338 } while (off2
> -1 && off2
< len
);
340 return result
.ToString ();
345 /// Return an array of the command line arguments of the current process
347 [MethodImplAttribute (MethodImplOptions
.InternalCall
)]
348 public extern static string[] GetCommandLineArgs();
351 /// Return a string containing the value of the environment
352 /// variable identifed by parameter "variable"
354 [MethodImplAttribute (MethodImplOptions
.InternalCall
)]
355 public extern static string GetEnvironmentVariable (string name
);
357 static Hashtable
GetEnvironmentVariablesNoCase ()
359 Hashtable vars
= new Hashtable (CaseInsensitiveHashCodeProvider
.Default
,
360 CaseInsensitiveComparer
.Default
);
362 foreach (string name
in GetEnvironmentVariableNames ()) {
363 vars
[name
] = GetEnvironmentVariable (name
);
370 /// Return a set of all environment variables and their values
373 public static IDictionary
GetEnvironmentVariables()
375 Hashtable vars
= new Hashtable ();
376 foreach (string name
in GetEnvironmentVariableNames ()) {
377 vars
[name
] = GetEnvironmentVariable (name
);
384 [MethodImplAttribute (MethodImplOptions
.InternalCall
)]
385 private extern static string GetWindowsFolderPath (int folder
);
388 /// Returns the fully qualified path of the
389 /// folder specified by the "folder" parameter
391 public static string GetFolderPath (SpecialFolder folder
)
393 if ((int) Platform
!= 128)
394 return GetWindowsFolderPath ((int) folder
);
396 string home
= internalGetHome ();
398 // http://freedesktop.org/Standards/basedir-spec/basedir-spec-0.6.html
399 string data
= GetEnvironmentVariable ("XDG_DATA_HOME");
400 if ((data
== null) || (data
== String
.Empty
)) {
401 data
= Path
.Combine (home
, ".local");
402 data
= Path
.Combine (data
, "share");
405 string config
= GetEnvironmentVariable ("XDG_CONFIG_HOME");
406 if ((config
== null) || (config
== String
.Empty
)) {
407 config
= Path
.Combine (home
, ".config");
412 // MyComputer is a virtual directory
413 case SpecialFolder
.MyComputer
:
417 case SpecialFolder
.Personal
:
419 // use FDO's CONFIG_HOME. This data will be synced across a network like the windows counterpart.
420 case SpecialFolder
.ApplicationData
:
422 //use FDO's DATA_HOME. This is *NOT* synced
423 case SpecialFolder
.LocalApplicationData
:
426 case SpecialFolder
.Desktop
:
428 case SpecialFolder
.DesktopDirectory
:
429 return Path
.Combine (home
, "Desktop");
431 // these simply dont exist on Linux
432 // The spec says if a folder doesnt exist, we
434 case SpecialFolder
.Favorites
:
435 case SpecialFolder
.Programs
:
436 case SpecialFolder
.SendTo
:
437 case SpecialFolder
.StartMenu
:
438 case SpecialFolder
.Startup
:
439 case SpecialFolder
.MyMusic
:
440 case SpecialFolder
.MyPictures
:
441 case SpecialFolder
.Templates
:
442 case SpecialFolder
.Cookies
:
443 case SpecialFolder
.History
:
444 case SpecialFolder
.InternetCache
:
445 case SpecialFolder
.Recent
:
446 case SpecialFolder
.CommonProgramFiles
:
447 case SpecialFolder
.ProgramFiles
:
448 case SpecialFolder
.System
:
450 // This is where data common to all users goes
451 case SpecialFolder
.CommonApplicationData
:
454 throw new ArgumentException ("Invalid SpecialFolder");
458 public static string[] GetLogicalDrives ()
460 return GetLogicalDrivesInternal ();
463 static internal string GetResourceString (string s
) { return ""; }
467 public static string GetEnvironmentVariable (string variable
, EnvironmentVariableTarget target
)
469 return (string)(GetEnvironmentVariables (target
) [variable
]);
473 public static IDictionary
GetEnvironmentVariables (EnvironmentVariableTarget target
)
475 throw new NotImplementedException ();
478 public static void SetEnvironmentVariable (string variable
, string value)
480 SetEnvironmentVariable (variable
, value, EnvironmentVariableTarget
.Process
);
484 public static void SetEnvironmentVariable (string variable
, string value, EnvironmentVariableTarget target
)
486 throw new NotImplementedException ();
490 static bool IsServerGC
{
492 throw new NotImplementedException ();
497 static int ProcessorCount
{
499 throw new NotImplementedException ();
506 private static string GacPath
{
508 if ((int) Platform
!= 128) {
509 /* On windows, we don't know the path where mscorlib.dll will be installed */
510 string corlibDir
= new DirectoryInfo (Path
.GetDirectoryName (typeof (int).Assembly
.Location
)).Parent
.Parent
.FullName
;
511 return Path
.Combine (Path
.Combine (corlibDir
, "mono"), "gac");
514 return Path
.Combine (Path
.Combine (internalGetGacPath (), "mono"), "gac");
518 [MethodImplAttribute (MethodImplOptions
.InternalCall
)]
519 private extern static string [] GetLogicalDrivesInternal ();
521 [MethodImplAttribute (MethodImplOptions
.InternalCall
)]
522 private extern static string [] GetEnvironmentVariableNames ();
524 [MethodImplAttribute (MethodImplOptions
.InternalCall
)]
525 internal extern static string GetMachineConfigPath ();
527 [MethodImplAttribute (MethodImplOptions
.InternalCall
)]
528 internal extern static string internalGetGacPath ();
530 [MethodImplAttribute (MethodImplOptions
.InternalCall
)]
531 internal extern static string internalGetHome ();