Skip to content

Commit

Permalink
Merge pull request #353 from gerardog/feature/path-precedence
Browse files Browse the repository at this point in the history
New PathPrecedence Setting to reorder the PATH environment variable
  • Loading branch information
gerardog authored May 26, 2024
2 parents 0481eff + 1f8474f commit ccf99bf
Show file tree
Hide file tree
Showing 3 changed files with 60 additions and 2 deletions.
2 changes: 1 addition & 1 deletion src/gsudo.Wrappers/gsudoModule.psm1
Original file line number Diff line number Diff line change
Expand Up @@ -134,7 +134,7 @@ if ($gsudoAutoComplete) {
'--integrity' = $integrityOptions;
'-i' = $integrityOptions;
'cache' = @('on', 'off', 'help');
'config' = @('CacheMode', 'CacheDuration', 'LogLevel', 'NewWindow.Force', 'NewWindow.CloseBehaviour', 'Prompt', 'PipedPrompt', 'ForceAttachedConsole', 'ForcePipedConsole', 'ForceVTConsole', 'CopyEnvironmentVariables', 'CopyNetworkShares', 'PowerShellLoadProfile', 'SecurityEnforceUacIsolation', 'ExceptionList');
'config' = @('CacheMode', 'CacheDuration', 'LogLevel', 'NewWindow.Force', 'NewWindow.CloseBehaviour', 'Prompt', 'PipedPrompt', 'PathPrecedence', 'ForceAttachedConsole', 'ForcePipedConsole', 'ForceVTConsole', 'CopyEnvironmentVariables', 'CopyNetworkShares', 'PowerShellLoadProfile', 'SecurityEnforceUacIsolation', 'ExceptionList');
'cachemode' = @('Auto', 'Disabled', 'Explicit', '--reset');
'loglevel' = @('All', 'Debug', 'Info', 'Warning', 'Error', 'None', '--reset');
'NewWindow.CloseBehaviour' = @('KeepShellOpen', 'PressKeyToClose', 'OsDefault', '--reset');
Expand Down
55 changes: 55 additions & 0 deletions src/gsudo/AppSettings/PathPrecedenceSetting.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,55 @@
using gsudo.Helpers;
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;

namespace gsudo.AppSettings
{
/// <summary>
/// Reorders the PATH environment variable to prioritize gsudo's path.
/// Saving the boolean value to the registry is anecdotical, the real change is done in the environment variable.
/// </summary>
internal class PathPrecedenceSetting : RegistrySetting<bool>
{
public PathPrecedenceSetting():
base("PathPrecedence", false, bool.Parse, RegistrySettingScope.GlobalOnly)
{

}

public override void Save(string newValue, bool global)
{
bool bNewValue = bool.Parse(newValue);
var ourPath = Path.GetDirectoryName(ProcessFactory.FindExecutableInPath("gsudo.exe")) // shim
?? Path.GetDirectoryName(ProcessHelper.GetOwnExeName());

var system32Path = Environment.GetFolderPath(Environment.SpecialFolder.System);

var allPaths = Environment.GetEnvironmentVariable("Path", EnvironmentVariableTarget.Machine).Split(new[] { ';' }, StringSplitOptions.RemoveEmptyEntries);
// I could also do .Distinct(StringComparer.OrdinalIgnoreCase);
// ...and it works well on local, but may be out of our responsibility to fix that.

IEnumerable<string> newPath;

if (bNewValue)
newPath = new[] { ourPath }.Concat(allPaths.Where(p => !p.Equals(ourPath, StringComparison.OrdinalIgnoreCase)));
else
newPath = allPaths.Where(p => !p.Equals(ourPath, StringComparison.OrdinalIgnoreCase)).Concat(new[] { ourPath });

var finalStringPath = string.Join(";", newPath);

Logger.Instance.Log($"Updating PATH environment variable to: {finalStringPath}", LogLevel.Debug);

Environment.SetEnvironmentVariable("Path", finalStringPath, EnvironmentVariableTarget.Machine);
base.Save(newValue, global);

if (bNewValue)
Logger.Instance.Log($"\"{ourPath}\" path is now prioritized in the PATH environment variable.", LogLevel.Info);
else
Logger.Instance.Log($"\"{system32Path}\" path is now prioritized in the PATH environment variable.", LogLevel.Info);

Logger.Instance.Log("Please restart all your consoles to ensure the change makes effect.", LogLevel.Warning);
}
}
}
5 changes: 4 additions & 1 deletion src/gsudo/AppSettings/Settings.cs
Original file line number Diff line number Diff line change
Expand Up @@ -98,6 +98,8 @@ class Settings
deserializer: ExtensionMethods.ParseEnum<CloseBehaviour>,
scope: RegistrySettingScope.Any);

public static RegistrySetting<bool> PathOverrideSetting = new PathPrecedenceSetting();

public static IDictionary<string, RegistrySetting> AllKeys =>
new Dictionary<string, RegistrySetting>(StringComparer.OrdinalIgnoreCase)
.Add(
Expand All @@ -120,7 +122,8 @@ class Settings

PowerShellLoadProfile,
SecurityEnforceUacIsolation,
ExceptionList
ExceptionList,
PathOverrideSetting
);

internal static TimeSpan TimeSpanParseWithInfinite(string value)
Expand Down

0 comments on commit ccf99bf

Please sign in to comment.