Search code examples
c#pathenvironment-variablespath-variablesraw-data

Get literal system variable path


Is there any way to get the path environmental variable as a literal string instead of expanded?

i.e.

%systemroot%\System32;%systemroot%\;etc...

instead of

C:\Windows\System32;C:\Windows\;etc...

I've tried using

Environment.GetSystemVariable("Path");

But that gives me the expanded directories and I don't see anything else under Environment that will get me that.

Edit:

PathUnExpandEnvStrings only works if the entire path is an environmental variable.

i.e.

C:\Windows\System32;C:\Windows;etc...

becomes

C:\Windows\System32;%systemroot%;etc...

using

Registry.GetValue(@"HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Control\Session Manager\Environment", "Path", null);

Still gets the values as C:\Windows\System32;C:\Windows;etc...


Solution

  • If you go the registry route you can pass RegistryValueOptions.DoNotExpandEnvironmentNames to the RegistryKey.GetValue() instance method to get the unexpanded path...

    using System;
    using Microsoft.Win32;
    
    namespace SO60725684
    {
        class Program
        {
            static void Main()
            {
                const string environmentKeyPath = @"SYSTEM\CurrentControlSet\Control\Session Manager\Environment";
                const string valueName = "TEMP";
    
                using (RegistryKey environmentKey = Registry.LocalMachine.OpenSubKey(environmentKeyPath))
                {
                    foreach (RegistryValueOptions options in Enum.GetValues(typeof(RegistryValueOptions)))
                    {
                        object valueData = environmentKey.GetValue(valueName, "<default>", options);
    
                        Console.WriteLine($"{valueName} ({options}) = \"{valueData}\"");
                    }
                }
            }
        }
    }
    

    This prints...

    Temp (None) = "C:\WINDOWS\TEMP"
    Temp (DoNotExpandEnvironmentNames) = "%SystemRoot%\TEMP"
    

    I'm using the "TEMP" variable just for the brevity of its value, but it works just as well for "Path".

    If you don't want to rely on the backing storage of an environment variable, there is also a Win32_Environment management class that exposes the value without expansion...

    using System;
    using System.Management;
    
    namespace SO60725684
    {
        class Program
        {
            static void Main()
            {
                string[] propertiesToDisplay = new string[] { "Name", "SystemVariable", "UserName", "VariableValue" };
                ObjectQuery query = new SelectQuery("Win32_Environment", "Name = 'TEMP'", propertiesToDisplay);
    
                using (ManagementObjectSearcher searcher = new ManagementObjectSearcher(query))
                using (ManagementObjectCollection resultCollection = searcher.Get())
                {
                    foreach (ManagementBaseObject resultInstance in resultCollection)
                    {
                        PropertyDataCollection properties = resultInstance.Properties;
    
                        foreach (string propertyName in propertiesToDisplay)
                        {
                            PropertyData property = properties[propertyName];
    
                            Console.WriteLine($"{property.Name}: {property.Value}");
                        }
                        Console.WriteLine();
                    }
                }
            }
        }
    }
    

    This prints...

    Name: TEMP
    SystemVariable: True
    UserName: <SYSTEM>
    VariableValue: %SystemRoot%\TEMP
    
    Name: TEMP
    SystemVariable: False
    UserName: NT AUTHORITY\SYSTEM
    VariableValue: %USERPROFILE%\AppData\Local\Temp
    
    Name: TEMP
    SystemVariable: False
    UserName: ComputerName\UserName
    VariableValue: %USERPROFILE%\AppData\Local\Temp
    

    As you can see, you get multiple results when the variable is defined for multiple users, so you'll need to do further filtering on the SystemVariable and UserName properties to get the one you want.