PathEnvironmentVariableHandler.cs (3000B)
1 // ----------------------------------------------------------------------------- 2 // <copyright file="PathEnvironmentVariableHandler.cs" company="Microsoft Corporation"> 3 // Copyright (c) Microsoft Corporation. Licensed under the MIT License. 4 // </copyright> 5 // ----------------------------------------------------------------------------- 6 7 namespace Microsoft.Management.Configuration.Processor.Helpers 8 { 9 using System; 10 using System.Collections.Generic; 11 12 /// <summary> 13 /// Class for handling PATH environment variable. 14 /// </summary> 15 public static class PathEnvironmentVariableHandler 16 { 17 private const string PathEnvironmentVariable = "PATH"; 18 19 private static readonly object EnvironmentVariableLock = new object(); 20 21 /// <summary> 22 /// Gets the lock to read or write PATH environment variable. 23 /// </summary> 24 public static object Lock 25 { 26 get { return EnvironmentVariableLock; } 27 } 28 29 /// <summary> 30 /// Updates the process's PATH environment variable if new paths added. 31 /// Only adds new paths since we add to PATH in other code which may not be in the registry. 32 /// </summary> 33 public static void UpdatePath() 34 { 35 HashSet<string> paths = new HashSet<string>(Environment.GetEnvironmentVariable(PathEnvironmentVariable)?.Split(';') ?? Array.Empty<string>()); 36 var originalPathsSize = paths.Count; 37 38 AddPathsIfNotExist(paths, Environment.GetEnvironmentVariable(PathEnvironmentVariable, EnvironmentVariableTarget.Machine)?.Split(';')); 39 AddPathsIfNotExist(paths, Environment.GetEnvironmentVariable(PathEnvironmentVariable, EnvironmentVariableTarget.User)?.Split(';')); 40 41 if (paths.Count > originalPathsSize) 42 { 43 lock (Lock) 44 { 45 Environment.SetEnvironmentVariable(PathEnvironmentVariable, string.Join(';', paths)); 46 } 47 } 48 } 49 50 // TODO: Currently it always adds new paths to the end. The "proper" thing to do would probably be to calculate 51 // the full new list of paths (what one would expect to get from a new process launch) and use a line merge algorithm 52 // with a strategy that puts the ephemeral entries before the new permanent ones. 53 #pragma warning disable SA1011 // Closing square brackets should be spaced correctly 54 private static void AddPathsIfNotExist(HashSet<string> currentPaths, string[]? paths) 55 #pragma warning restore SA1011 // Closing square brackets should be spaced correctly 56 { 57 if (paths is not null) 58 { 59 foreach (var path in paths) 60 { 61 if (!currentPaths.Contains(path)) 62 { 63 currentPaths.Add(path); 64 } 65 } 66 } 67 } 68 } 69 }