//------------------------------------------------------------------------------ // // System.Environment.cs // // Copyright (C) 2001 Moonlight Enterprises, All Rights Reserved // // Author: Jim Richardson, develop@wtfo-guru.com // Dan Lewis (dihlewis@yahoo.co.uk) // Created: Saturday, August 11, 2001 // //------------------------------------------------------------------------------ using System; using System.IO; //using System.Diagnostics; using System.Collections; using System.Security; using System.Security.Permissions; using System.Runtime.CompilerServices; using System.Text; namespace System { public sealed class Environment { /* * This is the version number of the corlib-runtime interface. When * making changes to this interface (by changing the layout * of classes the runtime knows about, changing icall semantics etc), * increment this variable. Also increment the * pair of this variable in the runtime in metadata/appdomain.c. */ private const int mono_corlib_version = 16; private Environment () { } [MonoTODO] public enum SpecialFolder { // TODO: Determine if these windoze style folder identifiers // have unix/linux counterparts #if NET_1_1 Desktop = 0x00, MyComputer = 0x11, #endif Programs = 0x02, Personal = 0x05, Favorites = 0x06, Startup = 0x07, Recent = 0x08, SendTo = 0x09, StartMenu = 0x0b, MyMusic = 0x0d, DesktopDirectory = 0x10, Templates = 0x15, ApplicationData = 0x1a, LocalApplicationData = 0x1c, InternetCache = 0x20, Cookies = 0x21, History = 0x22, CommonApplicationData = 0x23, System = 0x25, ProgramFiles = 0x26, MyPictures = 0x27, CommonProgramFiles = 0x2b, } // TODO: Make sure the security attributes do what I expect /// /// Gets the command line for this process /// public static string CommandLine { // TODO: Coordinate with implementor of EnvironmentPermissionAttribute // [EnvironmentPermissionAttribute(SecurityAction.Demand, Read = "COMMANDLINE")] get { // FIXME: we may need to quote, but any sane person // should use GetCommandLineArgs () instead. return String.Join (" ", GetCommandLineArgs ()); } } /// /// Gets or sets the current directory. Actually this is supposed to get /// and/or set the process start directory acording to the documentation /// but actually test revealed at beta2 it is just Getting/Setting the CurrentDirectory /// public static string CurrentDirectory { // originally it was my thought that the external call would be made in // the directory class however that class has additional security requirements // so the Directory class will call this class for its get/set current directory [EnvironmentPermissionAttribute(SecurityAction.Demand, Unrestricted = true)] get { return Directory.GetCurrentDirectory (); } [SecurityPermissionAttribute(SecurityAction.Demand, Flags = SecurityPermissionFlag.UnmanagedCode)] set { Directory.SetCurrentDirectory (value); } } /// /// Gets or sets the exit code of this process /// public extern static int ExitCode { [MethodImplAttribute (MethodImplOptions.InternalCall)] get; [MethodImplAttribute (MethodImplOptions.InternalCall)] set; } #if NET_1_1 static #endif public extern bool HasShutdownStarted { [MethodImplAttribute (MethodImplOptions.InternalCall)] get; } /// /// Gets the name of the local computer /// public extern static string MachineName { [MethodImplAttribute (MethodImplOptions.InternalCall)] get; } /// /// Gets the standard new line value /// public extern static string NewLine { [MethodImplAttribute (MethodImplOptions.InternalCall)] get; } // // Support methods and fields for OSVersion property // static OperatingSystem os; internal static extern PlatformID Platform { [MethodImplAttribute (MethodImplOptions.InternalCall)] get; } /// /// Gets the current OS version information /// [MonoTODO("Correct version")] public static OperatingSystem OSVersion { get { if (os == null) os = new OperatingSystem (Platform, new Version (5,1,2600,0)); return os; } } /// /// Get StackTrace /// public static string StackTrace { get { System.Diagnostics.StackTrace trace = new System.Diagnostics.StackTrace (1); return trace.ToString (); } } /// /// Get a fully qualified path to the system directory /// public static string SystemDirectory { get { return GetFolderPath (SpecialFolder.System); } } /// /// Get the number of milliseconds that have elapsed since the system was booted /// public extern static int TickCount { [MethodImplAttribute (MethodImplOptions.InternalCall)] get; } /// /// Get UserDomainName /// public static string UserDomainName { get { return MachineName; } } /// /// Gets a flag indicating whether the process is in interactive mode /// [MonoTODO] public static bool UserInteractive { get { return false; } } /// /// Get the user name of current process is running under /// public extern static string UserName { [MethodImplAttribute (MethodImplOptions.InternalCall)] get; } /// /// Get the version of the common language runtime /// public static Version Version { get { #if NET_1_1 return new Version (1, 1, 4322, 573); #else return new Version (1, 0, 3705, 288); #endif } } /// /// Get the amount of physical memory mapped to process /// [MonoTODO] public static long WorkingSet { get { return 0; } } [MethodImplAttribute (MethodImplOptions.InternalCall)] public extern static void Exit (int exitCode); /// /// Substitute environment variables in the argument "name" /// public static string ExpandEnvironmentVariables (string name) { if (name == null) throw new ArgumentNullException ("name"); int off1 = name.IndexOf ('%'); if (off1 == -1) return name; int len = name.Length; int off2 = 0; if (off1 == len - 1 || (off2 = name.IndexOf ('%', off1 + 1)) == -1) return name; PlatformID platform = Platform; StringBuilder result = new StringBuilder (); result.Append (name, 0, off1); do { Hashtable tbl = null; string var = name.Substring (off1 + 1, off2 - off1 - 1); string value = GetEnvironmentVariable (var); if (value == null && (int) platform != 128) { // On windows, env. vars. are case insensitive if (tbl == null) tbl = GetEnvironmentVariablesNoCase (); value = tbl [var] as string; } if (value == null) { result.Append ('%'); result.Append (var); result.Append ('%'); } else { result.Append (value); } if (off2 + 1 == len) { off1 = off2; off2 = -1; } else { off1 = off2 + 1; off2 = (off1 + 1 == len) ? -1 : name.IndexOf ('%', off1 + 1); } } while (off2 != -1); if (off1 + 1 < len) result.Append (name.Substring (off1)); return result.ToString (); } /// /// Return an array of the command line arguments of the current process /// [MethodImplAttribute (MethodImplOptions.InternalCall)] public extern static string[] GetCommandLineArgs(); /// /// Return a string containing the value of the environment /// variable identifed by parameter "variable" /// [MethodImplAttribute (MethodImplOptions.InternalCall)] public extern static string GetEnvironmentVariable (string name); static Hashtable GetEnvironmentVariablesNoCase () { Hashtable vars = new Hashtable (CaseInsensitiveHashCodeProvider.Default, CaseInsensitiveComparer.Default); foreach (string name in GetEnvironmentVariableNames ()) { vars [name] = GetEnvironmentVariable (name); } return vars; } /// /// Return a set of all environment variables and their values /// public static IDictionary GetEnvironmentVariables() { Hashtable vars = new Hashtable (); foreach (string name in GetEnvironmentVariableNames ()) { vars [name] = GetEnvironmentVariable (name); } return vars; } [MethodImplAttribute (MethodImplOptions.InternalCall)] private extern static string GetWindowsFolderPath (int folder); /// /// Returns the fully qualified path of the /// folder specified by the "folder" parameter /// public static string GetFolderPath (SpecialFolder folder) { if ((int) Platform != 128) return GetWindowsFolderPath ((int) folder); // we can do this in managed code for non-Windows environments string path = String.Empty; // http://freedesktop.org/Standards/basedir-spec/basedir-spec-0.6.html string data = GetEnvironmentVariable ("XDG_DATA_HOME"); if ((data == null) || (data == String.Empty)) { data = Path.Combine (GetEnvironmentVariable ("HOME"), ".local"); data = Path.Combine (data, "share"); } string config = GetEnvironmentVariable ("XDG_CONFIG_HOME"); if ((config == null) || (config == String.Empty)) { config = Path.Combine (GetEnvironmentVariable ("HOME"), ".config"); } string cache = GetEnvironmentVariable ("XDG_CACHE_HOME"); if ((cache == null) || (cache == String.Empty)) { cache = Path.Combine (GetEnvironmentVariable ("HOME"), ".cache"); } switch (folder) { #if NET_1_1 case SpecialFolder.MyComputer: // MyComputer is a virtual directory path = ""; break; #endif // data related case SpecialFolder.ApplicationData: case SpecialFolder.LocalApplicationData: case SpecialFolder.MyMusic: case SpecialFolder.MyPictures: case SpecialFolder.Personal: case SpecialFolder.Templates: path = data; break; // configuration related #if NET_1_1 case SpecialFolder.Desktop: #endif case SpecialFolder.DesktopDirectory: case SpecialFolder.Favorites: case SpecialFolder.Programs: case SpecialFolder.SendTo: case SpecialFolder.StartMenu: case SpecialFolder.Startup: path = config; break; // cache related (could disappear) case SpecialFolder.Cookies: case SpecialFolder.History: case SpecialFolder.InternetCache: case SpecialFolder.Recent: path = cache; break; // programs case SpecialFolder.CommonProgramFiles: case SpecialFolder.ProgramFiles: case SpecialFolder.System: break; // Directories shared by all users case SpecialFolder.CommonApplicationData: path = Path.GetDirectoryName (GetMachineConfigPath ()); break; default: throw new ArgumentException ("Invalid SpecialFolder"); } return path; } /// /// Returns an array of the logical drives /// [MonoTODO] public static string[] GetLogicalDrives () { return(new string[] { "/" }); } static internal string GetResourceString (string s) { return ""; } // private methods private static string GacPath { get { return Path.Combine (Path.Combine (internalGetGacPath (), "mono"), "gac"); } } [MethodImplAttribute (MethodImplOptions.InternalCall)] private extern static string [] GetEnvironmentVariableNames (); [MethodImplAttribute (MethodImplOptions.InternalCall)] internal extern static string GetMachineConfigPath (); [MethodImplAttribute (MethodImplOptions.InternalCall)] internal extern static string internalGetGacPath (); } }