Page 1 of 1

Working with environment variables in C#

#1 PsychoCoder  Icon User is offline

  • Google.Sucks.Init(true);
  • member icon

Reputation: 1639
  • View blog
  • Posts: 19,853
  • Joined: 26-July 07

Posted 22 June 2010 - 02:51 PM

Recently I have seen quite a few posts looking for to read & set Environment variables in C#, so I thought it was time for a tutorial covering the ins and outs of this process. While the .Net Framework has classes & methods for reading and updating environment variables, namely the Environment Class. So today we're going to create a class file to do exactly this, something that you can include in any application that involves being able to do this.

In earlier versions of .Net (2.0 and earlier) there wasn't a native support for changing the value of an environment variable for the currently running process, so you would have to use the Win32 API SetEnvironmentVariable Function

// Import the kernel32 dll.
[DllImport("kernel32.dll", CharSet = CharSet.Auto, SetLastError = true)]
[return: MarshalAs(UnmanagedType.Bool)]
// The declaration is similar to the SDK function
public static extern bool SetEnvironmentVariable(string lpName, string lpValue);



Then create a method for utilizing this Win32 API, something like this example

/// <summary>
/// method for setting the variable of an environment variable associated with
/// the current running process
/// </summary>
/// <param name="variable">variable to set</param>
/// <param name="value">value to set the variable to</param>
/// <returns></returns>
public static bool SetVariable(string variable, string value)
{
    try
    {
        // Get the write permission to set the environment variable.
        EnvironmentPermission permissions = new EnvironmentPermission(EnvironmentPermissionAccess.Write, variable);

        permissions.Demand();

        return SetEnvironmentVariable(variable, value);
    }
    catch (SecurityException ex)
    {
        MessageBox.Show(string.Format("Error while setting variable {0} : {1}", variable, ex.Message));
    }
    return false;
}



Now it's much easier with the Environment Class of the .Net Framework, no more P/Invoke, not more need for Interop, now we can use the native libraries for access to the environment variables in the Windows OS. So let's take a look at some of the functionality the Environment Class offers us. First we will get a list of all the environment variables that are currently on the system, for this we will be using the GetEnvironmentVariables Method (we'll take a look at it's overload soon).

For this we will be populating a Dictionary<TKey, TValue> to hold the key/value pairs returned from the environment variables query. You could use any key/value capable collection for this, I chose the Dictionary class for mine.

For this example I also chose to use the System.Threading.Tasks Namespace so I could run some parallel loops with the Parallel Class.

Our first example will be for retrieving all environment variables on the system the code is running. We will be looking at three different examples here:

  • Getting all environment variables
  • Getting environment variables by target (User, Machine & Process)
  • Get an environment variable by name


This is how we would get all the variables in one fail swoop

/// <summary>
/// method for getting all available environment variables
/// </summary>
/// <returns></returns>
public Dictionary<string, string> GetEnvironmentVariables()
{
    try
    {
        //dictionary object to hold the key/value pairs
        Dictionary<string, string> variables = new Dictionary<string, string>();

        //loop through the list and add to our dictionary list
        Parallel.ForEach<DictionaryEntry>(Environment.GetEnvironmentVariables().OfType<DictionaryEntry>(), entry =>
            {
                variables.Add(entry.Key.ToString(), entry.Value.ToString());
            });

        return variables;
    }
    catch (SecurityException ex)
    {
        Console.WriteLine("Error retrieving environment variables: {0}", ex.Message);
        return null;
    }
}



In our example console application we would call this like so for displaying the values out

static void Main(string[] args)
{
    EVEditor editor = new EVEditor();

    foreach (KeyValuePair<string, string> entry in editor.GetEnvironmentVariables())
    {
        Console.WriteLine(entry.Key + " - " + entry.Value);
    }

    Console.ReadLine();
}



Which will give the following results:

Attached Image

