winget-cli

Unnamed repository; edit this file 'description' to name the repository.
Log | Files | Refs | README | LICENSE

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 }