├── .gitignore ├── README.md ├── RELEASING ├── TODO ├── WINDOWS PATH.txt ├── WindowsPathEditor.sln ├── WindowsPathEditor ├── AnnotatedPathEntry.cs ├── App.xaml ├── App.xaml.cs ├── AutoCompleteBox.xaml ├── AutoCompleteBox.xaml.cs ├── DiffPath.cs ├── DiffWindow.xaml ├── DiffWindow.xaml.cs ├── DirectoryList.xaml ├── DirectoryList.xaml.cs ├── DragDropListBox │ ├── DragDropHelper.cs │ ├── DraggedAdorner.cs │ ├── InsertionAdorner.cs │ └── Utilities.cs ├── ExtensionMethods.cs ├── FolderBrowserDialogEx.cs ├── IReportProgress.cs ├── InvertBooleanConverter.cs ├── MainWindow.xaml ├── MainWindow.xaml.cs ├── ObservableCollectionEx.cs ├── PathChecker.cs ├── PathEntry.cs ├── PathMatch.cs ├── PathRegistry.cs ├── Properties │ ├── AssemblyInfo.cs │ ├── Resources.Designer.cs │ ├── Resources.resx │ ├── Settings.Designer.cs │ └── Settings.settings ├── Resources │ ├── accept.png │ ├── add.png │ ├── cross.png │ ├── delete.png │ ├── error.png │ ├── folder_explore.png │ └── view_text.ico ├── ScanningWindow.xaml ├── ScanningWindow.xaml.cs ├── SearchOperation.cs ├── SelectablePath.cs ├── UAC.cs ├── ValueConverterGroup.cs ├── WindowsPathEditor.csproj └── packages.config └── screenshot.png /.gitignore: -------------------------------------------------------------------------------- 1 | Debug 2 | Release 3 | *.user 4 | *.suo 5 | *.sdf 6 | packages 7 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | Windows Path Editor 2 | =================== 3 | 4 | This tool helps you manage your PATH on Windows. 5 | 6 | [Download Latest Version (1.7)](https://github.com/rix0rrr/WindowsPathEditor/releases/download/1.7/windowspatheditor-1.7.zip) 7 | 8 | Introduction 9 | ----------- 10 | 11 | In a fit of horrible irony, on Windows you'll both have the most need to edit 12 | your PATH (since all applications insist on creating their own `bin` 13 | directories instead of installing to a global `bin` directory like on Unices), 14 | and you're also equipped with the absolute worst tools to deal with this. The 15 | default environment editor dialog where you get to see 30 characters at once if 16 | you're lucky? Yuck. 17 | 18 | *Windows Path Editor* (a horribly creative name, I know) gives you a 19 | better overview and easier ways to manipulate your path settings. 20 | 21 | Features 22 | ----------- 23 | 24 | - Edit your path using drag and drop. 25 | - Detect conflicts between directories on your path (diagnose issues like the 26 | wrong executable being launched or the wrong DLL being loaded). 27 | - Remove bogus entries from your path with a single click. 28 | - Scan your disk for tools that have a `bin` directory and automatically add 29 | them to your path. 30 | - UAC aware. 31 | 32 | ![Screen Shot of Windows Path Editor](https://raw.github.com/rix0rrr/WindowsPathEditor/master/screenshot.png) 33 | -------------------------------------------------------------------------------- /RELEASING: -------------------------------------------------------------------------------- 1 | - Increment version number in AssemblyInfo.cs 2 | - Build as Debug (for the purposes of Debug.Print) 3 | - Zip contents of bin\Release to windowspatheditor-x.x.zip (don't include vshost.*) 4 | - Upload to GitHub releases, URL will be https://github.com/rix0rrr/WindowsPathEditor/releases/download/x.x/windowspatheditor-x.x.zip 5 | - Update README.md w/ new version link 6 | - Commit, Tag 7 | - Switch to gh-pages branch 8 | - Edit index.html, link to new version (in 2 places!) 9 | - Push (both branches!) 10 | -------------------------------------------------------------------------------- /TODO: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/rix0rrr/WindowsPathEditor/aa82da59f26ab662f0d5a9906c333ba9619bcc24/TODO -------------------------------------------------------------------------------- /WINDOWS PATH.txt: -------------------------------------------------------------------------------- 1 | Precedence: first SYSTEM then USER 2 | -------------------------------------------------------------------------------- /WindowsPathEditor.sln: -------------------------------------------------------------------------------- 1 |  2 | Microsoft Visual Studio Solution File, Format Version 11.00 3 | # Visual Studio 2010 4 | Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "WindowsPathEditor", "WindowsPathEditor\WindowsPathEditor.csproj", "{27BB9DC6-B4E7-4600-98E1-9C855720DF69}" 5 | EndProject 6 | Global 7 | GlobalSection(SolutionConfigurationPlatforms) = preSolution 8 | Debug|x86 = Debug|x86 9 | Release|x86 = Release|x86 10 | EndGlobalSection 11 | GlobalSection(ProjectConfigurationPlatforms) = postSolution 12 | {27BB9DC6-B4E7-4600-98E1-9C855720DF69}.Debug|x86.ActiveCfg = Debug|x86 13 | {27BB9DC6-B4E7-4600-98E1-9C855720DF69}.Debug|x86.Build.0 = Debug|x86 14 | {27BB9DC6-B4E7-4600-98E1-9C855720DF69}.Release|x86.ActiveCfg = Release|x86 15 | {27BB9DC6-B4E7-4600-98E1-9C855720DF69}.Release|x86.Build.0 = Release|x86 16 | EndGlobalSection 17 | GlobalSection(SolutionProperties) = preSolution 18 | HideSolutionNode = FALSE 19 | EndGlobalSection 20 | EndGlobal 21 | -------------------------------------------------------------------------------- /WindowsPathEditor/AnnotatedPathEntry.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Linq; 4 | using System.Text; 5 | using System.ComponentModel; 6 | 7 | namespace WindowsPathEditor 8 | { 9 | /// 10 | /// Mutable wrapper for a PathEntry that can have issues added to i 11 | /// 12 | public class AnnotatedPathEntry : INotifyPropertyChanged 13 | { 14 | public event PropertyChangedEventHandler PropertyChanged; 15 | private List issues = new List(); 16 | 17 | public AnnotatedPathEntry(PathEntry path) 18 | { 19 | Path = path; 20 | SeriousError = false; 21 | } 22 | 23 | public PathEntry Path { get; private set; } 24 | 25 | /// 26 | /// Return the alert level (0, 1 or 2) depending on whether everything is ok, the dirty has issues or is missing 27 | /// 28 | public int AlertLevel 29 | { 30 | get 31 | { 32 | if (SeriousError) return 2; 33 | if (issues.Count() > 0) return 1; 34 | return 0; 35 | } 36 | } 37 | 38 | public bool SeriousError { get; set; } 39 | 40 | public bool Exists { get { return Path.Exists; } } 41 | 42 | public string SymbolicPath { get { return Path.SymbolicPath; } } 43 | 44 | 45 | /// 46 | /// Return all issues with the PathEntry 47 | /// 48 | public IEnumerable Issues 49 | { 50 | get 51 | { 52 | lock (issues) 53 | { 54 | return issues.ToList(); 55 | } 56 | } 57 | } 58 | 59 | /// 60 | /// Add an issue 61 | /// 62 | public void AddIssue(string issue) 63 | { 64 | lock (issues) issues.Add(issue); 65 | PropertyChanged.Notify(() => Issues); 66 | PropertyChanged.Notify(() => AlertLevel); 67 | } 68 | 69 | internal void ClearIssues() 70 | { 71 | lock(issues) issues.Clear(); 72 | PropertyChanged.Notify(() => Issues); 73 | PropertyChanged.Notify(() => AlertLevel); 74 | } 75 | 76 | public override string ToString() 77 | { 78 | return Path.ToString(); 79 | } 80 | 81 | public static AnnotatedPathEntry FromPath(PathEntry p) 82 | { 83 | return new AnnotatedPathEntry(p); 84 | } 85 | } 86 | } 87 | -------------------------------------------------------------------------------- /WindowsPathEditor/App.xaml: -------------------------------------------------------------------------------- 1 |  5 | 6 | 7 | 8 | 9 | -------------------------------------------------------------------------------- /WindowsPathEditor/App.xaml.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Configuration; 4 | using System.Data; 5 | using System.Linq; 6 | using System.Windows; 7 | 8 | namespace WindowsPathEditor 9 | { 10 | /// 11 | /// Interaction logic for App.xaml 12 | /// 13 | public partial class App : Application 14 | { 15 | } 16 | } 17 | -------------------------------------------------------------------------------- /WindowsPathEditor/AutoCompleteBox.xaml: -------------------------------------------------------------------------------- 1 |  8 | 9 | 10 | 18 | 23 | 24 | 38 | 39 | 40 | 41 | 42 | 43 | -------------------------------------------------------------------------------- /WindowsPathEditor/AutoCompleteBox.xaml.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Linq; 4 | using System.Text; 5 | using System.Windows; 6 | using System.Windows.Controls; 7 | using System.Windows.Data; 8 | using System.Windows.Documents; 9 | using System.Windows.Input; 10 | using System.Windows.Media; 11 | using System.Windows.Media.Imaging; 12 | using System.Windows.Navigation; 13 | using System.Windows.Shapes; 14 | using System.Reactive.Linq; 15 | using System.Reactive.Concurrency; 16 | 17 | namespace WindowsPathEditor 18 | { 19 | /// 20 | /// Interaction logic for AutoCompleteBox.xaml 21 | /// 22 | public partial class AutoCompleteBox 23 | { 24 | private IDisposable subscription; 25 | 26 | public AutoCompleteBox() 27 | { 28 | InitializeComponent(); 29 | } 30 | 31 | public void SetCompleteProvider(Func> provider) 32 | { 33 | if (subscription != null) subscription.Dispose(); 34 | 35 | var changes = Observable.FromEventPattern(textBox, "TextChanged") 36 | .Select(e => ((TextBox)e.Sender).Text) 37 | .Where(txt => txt != ""); 38 | 39 | var search = Observable.ToAsync>(provider); 40 | 41 | var results = from s in changes 42 | from r in search(s).TakeUntil(changes) 43 | select r; 44 | 45 | subscription = results.ObserveOnDispatcher() 46 | .Subscribe(res => 47 | { 48 | popup.IsOpen = true; 49 | if (res.Count() > 0) 50 | suggestionList.ItemsSource = res; 51 | else 52 | suggestionList.ItemsSource = new string[] { "(no matches)" }; 53 | }); 54 | } 55 | 56 | private void textBox_KeyUp(object sender, KeyEventArgs e) 57 | { 58 | if (e.Key == Key.Escape) { textBox.Text = ""; popup.IsOpen = false; } 59 | if (textBox.Text == "") popup.IsOpen = false; 60 | } 61 | } 62 | } 63 | -------------------------------------------------------------------------------- /WindowsPathEditor/DiffPath.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Linq; 4 | using System.Text; 5 | 6 | namespace WindowsPathEditor 7 | { 8 | public class DiffPath 9 | { 10 | public DiffPath(PathEntry path, bool added) 11 | { 12 | Path = path; 13 | IsAdded = added; 14 | } 15 | 16 | public PathEntry Path { get; private set; } 17 | 18 | public bool IsAdded { get; private set; } 19 | 20 | public string SymbolicPath { get { return Path.SymbolicPath; } } 21 | } 22 | } 23 | -------------------------------------------------------------------------------- /WindowsPathEditor/DiffWindow.xaml: -------------------------------------------------------------------------------- 1 |  8 | 9 |