Pretty straight forward really. In our next example we will be providing a variable to a method, of type EnvironmentVariableTarget, which will be passed to the overloaded version of the GetEnvironmentVariable Method. This code looks the same as our previous example, except this time we have to provide the target we want to search through:

/// <summary>
/// method for getting all environment variables by target:
/// EnvironmentVariableTarget.User
/// EnvironmentVariableTarget.Machine
/// EnvironmentVariableTarget.Process
/// </summary>
/// <param name="target">the EnvironmentVariableTarget we want the variables for</param>
/// <returns></returns>
public Dictionary<string, string> GetEnvironmentVariablesByTarget(EnvironmentVariableTarget target)
{
    try
    {
        Dictionary<string, string> variables = new Dictionary<string, string>();

        Parallel.ForEach<DictionaryEntry>(Environment.GetEnvironmentVariables(target).OfType<DictionaryEntry>(), entry =>
            {
                variables.Add(entry.Key.ToString(), entry.Value.ToString());
            });

        return variables;
    }
    catch (SecurityException ex)
    {
        Console.WriteLine("Error retrieving environment variables: {0}", ex.Message);
        return null;
    }
}



For calling this we will need to provide either:

  • EnvironmentVariableTarget.User
  • EnvironmentVariableTarget.Machine
  • EnvironmentVariableTarget.Process


For the purposes of our example we will get the environment variables for the current user (EnvironmentVariableTarget.User). So our call would look like this

static void Main(string[] args)
{
    EVEditor editor = new EVEditor();

    foreach (KeyValuePair<string, string> entry in editor.GetEnvironmentVariablesByTarget(EnvironmentVariableTarget.User))
    {
        Console.WriteLine(entry.Key + " - " + entry.Value);
    }

    Console.ReadLine();
}



And would give the following results:

Attached Image

Now let's move on to retrieving an environment variable by it's name. For this instead of GetEnvironmentVariables we'll be using GetEnvironmentVariable. This too has an overload, but we wont be using that in this example (It's pretty simple to implement if you wish to once this is over). This method is much simpler than the rest, but we did add some checking to it making it longer. So here is how you would look for just a single environment variable by name:

/// <summary>
/// method for retrieving an environment variable by it's name
/// </summary>
/// <param name="name">the name of the environment variable we're looking for</param>
/// <returns></returns>
public string GetEnvironmentVariableByName(string name)
{
    try
    {
        //get the variable
        string variable = Environment.GetEnvironmentVariable(name);

        //check for a value, if nothing is returned let the application know
        if (!string.IsNullOrEmpty(variable))
            return variable;
        else
            return "The requested environment variable could not be found";
    }
    catch(SecurityException ex)
    {
        Console.WriteLine(string.Format("Error searching for environment variable: {0}", ex.Message));
        return string.Empty;
    }            
}



And calling it would look like this in our test application:

static void Main(string[] args)
{
    EVEditor editor = new EVEditor(EVEditor.Target.Machine);
    Console.WriteLine(editor.GetEnvironmentVariableByName("windir"));
    Console.ReadLine();
}



Which gives us this

Attached Image

So now one last thing, let's taqke a look at setting/updating the value of an environment variable. For this Microsoft gives us the SetEnvironmentVariable Method. This method has an overload, one is



These methods are used to create/modify or delete an environment variable in the current process or in the registery for either the current user or the local machine. So we will look at it for creating, modifying or deleting an environment variable, which can all be done in the same method, we'll call it SetEnvironmentVariableValue, which will take 3 parameters:

  • string variable: The variable we're looking for
  • string value: The value we wish to set it to
  • EnvironmentVariableTarget target: the target for the variable - User, Process or Local Machine


This is how our method looks. In this example we're using optional parameters available to us in C# 4.0. The method first checks to see if the variable exists, if not then an exception is thrown, if it's found then it sets the value. If null is passed as the value then the environment value will be deleted (this is by design). This could be modified to not check if the variable exists, just create it if it isn't found, but for this we're doing some error checking. Here's [b]SetEnvironmentVariable[b]:

