mirror of
https://github.com/microsoft/PowerToys
synced 2025-08-30 22:15:11 +00:00
[EnvVar]Fix how expanded variables are processed (#29418)
* Read variables from registry (without expanding), not by using Environment API Fix seting variables to registry * Expand in Applied variables list * Remove using * Add comments
This commit is contained in:
@@ -65,6 +65,9 @@ namespace EnvironmentVariables.Helpers
|
||||
return baseKey.OpenSubKey(keyName, writable: writable);
|
||||
}
|
||||
|
||||
// Code taken from https://github.com/dotnet/runtime/blob/main/src/libraries/System.Private.CoreLib/src/System/Environment.Win32.cs
|
||||
// Set variables directly to registry instead of using Environment API - Environment.SetEnvironmentVariable() has 1 second timeout for SendNotifyMessage(WM_SETTINGSCHANGED).
|
||||
// When applying profile, this would take num_of_variables * 1s to propagate the changes. We do manually SendNotifyMessage with no timeout where needed.
|
||||
private static void SetEnvironmentVariableFromRegistryWithoutNotify(string variable, string value, bool fromMachine)
|
||||
{
|
||||
const int MaxUserEnvVariableLength = 255; // User-wide env vars stored in the registry have names limited to 255 chars
|
||||
@@ -84,7 +87,15 @@ namespace EnvironmentVariables.Helpers
|
||||
}
|
||||
else
|
||||
{
|
||||
environmentKey.SetValue(variable, value);
|
||||
// If a variable contains %, we save it as a REG_EXPAND_SZ, which is the same behavior as the Windows default environment variables editor.
|
||||
if (value.Contains('%'))
|
||||
{
|
||||
environmentKey.SetValue(variable, value, RegistryValueKind.ExpandString);
|
||||
}
|
||||
else
|
||||
{
|
||||
environmentKey.SetValue(variable, value, RegistryValueKind.String);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -102,23 +113,32 @@ namespace EnvironmentVariables.Helpers
|
||||
}
|
||||
}
|
||||
|
||||
// Code taken from https://github.com/dotnet/runtime/blob/main/src/libraries/System.Private.CoreLib/src/System/Environment.Win32.cs
|
||||
// Reading variables from registry instead of using Environment API, because Environment API expands variables by default.
|
||||
internal static void GetVariables(EnvironmentVariableTarget target, VariablesSet set)
|
||||
{
|
||||
var variables = Environment.GetEnvironmentVariables(target);
|
||||
var sortedList = new SortedList<string, Variable>();
|
||||
|
||||
foreach (DictionaryEntry variable in variables)
|
||||
bool fromMachine = target == EnvironmentVariableTarget.Machine ? true : false;
|
||||
|
||||
using (RegistryKey environmentKey = OpenEnvironmentKeyIfExists(fromMachine, writable: false))
|
||||
{
|
||||
string key = variable.Key as string;
|
||||
string value = variable.Value as string;
|
||||
|
||||
if (string.IsNullOrEmpty(key))
|
||||
if (environmentKey != null)
|
||||
{
|
||||
continue;
|
||||
foreach (string name in environmentKey.GetValueNames())
|
||||
{
|
||||
string value = environmentKey.GetValue(name, string.Empty, RegistryValueOptions.DoNotExpandEnvironmentNames).ToString();
|
||||
try
|
||||
{
|
||||
Variable entry = new Variable(name, value, set.Type);
|
||||
sortedList.Add(name, entry);
|
||||
}
|
||||
catch (ArgumentException)
|
||||
{
|
||||
// Throw and catch intentionally to provide non-fatal notification about corrupted environment block
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Variable entry = new Variable(key, value, set.Type);
|
||||
sortedList.Add(key, entry);
|
||||
}
|
||||
|
||||
set.Variables = new System.Collections.ObjectModel.ObservableCollection<Variable>(sortedList.Values);
|
||||
|
@@ -132,10 +132,13 @@ namespace EnvironmentVariables.ViewModels
|
||||
var variables = new List<Variable>();
|
||||
if (AppliedProfile != null)
|
||||
{
|
||||
variables = variables.Concat(AppliedProfile.Variables.OrderBy(x => x.Name)).ToList();
|
||||
variables = variables.Concat(AppliedProfile.Variables.Select(x => new Variable(x.Name, Environment.ExpandEnvironmentVariables(x.Values), VariablesSetType.Profile)).OrderBy(x => x.Name)).ToList();
|
||||
}
|
||||
|
||||
variables = variables.Concat(UserDefaultSet.Variables.OrderBy(x => x.Name)).Concat(SystemDefaultSet.Variables.OrderBy(x => x.Name)).ToList();
|
||||
// Variables are expanded to be shown in the applied variables section, so the user sees their actual values.
|
||||
variables = variables.Concat(UserDefaultSet.Variables.Select(x => new Variable(x.Name, Environment.ExpandEnvironmentVariables(x.Values), VariablesSetType.User)).OrderBy(x => x.Name))
|
||||
.Concat(SystemDefaultSet.Variables.Select(x => new Variable(x.Name, Environment.ExpandEnvironmentVariables(x.Values), VariablesSetType.System)).OrderBy(x => x.Name))
|
||||
.ToList();
|
||||
|
||||
// Handle PATH variable - add USER value to the end of the SYSTEM value
|
||||
var profilePath = variables.Where(x => x.Name.Equals("PATH", StringComparison.OrdinalIgnoreCase) && x.ParentType == VariablesSetType.Profile).FirstOrDefault();
|
||||
|
Reference in New Issue
Block a user