Sunday, February 26, 2012

The C# Code Series: Exploring System.Environment

It's time to code! This series will have code in C#. I shall code in VS2010.

I shall be trying to code something random each day and put it up! This is the first of its kind by me, so lets hope, it goes smooth!

Today, i shall look at the System.Environment class.

First and foremost, System.Environment is a static class. So we cant instantiate it.
It has a number of System properties that are available that could be useful such as MachineName, ProcessorCount, UserName, UserDomainName, Is64BitProcess, OSVersion, Is64BitOperatingSystem and more.

First, lets try and find what all properties it has. We can use Reflection to get this information.

So, i can something like

            //Print all the properties of the System.Enviroment class
            foreach (var property in typeof(System.Environment).GetProperties())
            {
                Console.WriteLine(property);
            }

This is fine, but the printed property list also shows the data type of the property. This is because the GetProperties() method return an array of PropertyInfo objects. So, lets try and just get the names of the properties. Each PropertyInfo has a Name property, so we can use this property.

            //This prints all the properties but doesnt show their data types.
            //We are getting the name property from the PropertyInfo class
            foreach (var property in typeof(System.Environment).GetProperties(BindingFlags.Public))
            {
                Console.WriteLine(property.Name);
            }

I am passing a "BindingFlags.Public" to the GetProperties() method. We can think of this as a filter.

This says, i would like to have a list of public properties please.

We can also add more filters to this method, like

             typeof(System.Environment).GetProperties(BindingFlags.Public|BindingFlags.Static)

So, here we are saying please give me Properties that are public or that are static.

By default, the GetProperties() method gives us public properties.

So, now let's try and get the values for these properties. We can say

            //Print the public properties and also their values

            foreach (var propertyInfo in typeof(System.Environment).GetProperties())
            {
                var value = propertyInfo.GetValue(null, null);
                Console.WriteLine("{0}:{1}",propertyInfo.Name, value);
            }

So far so good. There's a SpecialFolder Enumeration available to us in the Environment class.

We can say right-click and say "Go to Declaration" to see the source code for the .NET implementation of the Environment class. If i did so, we can see the following enum names declared.

        [ComVisible(true)]
        public enum SpecialFolder
        {
            Desktop = 0,
            Programs = 2,
            MyDocuments = 5,
            Personal = 5,
            Favorites = 6,
            Startup = 7,
            Recent = 8,
            SendTo = 9,
            StartMenu = 11,
            MyMusic = 13,
            MyVideos = 14,
            DesktopDirectory = 16,
            MyComputer = 17,
            NetworkShortcuts = 19,
            Fonts = 20,
            Templates = 21,
            CommonStartMenu = 22,
            CommonPrograms = 23,
            CommonStartup = 24,
            CommonDesktopDirectory = 25,
            ApplicationData = 26,
            PrinterShortcuts = 27,
            LocalApplicationData = 28,
            InternetCache = 32,
            Cookies = 33,
            History = 34,
            CommonApplicationData = 35,
            Windows = 36,
            System = 37,
            ProgramFiles = 38,
            MyPictures = 39,
            UserProfile = 40,
            SystemX86 = 41,
            ProgramFilesX86 = 42,
            CommonProgramFiles = 43,
            CommonProgramFilesX86 = 44,
            CommonTemplates = 45,
            CommonDocuments = 46,
            CommonAdminTools = 47,
            AdminTools = 48,
            CommonMusic = 53,
            CommonPictures = 54,
            CommonVideos = 55,
            Resources = 56,
            LocalizedResources = 57,
            CommonOemLinks = 58,
            CDBurning = 59,
        }

That's cool. So can we get the same name from the code. Lets give it a try!

            //Print All the Special Folders
            foreach (var specialFolder in typeof(Environment.SpecialFolder).GetEnumNames())
            {
                Console.WriteLine(specialFolder);
            }

That should do it! Prints all the enum names available for us.

Why am i interested in this SpecialFolder guy? Well, good question. First of all, there are a couple of methods that we can use. These are
  • GetLogicalDrives()
  • GetFolderPath()
Lets try and use both these methods. First we shall look at all the available drives on the machine.
This is simple. We could say,

            //Get a list of Available drives on this machine
            foreach (var drive in Environment.GetLogicalDrives())
            {
                Console.WriteLine(drive);
            }

That's fun. Now let's get to the other method. This is a little tricky. How can we get the Folder paths for each of the special folder.

Well, we may think of a dictionary and add stuff to it. Something like,

 //One way of doing things.
                //We can create a Dictionary.
                //We can add SpecialFolder name as the Key and the FolderPath as the value.
                 var environment = new Dictionary<string, string>
                                      {
                                          {"CurrentDirectory", Environment.CurrentDirectory},
                                          {
                                              "WindowsSystemFolder",
                                              Environment.GetFolderPath(Environment.SpecialFolder.Windows)
                                           },
                                          {"AdminTools", Environment.GetFolderPath(Environment.SpecialFolder.AdminTools)}
                                     
                                      };
                foreach (var key in environment.Keys)
                {
                    Console.WriteLine("{0}: {1}", key, environment[key]);
                }

Well, this becomes bloated soon. So, why not use reflection and solve this problem?

To do this we need a way to get hold of the SpecialFolder object itself. Since GetFolderPath() method takes a SpecialFolderPath type.

In the above code sample, where we tried to get the names of the SpecialFolders, we used a method called GetEnumNames(). GetEnumNames() returns an array of strings.  If we wanted the enums themselves like Environment.SpecialFolder.Windows, we will have to use another method called GetEnumValues().

To demonstrate:

            //Get the Enums. To do this, we need to access Enums directly. Two ways

            //Way one
            var specialFolders = Enum.GetValues(typeof(Environment.SpecialFolder));

            //Way two
            foreach (var specialFolderName in typeof(Environment.SpecialFolder).GetEnumValues())
            {
                environment.Add(specialFolderName.ToString(),
                                Environment.GetFolderPath((Environment.SpecialFolder) specialFolderName));
               
                Console.WriteLine("{0} : {1}",specialFolderName.ToString(), Environment.GetFolderPath((Environment.SpecialFolder)specialFolderName));
            }


That's it! There. We have nailed down System.Environment down using reflection and learnt what properties it has, and how we can get their values. The GetFolderPath() uses another signature such as :
Environment.GetFolderPath(System.Environment.SpecialFolder folder,System.Environment.SpecialFolderOption option)

We shall take a look at this maybe later! Goodbye for now.






No comments:

Post a Comment