/// <summary>
/// method for handling environment variable values. Will:
/// Update
/// Create
/// Delete
/// </summary>
/// <param name="variable">the variable we're looking for</param>
/// <param name="value">the value to set it to (null for deleting a variable)</param>
/// <param name="target">the targer, defaults to User</param>
/// <returns></returns>
public void SetEnvironmentVariableValue(string variable, string value = null, EnvironmentVariableTarget target = EnvironmentVariableTarget.User)
{
    try
    {
        //first make sure a name is provided
        if (string.IsNullOrEmpty(variable))
            throw new ArgumentException("Variable names cannot be empty or null", "variable");

        if (!DoesEnvironmentVariableExist(variable, target))
            throw new Exception(string.Format("The environment variable {0} was not found", variable));
        else
            Environment.SetEnvironmentVariable(variable, value, target);

        Console.WriteLine(string.Format("The environment variable {0} has been deleted", variable));

    }
    catch (SecurityException ex)
    {
        Console.WriteLine(string.Format("Error setting environment variable {0}: {1}", variable, ex.Message));
    }
    catch (ArgumentException ex)
    {
        Console.WriteLine(string.Format("Error setting environment variable {0}: {1}", variable, ex.Message));
    }
}



There's a call to the method DoesEnvironmentVariableExist, and I almost for the method so here it is. It simply checks to make sure the environment variable exists before it's value is set:

private bool DoesEnvironmentVariableExist(string variable, EnvironmentVariableTarget target = EnvironmentVariableTarget.User)
{
    try
    {
        return string.IsNullOrEmpty(Environment.GetEnvironmentVariable(variable, target)) ? false : true;
    }
    catch (SecurityException)
    {
        return false;
    }
}



So as you can see working with environment variables in C# has greatly improved since .Net first came out, and Microsoft seems willing to keep improving what is offered to use as developers. In closing here's the entire class we created in this entry for working with environment variables:

using System;
using System.Collections;
using System.Collections.Generic;
using System.Linq;
using System.Runtime.InteropServices;
using System.Security;
using System.Security.Permissions;
using System.Threading.Tasks;

namespace EnviromentVariableEditor.Core
{
    class EVEditor
    {
        private string _message;
        private bool _successful;

        public string Message
        {
            get { return _message; }
            private set { _message = value; }
        }

        public bool IsSuccessful
        {
            get { return _successful; }
            private set { _successful = value; }
        }

        #region System.Environment Namespace Version

        /// <summary>
        /// method for getting all available environment variables
        /// </summary>
        /// <returns></returns>
        public Dictionary<string, string> GetEnvironmentVariables()
        {
            try
            {
                //dictionary object to hold the key/value pairs
                Dictionary<string, string> variables = new Dictionary<string, string>();

                //loop through the list and add to our dictionary list
                Parallel.ForEach<DictionaryEntry>(Environment.GetEnvironmentVariables().OfType<DictionaryEntry>(), entry =>
                    {
                        variables.Add(entry.Key.ToString(), entry.Value.ToString());
                    });

                return variables;
            }
            catch (SecurityException ex)
            {
                Console.WriteLine("Error retrieving environment variables: {0}", ex.Message);
                return null;
            }
        }

        /// <summary>
        /// method for getting all environment variables by target:
        /// EnvironmentVariableTarget.User
        /// EnvironmentVariableTarget.Machine
        /// EnvironmentVariableTarget.Process
        /// </summary>
        /// <param name="target">the EnvironmentVariableTarget we want the variables for</param>
        /// <returns></returns>
        public Dictionary<string, string> GetEnvironmentVariablesByTarget(EnvironmentVariableTarget target)
        {
            try
            {
                Dictionary<string, string> variables = new Dictionary<string, string>();

                Parallel.ForEach<DictionaryEntry>(Environment.GetEnvironmentVariables(target).OfType<DictionaryEntry>(), entry =>
                    {
                        variables.Add(entry.Key.ToString(), entry.Value.ToString());
                    });

                return variables;
            }
            catch (SecurityException ex)
            {
                Console.WriteLine("Error retrieving environment variables: {0}", ex.Message);
                return null;
            }
        }

