none
Environment Variables Refresh

    Question

  • I have a C# program which runs a batch file that edits the environment variables (using setx, so the new environment variable stays around after the shell is gone).  I need to have C# check that environment variable after the batch file returns, but when I do that (using Environment.GetEnvironmentVariable) it doesn't seem to be registering variables that have changed since the program started running.  Is there a way to refresh the Environment class so that it is up to date?
    Thursday, June 07, 2007 5:52 PM

Answers

  • The environment variables are cached when a process starts.  Unless the process itself changes them they will not be visible until the process restarts.  In your case the batch file (running in a separate process) will update the env vars but the main process won't be able to see the changes.  There isn't a workaround short of making the same changes in the main process.  However if all you want to do is confirm that the env vars were changed then you can run another process that confirms the env vars were changed properly.  All new processes would get the new env vars.

     

    Michael Taylor - 6/8/07

    http://p3net.mvps.org

    Friday, June 08, 2007 1:02 PM
    Moderator
  • When an application is started it "inherits" the environment of the calling process.  The environment variables aren't cached, they're copied.  GetEnvironmentVariable makes repeated requests to the system for that environment variable for the process; but it's for that process, not the parent.   There's no way to see changes to process environment variables of the parent process unless it has explicitly given you access to them, something which the command prompt does/can not do.

     

    You could write a small console app that you could use for setting user-wide environment variables using Environment.SetEnvironmentVariable(string variable, string value, EnvironmentVariableTarget target) (where EnvironmentVariableTarget is User) and then get those environment variables with GetEnvironmentVariable(String, EnvironmentVariableTarget target).  I don't recommend that; if you have to go to the trouble of writing another app to set env. variables, it's probably better to use accepted inter-process communications methods available in .NET.

    Friday, June 08, 2007 3:51 PM
    Moderator

All replies

  • The environment variables are cached when a process starts.  Unless the process itself changes them they will not be visible until the process restarts.  In your case the batch file (running in a separate process) will update the env vars but the main process won't be able to see the changes.  There isn't a workaround short of making the same changes in the main process.  However if all you want to do is confirm that the env vars were changed then you can run another process that confirms the env vars were changed properly.  All new processes would get the new env vars.

     

    Michael Taylor - 6/8/07

    http://p3net.mvps.org

    Friday, June 08, 2007 1:02 PM
    Moderator
  • When an application is started it "inherits" the environment of the calling process.  The environment variables aren't cached, they're copied.  GetEnvironmentVariable makes repeated requests to the system for that environment variable for the process; but it's for that process, not the parent.   There's no way to see changes to process environment variables of the parent process unless it has explicitly given you access to them, something which the command prompt does/can not do.

     

    You could write a small console app that you could use for setting user-wide environment variables using Environment.SetEnvironmentVariable(string variable, string value, EnvironmentVariableTarget target) (where EnvironmentVariableTarget is User) and then get those environment variables with GetEnvironmentVariable(String, EnvironmentVariableTarget target).  I don't recommend that; if you have to go to the trouble of writing another app to set env. variables, it's probably better to use accepted inter-process communications methods available in .NET.

    Friday, June 08, 2007 3:51 PM
    Moderator
  • I was able to get an updated value by spinning up a new thread to get load up the value I just set. This is a quick hack, but here's how I did it.

     

    /// Some code here to read out a value, then  change it /// Then create object EnvironementReader, run GetVariableValue('put the name of the variable you want to read'), view the EnvironmentValue property, it now has the latest value.

      public class EnvironmentReader 
      {
        public string EnvironmentValue { get; set;}
        private string Variable{get; set;}
    
        /// <summary>
        /// Variable is the name of the machine level environment variable you'd like to read out of current process.
        /// </summary>
        /// <param name="Variable"></param>
        public void LoadEnvironmentVariable(string Variable) 
        {
          this.Variable= Variable;
          Thread t = new Thread(new ThreadStart(GetVariableValue));
          t.Start();
        }
        private void GetVariableValue() 
        {
          this.EnvironmentValue = Environment.GetEnvironmentVariable(this.Variable, EnvironmentVariableTarget.Machine);
        }
      }
    Tuesday, August 24, 2010 5:21 AM
  • As a workaround, you could read the registry directly

    Registry.GetValue(@"HKEY_CURRENT_USER\Environment", "LastUsedSomething", "DefaultSomething")

    Thursday, November 20, 2014 6:07 PM
  • Good idea. Now, does anyone know of why reading the registry value directly would be a problem?
    Tuesday, May 26, 2015 2:38 PM