        /// <summary>
        /// method for retrieving an environment variable by it's name
        /// </summary>
        /// <param name="name">the name of the environment variable we're looking for</param>
        /// <returns></returns>
        public string GetEnvironmentVariableByName(string name)
        {
            try
            {
                //get the variable
                string variable = Environment.GetEnvironmentVariable(name);

                //check for a value, if nothing is returned let the application know
                if (!string.IsNullOrEmpty(variable))
                    return variable;
                else
                    return "The requested environment variable could not be found";
            }
            catch (SecurityException ex)
            {
                Console.WriteLine(string.Format("Error searching for environment variable: {0}", ex.Message));
                return string.Empty;
            }
        }

        /// <summary>
        /// method for handling environment variable values. Will:
        /// Update
        /// Create
        /// Delete
        /// </summary>
        /// <param name="variable">the variable we're looking for</param>
        /// <param name="value">the value to set it to (null for deleting a variable)</param>
        /// <param name="target">the targer, defaults to User</param>
        /// <returns></returns>
        public void SetEnvironmentVariableValue(string variable, string value = null, EnvironmentVariableTarget target = EnvironmentVariableTarget.User)
        {
            try
            {
                //first make sure a name is provided
                if (string.IsNullOrEmpty(variable))
                    throw new ArgumentException("Variable names cannot be empty or null", "variable");

                if (!DoesEnvironmentVariableExist(variable, target))
                    throw new Exception(string.Format("The environment variable {0} was not found", variable));
                else
                    Environment.SetEnvironmentVariable(variable, value, target);

                Console.WriteLine(string.Format("The environment variable {0} has been deleted", variable));

            }
            catch (SecurityException ex)
            {
                Console.WriteLine(string.Format("Error setting environment variable {0}: {1}", variable, ex.Message));
            }
            catch (ArgumentException ex)
            {
                Console.WriteLine(string.Format("Error setting environment variable {0}: {1}", variable, ex.Message));
            }
        }

        private bool DoesEnvironmentVariableExist(string variable, EnvironmentVariableTarget target = EnvironmentVariableTarget.User)
        {
            try
            {
                return string.IsNullOrEmpty(Environment.GetEnvironmentVariable(variable, target)) ? false : true;
            }
            catch (SecurityException)
            {
                return false;
            }
        }
        #endregion
    }
}




Thanks for reading and I hope you found it useful and informative.

Is This A Good Question/Topic? 1
  • +

Replies To: Working with environment variables in C#

#2 mroc  Icon User is offline

  • New D.I.C Head

Reputation: 0
  • View blog
  • Posts: 1
  • Joined: 27-June 14

Posted 27 June 2014 - 03:15 AM

Dictionary<K,V>.Add is not thread safe. If the call Parallel.ForEach would really be executed in parallel (which is not guaranteed) it would break your dictionary. See the section Thread Safety in http://msdn.microsof...(v=vs.110).aspx or http://en.wikipedia....i/Thread_safety for a common introduction to the topic.

        Dictionary<string, string> variables = new Dictionary<string, string>();  

11    

12         //loop through the list and add to our dictionary list  

13         Parallel.ForEach<DictionaryEntry>(Environment.GetEnvironmentVariables().OfType<DictionaryEntry>(), entry =>  

14             {  

15                 variables.Add(entry.Key.ToString(), entry.Value.ToString());  

16             });  



Was This Post Helpful? 0
  • +
  • -

Page 1 of 1