├── .vs ├── ProjectSettings.json └── slnx.sqlite ├── .nuget ├── NuGet.exe ├── NuGet.Config └── NuGet.targets ├── RegistryExplorer ├── Images │ ├── cut.png │ ├── copy.png │ ├── down.png │ ├── exit.png │ ├── find.png │ ├── paste.png │ ├── redo.png │ ├── undo.png │ ├── delete2.png │ ├── export.png │ ├── folder.png │ ├── hivekey.png │ ├── import.png │ ├── import2.png │ ├── newvalue.png │ ├── refresh.png │ ├── registry.ico │ ├── shield.png │ ├── book_blue.png │ ├── favorites.png │ ├── find_next.png │ ├── find_previous.png │ ├── folder_blue.png │ ├── folder_closed.png │ ├── workstation2.png │ └── DataTypes │ │ ├── empty.png │ │ ├── reg_binary.png │ │ └── reg_string.png ├── Properties │ ├── Settings.settings │ ├── Settings.Designer.cs │ ├── AssemblyInfo.cs │ ├── Resources.Designer.cs │ └── Resources.resx ├── packages.config ├── Styles.xaml ├── ViewModels │ ├── RegistryKeyItemSpecial.cs │ ├── ValueViewModel.cs │ ├── AccentViewModel.cs │ ├── RegistryItem.cs │ ├── ToolBarViewModel.cs │ ├── MenuBarViewModel.cs │ ├── Dialogs │ │ └── LoadHiveViewModel.cs │ ├── RegistryKeyItemBase.cs │ ├── DataGridViewModel.cs │ ├── RegistryValue.cs │ ├── RegistryKeyItem.cs │ └── MainViewModel.cs ├── Behaviors │ ├── VirtualizingStackPanelEx.cs │ ├── ValueCellTemplateSelector.cs │ ├── TextBoxEditingBehavior.cs │ ├── SelectedTreeViewItemBehavior.cs │ ├── ActiveViewBehavior.cs │ ├── TreeViewHelper.cs │ └── KeyNavigationTreeViewBehavior.cs ├── Model │ ├── Options.cs │ └── Commands.cs ├── Extensions │ ├── DialogHelper.cs │ └── ImageExtension.cs ├── VisualTreeHelpers.cs ├── Converters │ ├── StringPrefixConverter.cs │ └── DataTypeToImageConverter.cs ├── MainWindow.xaml.cs ├── Views │ ├── Dialogs │ │ ├── LoadHiveView.xaml.cs │ │ └── LoadHiveView.xaml │ ├── MenuBarView.xaml.cs │ ├── ToolBarView.xaml.cs │ ├── DataGridView.xaml.cs │ ├── RegistryTreeView.xaml.cs │ ├── ToolBarView.xaml │ ├── MenuBarView.xaml │ ├── DataGridView.xaml │ └── RegistryTreeView.xaml ├── App.config ├── DialogViewModelBase.cs ├── AppCommand.cs ├── ViewModelBase.cs ├── Serialization │ └── Serializer.cs ├── App.xaml ├── App.xaml.cs ├── CommandManager.cs ├── MainWindow.xaml ├── app.manifest ├── NativeMethods.cs └── RegistryExplorer.csproj ├── README.md ├── RegistryExplorer.sln ├── .gitattributes └── .gitignore /.vs/ProjectSettings.json: -------------------------------------------------------------------------------- 1 | { 2 | "CurrentProjectSetting": null 3 | } -------------------------------------------------------------------------------- /.nuget/NuGet.exe: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/zodiacon/RegistryExplorer/HEAD/.nuget/NuGet.exe -------------------------------------------------------------------------------- /.vs/slnx.sqlite: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/zodiacon/RegistryExplorer/HEAD/.vs/slnx.sqlite -------------------------------------------------------------------------------- /RegistryExplorer/Images/cut.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/zodiacon/RegistryExplorer/HEAD/RegistryExplorer/Images/cut.png -------------------------------------------------------------------------------- /RegistryExplorer/Images/copy.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/zodiacon/RegistryExplorer/HEAD/RegistryExplorer/Images/copy.png -------------------------------------------------------------------------------- /RegistryExplorer/Images/down.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/zodiacon/RegistryExplorer/HEAD/RegistryExplorer/Images/down.png -------------------------------------------------------------------------------- /RegistryExplorer/Images/exit.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/zodiacon/RegistryExplorer/HEAD/RegistryExplorer/Images/exit.png -------------------------------------------------------------------------------- /RegistryExplorer/Images/find.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/zodiacon/RegistryExplorer/HEAD/RegistryExplorer/Images/find.png -------------------------------------------------------------------------------- /RegistryExplorer/Images/paste.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/zodiacon/RegistryExplorer/HEAD/RegistryExplorer/Images/paste.png -------------------------------------------------------------------------------- /RegistryExplorer/Images/redo.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/zodiacon/RegistryExplorer/HEAD/RegistryExplorer/Images/redo.png -------------------------------------------------------------------------------- /RegistryExplorer/Images/undo.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/zodiacon/RegistryExplorer/HEAD/RegistryExplorer/Images/undo.png -------------------------------------------------------------------------------- /RegistryExplorer/Images/delete2.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/zodiacon/RegistryExplorer/HEAD/RegistryExplorer/Images/delete2.png -------------------------------------------------------------------------------- /RegistryExplorer/Images/export.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/zodiacon/RegistryExplorer/HEAD/RegistryExplorer/Images/export.png -------------------------------------------------------------------------------- /RegistryExplorer/Images/folder.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/zodiacon/RegistryExplorer/HEAD/RegistryExplorer/Images/folder.png -------------------------------------------------------------------------------- /RegistryExplorer/Images/hivekey.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/zodiacon/RegistryExplorer/HEAD/RegistryExplorer/Images/hivekey.png -------------------------------------------------------------------------------- /RegistryExplorer/Images/import.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/zodiacon/RegistryExplorer/HEAD/RegistryExplorer/Images/import.png -------------------------------------------------------------------------------- /RegistryExplorer/Images/import2.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/zodiacon/RegistryExplorer/HEAD/RegistryExplorer/Images/import2.png -------------------------------------------------------------------------------- /RegistryExplorer/Images/newvalue.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/zodiacon/RegistryExplorer/HEAD/RegistryExplorer/Images/newvalue.png -------------------------------------------------------------------------------- /RegistryExplorer/Images/refresh.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/zodiacon/RegistryExplorer/HEAD/RegistryExplorer/Images/refresh.png -------------------------------------------------------------------------------- /RegistryExplorer/Images/registry.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/zodiacon/RegistryExplorer/HEAD/RegistryExplorer/Images/registry.ico -------------------------------------------------------------------------------- /RegistryExplorer/Images/shield.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/zodiacon/RegistryExplorer/HEAD/RegistryExplorer/Images/shield.png -------------------------------------------------------------------------------- /RegistryExplorer/Images/book_blue.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/zodiacon/RegistryExplorer/HEAD/RegistryExplorer/Images/book_blue.png -------------------------------------------------------------------------------- /RegistryExplorer/Images/favorites.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/zodiacon/RegistryExplorer/HEAD/RegistryExplorer/Images/favorites.png -------------------------------------------------------------------------------- /RegistryExplorer/Images/find_next.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/zodiacon/RegistryExplorer/HEAD/RegistryExplorer/Images/find_next.png -------------------------------------------------------------------------------- /RegistryExplorer/Images/find_previous.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/zodiacon/RegistryExplorer/HEAD/RegistryExplorer/Images/find_previous.png -------------------------------------------------------------------------------- /RegistryExplorer/Images/folder_blue.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/zodiacon/RegistryExplorer/HEAD/RegistryExplorer/Images/folder_blue.png -------------------------------------------------------------------------------- /RegistryExplorer/Images/folder_closed.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/zodiacon/RegistryExplorer/HEAD/RegistryExplorer/Images/folder_closed.png -------------------------------------------------------------------------------- /RegistryExplorer/Images/workstation2.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/zodiacon/RegistryExplorer/HEAD/RegistryExplorer/Images/workstation2.png -------------------------------------------------------------------------------- /RegistryExplorer/Images/DataTypes/empty.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/zodiacon/RegistryExplorer/HEAD/RegistryExplorer/Images/DataTypes/empty.png -------------------------------------------------------------------------------- /RegistryExplorer/Images/DataTypes/reg_binary.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/zodiacon/RegistryExplorer/HEAD/RegistryExplorer/Images/DataTypes/reg_binary.png -------------------------------------------------------------------------------- /RegistryExplorer/Images/DataTypes/reg_string.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/zodiacon/RegistryExplorer/HEAD/RegistryExplorer/Images/DataTypes/reg_string.png -------------------------------------------------------------------------------- /.nuget/NuGet.Config: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | -------------------------------------------------------------------------------- /RegistryExplorer/Properties/Settings.settings: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # RegistryExplorer 2 | 3 | Registry Explorer is intended to be a replacement for Windows RegEdit.exe tool. 4 | 5 | Notable improvements (some are work in progress): 6 | 1. A read only mode to prevent accidental changes 7 | 2. multi level undo/redo for all operations 8 | 3. value filtering 9 | -------------------------------------------------------------------------------- /RegistryExplorer/packages.config: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | -------------------------------------------------------------------------------- /RegistryExplorer/Styles.xaml: -------------------------------------------------------------------------------- 1 | 6 | -------------------------------------------------------------------------------- /RegistryExplorer/ViewModels/RegistryKeyItemSpecial.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Linq; 4 | using System.Text; 5 | using System.Threading.Tasks; 6 | 7 | namespace RegistryExplorer.ViewModels { 8 | class RegistryKeyItemSpecial : RegistryKeyItemBase { 9 | public string Icon { get; set; } 10 | 11 | public IEnumerable Values { 12 | get { return null; } 13 | } 14 | 15 | public RegistryKeyItemSpecial(RegistryKeyItemBase parent) 16 | : base(parent) { 17 | } 18 | } 19 | } 20 | -------------------------------------------------------------------------------- /RegistryExplorer/Behaviors/VirtualizingStackPanelEx.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Linq; 4 | using System.Text; 5 | using System.Threading.Tasks; 6 | using System.Windows.Controls; 7 | 8 | namespace RegistryExplorer.Behaviors { 9 | public class VirtualizingStackPanelEx : VirtualizingStackPanel { 10 | /// 11 | /// Publically expose BringIndexIntoView. 12 | /// 13 | public void BringIntoView(int index) { 14 | 15 | base.BringIndexIntoView(index); 16 | } 17 | } 18 | 19 | } 20 | -------------------------------------------------------------------------------- /RegistryExplorer/Model/Options.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Linq; 4 | using System.Text; 5 | using System.Threading.Tasks; 6 | using Prism.Mvvm; 7 | 8 | namespace RegistryExplorer.Model { 9 | class Options : BindableBase { 10 | private bool _alwaysOnTop; 11 | 12 | public bool AlwaysOnTop { 13 | get { return _alwaysOnTop; } 14 | set { 15 | if(SetProperty(ref _alwaysOnTop, value)) { 16 | App.Current.MainWindow.Topmost = value; 17 | } 18 | } 19 | } 20 | 21 | 22 | } 23 | } 24 | -------------------------------------------------------------------------------- /RegistryExplorer/ViewModels/ValueViewModel.cs: -------------------------------------------------------------------------------- 1 | using Microsoft.Win32; 2 | using System; 3 | using System.Collections.Generic; 4 | using System.Linq; 5 | using System.Text; 6 | using System.Threading.Tasks; 7 | using System.Windows.Input; 8 | 9 | namespace RegistryExplorer.ViewModels { 10 | class ValueViewModel { 11 | public string Text { get; set; } 12 | public RegistryValueKind Type { get; set; } 13 | public ICommand Command { get; } 14 | 15 | public ValueViewModel() { 16 | Command = App.MainViewModel.CreateNewValueCommand; 17 | } 18 | } 19 | } 20 | -------------------------------------------------------------------------------- /RegistryExplorer/Extensions/DialogHelper.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Linq; 4 | using System.Text; 5 | using System.Threading.Tasks; 6 | using System.Windows; 7 | 8 | namespace RegistryExplorer.Extensions { 9 | static class DialogHelper { 10 | public static TViewModel ShowDialog() where TDialog : FrameworkElement, new() { 11 | var dlg = new TDialog(); 12 | var vm = (TViewModel)Activator.CreateInstance(typeof(TViewModel), dlg); 13 | dlg.DataContext = vm; 14 | return vm; 15 | } 16 | } 17 | } 18 | -------------------------------------------------------------------------------- /RegistryExplorer/ViewModels/AccentViewModel.cs: -------------------------------------------------------------------------------- 1 | using MahApps.Metro; 2 | using System; 3 | using System.Collections.Generic; 4 | using System.Linq; 5 | using System.Text; 6 | using System.Threading.Tasks; 7 | using System.Windows.Media; 8 | 9 | namespace RegistryExplorer.ViewModels { 10 | class AccentViewModel { 11 | public Accent Accent { get; } 12 | 13 | public AccentViewModel(Accent accent) { 14 | Accent = accent; 15 | 16 | } 17 | 18 | public string Name => Accent.Name; 19 | public Brush Color => Accent.Resources["AccentColorBrush"] as Brush; 20 | 21 | } 22 | } 23 | -------------------------------------------------------------------------------- /RegistryExplorer/VisualTreeHelpers.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Linq; 4 | using System.Text; 5 | using System.Threading.Tasks; 6 | using System.Windows; 7 | using System.Windows.Media; 8 | 9 | namespace RegistryExplorer { 10 | static class VisualTreeHelpers { 11 | public static bool IsChildOf(this FrameworkElement source, FrameworkElement parent) { 12 | while(source != null) { 13 | if(source == parent) 14 | return true; 15 | source = VisualTreeHelper.GetParent(source) as FrameworkElement; 16 | } 17 | return false; 18 | } 19 | } 20 | } 21 | -------------------------------------------------------------------------------- /RegistryExplorer/Converters/StringPrefixConverter.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Globalization; 4 | using System.Linq; 5 | using System.Text; 6 | using System.Threading.Tasks; 7 | using System.Windows.Data; 8 | 9 | namespace RegistryExplorer.Converters { 10 | class StringPrefixConverter : IValueConverter { 11 | public object Convert(object value, Type targetType, object parameter, CultureInfo culture) { 12 | return string.Format("{0} {1}", parameter, value); 13 | } 14 | 15 | public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture) { 16 | throw new NotImplementedException(); 17 | } 18 | } 19 | } 20 | -------------------------------------------------------------------------------- /RegistryExplorer/MainWindow.xaml.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Linq; 4 | using System.Text; 5 | using System.Threading.Tasks; 6 | using System.Windows; 7 | using System.Windows.Controls; 8 | using System.Windows.Data; 9 | using System.Windows.Documents; 10 | using System.Windows.Input; 11 | using System.Windows.Media; 12 | using System.Windows.Media.Imaging; 13 | using System.Windows.Navigation; 14 | using System.Windows.Shapes; 15 | 16 | namespace RegistryExplorer { 17 | /// 18 | /// Interaction logic for MainWindow.xaml 19 | /// 20 | public partial class MainWindow { 21 | public MainWindow() { 22 | InitializeComponent(); 23 | } 24 | } 25 | } 26 | -------------------------------------------------------------------------------- /RegistryExplorer/Views/Dialogs/LoadHiveView.xaml.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Linq; 4 | using System.Text; 5 | using System.Threading.Tasks; 6 | using System.Windows; 7 | using System.Windows.Controls; 8 | using System.Windows.Data; 9 | using System.Windows.Documents; 10 | using System.Windows.Input; 11 | using System.Windows.Media; 12 | using System.Windows.Media.Imaging; 13 | using System.Windows.Shapes; 14 | 15 | namespace RegistryExplorer.Views.Dialogs { 16 | /// 17 | /// Interaction logic for LoadHiveView.xaml 18 | /// 19 | public partial class LoadHiveView { 20 | public LoadHiveView() { 21 | InitializeComponent(); 22 | } 23 | } 24 | } 25 | -------------------------------------------------------------------------------- /RegistryExplorer/Views/MenuBarView.xaml.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Linq; 4 | using System.Text; 5 | using System.Threading.Tasks; 6 | using System.Windows; 7 | using System.Windows.Controls; 8 | using System.Windows.Data; 9 | using System.Windows.Documents; 10 | using System.Windows.Input; 11 | using System.Windows.Media; 12 | using System.Windows.Media.Imaging; 13 | using System.Windows.Navigation; 14 | using System.Windows.Shapes; 15 | 16 | namespace RegistryExplorer.Views { 17 | /// 18 | /// Interaction logic for MenuBarView.xaml 19 | /// 20 | public partial class MenuBarView : UserControl { 21 | public MenuBarView() { 22 | InitializeComponent(); 23 | } 24 | } 25 | } 26 | -------------------------------------------------------------------------------- /RegistryExplorer/Views/ToolBarView.xaml.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Linq; 4 | using System.Text; 5 | using System.Threading.Tasks; 6 | using System.Windows; 7 | using System.Windows.Controls; 8 | using System.Windows.Data; 9 | using System.Windows.Documents; 10 | using System.Windows.Input; 11 | using System.Windows.Media; 12 | using System.Windows.Media.Imaging; 13 | using System.Windows.Navigation; 14 | using System.Windows.Shapes; 15 | 16 | namespace RegistryExplorer.Views { 17 | /// 18 | /// Interaction logic for ToolBarView.xaml 19 | /// 20 | public partial class ToolBarView : UserControl { 21 | public ToolBarView() { 22 | InitializeComponent(); 23 | } 24 | } 25 | } 26 | -------------------------------------------------------------------------------- /RegistryExplorer/ViewModels/RegistryItem.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Linq; 4 | using System.Text; 5 | using System.Threading.Tasks; 6 | using Microsoft.Win32; 7 | 8 | namespace RegistryExplorer.ViewModels { 9 | class RegistryKeyItem { 10 | RegistryKey _key, _parent; 11 | string _name; 12 | 13 | public RegistryKeyItem(RegistryKey parent, string name) { 14 | _parent = parent; 15 | _name = name; 16 | } 17 | 18 | public string Text { 19 | get { return _key == null ? _name : _key.Name; } 20 | } 21 | 22 | public string[] SubKeyNames { 23 | get { 24 | if(_key == null) 25 | _key = _parent.OpenSubKey(_name); 26 | return _key.GetSubKeyNames(); 27 | } 28 | } 29 | } 30 | } 31 | -------------------------------------------------------------------------------- /RegistryExplorer/Views/DataGridView.xaml.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Linq; 4 | using System.Text; 5 | using System.Threading.Tasks; 6 | using System.Windows; 7 | using System.Windows.Controls; 8 | using System.Windows.Data; 9 | using System.Windows.Documents; 10 | using System.Windows.Input; 11 | using System.Windows.Media; 12 | using System.Windows.Media.Imaging; 13 | using System.Windows.Navigation; 14 | using System.Windows.Shapes; 15 | 16 | namespace RegistryExplorer.Views { 17 | /// 18 | /// Interaction logic for DataGridView.xaml 19 | /// 20 | public partial class DataGridView : UserControl { 21 | public DataGridView() { 22 | InitializeComponent(); 23 | } 24 | } 25 | } 26 | -------------------------------------------------------------------------------- /RegistryExplorer/Views/RegistryTreeView.xaml.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Linq; 4 | using System.Text; 5 | using System.Threading.Tasks; 6 | using System.Windows; 7 | using System.Windows.Controls; 8 | using System.Windows.Data; 9 | using System.Windows.Documents; 10 | using System.Windows.Input; 11 | using System.Windows.Media; 12 | using System.Windows.Media.Imaging; 13 | using System.Windows.Navigation; 14 | using System.Windows.Shapes; 15 | 16 | namespace RegistryExplorer.Views { 17 | /// 18 | /// Interaction logic for RegistryTreeView.xaml 19 | /// 20 | public partial class RegistryTreeView { 21 | public RegistryTreeView() { 22 | InitializeComponent(); 23 | } 24 | 25 | } 26 | } 27 | -------------------------------------------------------------------------------- /RegistryExplorer/App.config: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | -------------------------------------------------------------------------------- /RegistryExplorer/DialogViewModelBase.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Linq; 4 | using System.Text; 5 | using System.Threading.Tasks; 6 | using System.Windows; 7 | 8 | namespace RegistryExplorer { 9 | abstract class DialogViewModelBase : ViewModelBase { 10 | Window _dialog; 11 | bool? _result; 12 | 13 | public DialogViewModelBase(DependencyObject dialog) { 14 | if(dialog != null) 15 | _dialog = Window.GetWindow(dialog); 16 | } 17 | 18 | public DialogViewModelBase(bool? result) { 19 | _result = result; 20 | } 21 | 22 | protected void Close(bool? result = true) { 23 | if(_dialog != null) { 24 | _dialog.DialogResult = result; 25 | _dialog.Close(); 26 | } 27 | } 28 | 29 | public bool? ShowDialog() { 30 | return _dialog != null ? _dialog.ShowDialog() : _result; 31 | } 32 | } 33 | } 34 | -------------------------------------------------------------------------------- /RegistryExplorer/AppCommand.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Linq; 4 | using System.Text; 5 | using System.Threading.Tasks; 6 | using System.Windows.Input; 7 | using Prism.Commands; 8 | 9 | namespace RegistryExplorer { 10 | public interface IAppCommand { 11 | void Undo(); 12 | void Execute(); 13 | string Description { get; } 14 | } 15 | 16 | class AppCommand : IAppCommand { 17 | T _context; 18 | Action _execute, _undo; 19 | 20 | public string Description { get; set; } 21 | 22 | public AppCommand(T context, Action execute, Action undo = null) { 23 | if(execute == null) 24 | throw new ArgumentNullException(nameof(execute)); 25 | 26 | _context = context; 27 | _execute = execute; 28 | _undo = undo ?? execute; 29 | } 30 | 31 | public void Execute() { 32 | _execute(_context); 33 | } 34 | 35 | public void Undo() { 36 | _undo(_context); 37 | } 38 | } 39 | 40 | } 41 | -------------------------------------------------------------------------------- /RegistryExplorer/ViewModelBase.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Linq; 4 | using System.Text; 5 | using System.Threading.Tasks; 6 | using Prism; 7 | using Prism.Mvvm; 8 | 9 | namespace RegistryExplorer { 10 | class ViewModelBase : BindableBase, IActiveAware { 11 | bool _isActive; 12 | public bool IsActive { 13 | get { 14 | return _isActive; 15 | } 16 | set { 17 | if(SetProperty(ref _isActive, value)) 18 | OnIsActiveChanged(); 19 | } 20 | } 21 | 22 | protected virtual void OnIsActiveChanged() { 23 | var ac = IsActiveChanged; 24 | if(ac != null) 25 | ac(this, EventArgs.Empty); 26 | if(IsActive) 27 | ActiveView = this; 28 | } 29 | 30 | public event EventHandler IsActiveChanged; 31 | 32 | static ViewModelBase _activeView; 33 | 34 | public ViewModelBase ActiveView { 35 | get { return _activeView; } 36 | set { SetProperty(ref _activeView, value); } 37 | } 38 | 39 | } 40 | } 41 | -------------------------------------------------------------------------------- /RegistryExplorer/Serialization/Serializer.cs: -------------------------------------------------------------------------------- 1 | using RegistryExplorer.ViewModels; 2 | using System; 3 | using System.Collections.Generic; 4 | using System.IO; 5 | using System.Linq; 6 | using System.Text; 7 | using System.Threading.Tasks; 8 | 9 | namespace RegistryExplorer.Serialization { 10 | static class Serializer { 11 | public static void SaveKeys(Stream stm, ICollection keys) { 12 | var writer = new BinaryWriter(stm); 13 | writer.Write(keys.Count); 14 | foreach(RegistryKeyItem key in keys) { 15 | writer.Write(key.Root.Name); 16 | writer.Write(key.Path); 17 | } 18 | } 19 | 20 | public static ICollection LoadKeys(Stream stm) { 21 | var reader = new BinaryReader(stm); 22 | int count = reader.ReadInt32(); 23 | var keys = new List(count); 24 | 25 | for(int i = 0; i < count; i++) { 26 | var key = new RegistryKeyItem(reader.ReadString(), reader.ReadString()); 27 | keys.Add(key); 28 | } 29 | return keys; 30 | } 31 | } 32 | } 33 | -------------------------------------------------------------------------------- /RegistryExplorer/Extensions/ImageExtension.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Linq; 4 | using System.Text; 5 | using System.Threading.Tasks; 6 | using System.Windows.Controls; 7 | using System.Windows.Markup; 8 | using System.Windows.Media; 9 | using System.Windows.Media.Imaging; 10 | 11 | namespace RegistryExplorer.Extensions { 12 | [MarkupExtensionReturnType(typeof(Image))] 13 | class ImageExtension : MarkupExtension { 14 | public string Uri { get; set; } 15 | 16 | public double Width { get; set; } = double.NaN; 17 | public double Height { get; set; } = double.NaN; 18 | public Stretch Stretch { get; set; } = Stretch.Uniform; 19 | 20 | public ImageExtension(string uri) { 21 | Uri = uri; 22 | } 23 | 24 | public override object ProvideValue(IServiceProvider serviceProvider) { 25 | return new Image { 26 | Source = new BitmapImage(new Uri(Uri, UriKind.RelativeOrAbsolute)), 27 | Width = Width, 28 | Height = Height, 29 | Stretch = Stretch 30 | }; 31 | } 32 | } 33 | } 34 | -------------------------------------------------------------------------------- /RegistryExplorer/Behaviors/ValueCellTemplateSelector.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Diagnostics; 4 | using System.Linq; 5 | using System.Text; 6 | using System.Threading.Tasks; 7 | using System.Windows; 8 | using System.Windows.Controls; 9 | using Microsoft.Win32; 10 | using RegistryExplorer.ViewModels; 11 | 12 | namespace RegistryExplorer.Behaviors { 13 | class ValueCellTemplateSelector : DataTemplateSelector { 14 | public DataTemplate SingleValueDataTemplate { get; set; } 15 | public override DataTemplate SelectTemplate(object item, DependencyObject container) { 16 | if(item != null) { 17 | var value = item as RegistryValue; 18 | Debug.Assert(value != null); 19 | 20 | switch(value.DataType) { 21 | case RegistryValueKind.DWord: 22 | case RegistryValueKind.QWord: 23 | case RegistryValueKind.String: 24 | case RegistryValueKind.ExpandString: 25 | return SingleValueDataTemplate; 26 | } 27 | } 28 | return base.SelectTemplate(item, container); 29 | } 30 | } 31 | } 32 | -------------------------------------------------------------------------------- /RegistryExplorer.sln: -------------------------------------------------------------------------------- 1 | 2 | Microsoft Visual Studio Solution File, Format Version 12.00 3 | # Visual Studio 15 4 | VisualStudioVersion = 15.0.26403.7 5 | MinimumVisualStudioVersion = 10.0.40219.1 6 | Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "RegistryExplorer", "RegistryExplorer\RegistryExplorer.csproj", "{BEA1DFDC-BB70-49BE-AEE4-73502652C368}" 7 | EndProject 8 | Global 9 | GlobalSection(SolutionConfigurationPlatforms) = preSolution 10 | Debug|Any CPU = Debug|Any CPU 11 | Release|Any CPU = Release|Any CPU 12 | EndGlobalSection 13 | GlobalSection(ProjectConfigurationPlatforms) = postSolution 14 | {BEA1DFDC-BB70-49BE-AEE4-73502652C368}.Debug|Any CPU.ActiveCfg = Debug|Any CPU 15 | {BEA1DFDC-BB70-49BE-AEE4-73502652C368}.Debug|Any CPU.Build.0 = Debug|Any CPU 16 | {BEA1DFDC-BB70-49BE-AEE4-73502652C368}.Release|Any CPU.ActiveCfg = Release|Any CPU 17 | {BEA1DFDC-BB70-49BE-AEE4-73502652C368}.Release|Any CPU.Build.0 = Release|Any CPU 18 | EndGlobalSection 19 | GlobalSection(SolutionProperties) = preSolution 20 | HideSolutionNode = FALSE 21 | EndGlobalSection 22 | EndGlobal 23 | -------------------------------------------------------------------------------- /RegistryExplorer/Behaviors/TextBoxEditingBehavior.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Linq; 4 | using System.Text; 5 | using System.Threading.Tasks; 6 | using System.Windows; 7 | using System.Windows.Controls; 8 | using System.Windows.Input; 9 | using System.Windows.Interactivity; 10 | using System.Windows.Media; 11 | using RegistryExplorer.ViewModels; 12 | 13 | namespace RegistryExplorer.Behaviors { 14 | class TextBoxEditingBehavior : Behavior { 15 | 16 | protected override void OnAttached() { 17 | base.OnAttached(); 18 | 19 | AssociatedObject.IsVisibleChanged += AssociatedObject_IsVisibleChanged; 20 | } 21 | 22 | protected override void OnDetaching() { 23 | 24 | AssociatedObject.IsVisibleChanged -= AssociatedObject_IsVisibleChanged; 25 | 26 | base.OnDetaching(); 27 | } 28 | 29 | private void AssociatedObject_IsVisibleChanged(object sender, DependencyPropertyChangedEventArgs e) { 30 | if((bool)e.NewValue) { 31 | AssociatedObject.SelectAll(); 32 | AssociatedObject.Focus(); 33 | } 34 | } 35 | } 36 | } 37 | -------------------------------------------------------------------------------- /RegistryExplorer/App.xaml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | -------------------------------------------------------------------------------- /RegistryExplorer/ViewModels/ToolBarViewModel.cs: -------------------------------------------------------------------------------- 1 | using Microsoft.Win32; 2 | using Prism.Commands; 3 | using Prism.Mvvm; 4 | using System; 5 | using System.Collections.Generic; 6 | using System.Linq; 7 | using System.Text; 8 | using System.Threading.Tasks; 9 | using System.Windows.Input; 10 | 11 | namespace RegistryExplorer.ViewModels { 12 | 13 | class ToolBarViewModel : BindableBase { 14 | public MainViewModel MainViewModel { get; } 15 | 16 | public ToolBarViewModel(MainViewModel vm) { 17 | MainViewModel = vm; 18 | } 19 | 20 | public IEnumerable NewValueTypes { 21 | get { 22 | yield return new ValueViewModel { Text = "DWORD", Type = RegistryValueKind.DWord }; 23 | yield return new ValueViewModel { Text = "QWORD", Type = RegistryValueKind.QWord }; 24 | yield return new ValueViewModel { Text = "String", Type = RegistryValueKind.String}; 25 | yield return new ValueViewModel { Text = "Expand String", Type = RegistryValueKind.ExpandString }; 26 | yield return new ValueViewModel { Text = "Multi String", Type = RegistryValueKind.MultiString}; 27 | yield return new ValueViewModel { Text = "Binary", Type = RegistryValueKind.Binary }; 28 | } 29 | } 30 | } 31 | } 32 | -------------------------------------------------------------------------------- /RegistryExplorer/Properties/Settings.Designer.cs: -------------------------------------------------------------------------------- 1 | //------------------------------------------------------------------------------ 2 | // 3 | // This code was generated by a tool. 4 | // Runtime Version:4.0.30319.42000 5 | // 6 | // Changes to this file may cause incorrect behavior and will be lost if 7 | // the code is regenerated. 8 | // 9 | //------------------------------------------------------------------------------ 10 | 11 | namespace RegistryExplorer.Properties { 12 | 13 | 14 | [global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()] 15 | [global::System.CodeDom.Compiler.GeneratedCodeAttribute("Microsoft.VisualStudio.Editors.SettingsDesigner.SettingsSingleFileGenerator", "14.0.0.0")] 16 | internal sealed partial class Settings : global::System.Configuration.ApplicationSettingsBase { 17 | 18 | private static Settings defaultInstance = ((Settings)(global::System.Configuration.ApplicationSettingsBase.Synchronized(new Settings()))); 19 | 20 | public static Settings Default { 21 | get { 22 | return defaultInstance; 23 | } 24 | } 25 | } 26 | } 27 | -------------------------------------------------------------------------------- /RegistryExplorer/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.Threading.Tasks; 7 | using System.Windows; 8 | using RegistryExplorer.ViewModels; 9 | using MahApps.Metro; 10 | using Prism.Mvvm; 11 | using MahApps.Metro.Controls.Dialogs; 12 | 13 | namespace RegistryExplorer { 14 | /// 15 | /// Interaction logic for App.xaml 16 | /// 17 | public partial class App : Application { 18 | internal static readonly string Name = "Registry Explorer"; 19 | 20 | internal static MainViewModel MainViewModel; 21 | 22 | public App() { 23 | ViewModelLocationProvider.SetDefaultViewTypeToViewModelTypeResolver(view => Type.GetType(view.FullName.Replace("View", "ViewModel"))); 24 | } 25 | 26 | protected override void OnStartup(StartupEventArgs e) { 27 | MainViewModel = new MainViewModel(DialogCoordinator.Instance); 28 | 29 | var win = new MainWindow() { 30 | DataContext = MainViewModel 31 | }; 32 | win.Show(); 33 | } 34 | 35 | protected override void OnExit(ExitEventArgs e) { 36 | base.OnExit(e); 37 | 38 | NativeMethods.Dispose(); 39 | } 40 | } 41 | } 42 | -------------------------------------------------------------------------------- /RegistryExplorer/ViewModels/MenuBarViewModel.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Linq; 4 | using System.Text; 5 | using System.Threading.Tasks; 6 | using Prism.Commands; 7 | using Prism.Mvvm; 8 | using MahApps.Metro; 9 | using System.Windows; 10 | using Zodiacon.WPF; 11 | 12 | namespace RegistryExplorer.ViewModels { 13 | class MenuBarViewModel : BindableBase, IDisposable { 14 | public MainViewModel MainViewModel { get; } 15 | PropertyFollower _follower; 16 | 17 | public MenuBarViewModel(MainViewModel vm) { 18 | MainViewModel = vm; 19 | _follower = PropertyFollower.Create(MainViewModel, this, nameof(ViewModels.MainViewModel.IsReadOnlyMode)); 20 | 21 | ChangeAccentCommand = new DelegateCommand(accent => { 22 | ThemeManager.ChangeAppStyle(Application.Current, accent.Accent, ThemeManager.DetectAppStyle().Item1); 23 | }); 24 | 25 | } 26 | 27 | public DelegateCommandBase ExitCommand { 28 | get { return MainViewModel.ExitCommand; } 29 | } 30 | 31 | public void Dispose() { 32 | _follower.Dispose(); 33 | } 34 | 35 | public DelegateCommandBase ChangeAccentCommand { get; } 36 | 37 | public IEnumerable Accents => ThemeManager.Accents.Select(accent => new AccentViewModel(accent)).ToArray(); 38 | 39 | } 40 | } 41 | -------------------------------------------------------------------------------- /RegistryExplorer/Converters/DataTypeToImageConverter.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Linq; 4 | using System.Text; 5 | using System.Threading.Tasks; 6 | using System.Windows.Data; 7 | using Microsoft.Win32; 8 | 9 | namespace RegistryExplorer.Converters { 10 | class DataTypeToImageConverter : IValueConverter { 11 | Dictionary _images = new Dictionary { 12 | { RegistryValueKind.Binary, "/images/DataTypes/reg_binary.png" }, 13 | { RegistryValueKind.String, "/images/DataTypes/reg_string.png" }, 14 | { RegistryValueKind.MultiString, "/images/DataTypes/reg_string.png" }, 15 | { RegistryValueKind.DWord, "/images/DataTypes/reg_binary.png" }, 16 | { RegistryValueKind.QWord, "/images/DataTypes/reg_binary.png" }, 17 | { RegistryValueKind.ExpandString, "/images/DataTypes/reg_string.png" }, 18 | { RegistryValueKind.None, "/images/DataTypes/empty.png" } 19 | }; 20 | 21 | public object Convert(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture) { 22 | var type = (RegistryValueKind)value; 23 | string image; 24 | if(_images.TryGetValue(type, out image)) 25 | return image; 26 | return null; 27 | } 28 | 29 | public object ConvertBack(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture) { 30 | throw new NotImplementedException(); 31 | } 32 | } 33 | } 34 | -------------------------------------------------------------------------------- /RegistryExplorer/Behaviors/SelectedTreeViewItemBehavior.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Diagnostics; 4 | using System.Linq; 5 | using System.Text; 6 | using System.Threading.Tasks; 7 | using System.Windows; 8 | using System.Windows.Controls; 9 | using System.Windows.Documents; 10 | using System.Windows.Interactivity; 11 | using RegistryExplorer.ViewModels; 12 | 13 | namespace RegistryExplorer.Behaviors { 14 | class SelectedTreeViewItemBehavior : Behavior { 15 | protected override void OnAttached() { 16 | base.OnAttached(); 17 | 18 | AssociatedObject.SelectedItemChanged += AssociatedObject_SelectedItemChanged; 19 | 20 | } 21 | 22 | 23 | protected override void OnDetaching() { 24 | AssociatedObject.SelectedItemChanged -= AssociatedObject_SelectedItemChanged; 25 | base.OnDetaching(); 26 | } 27 | 28 | void AssociatedObject_SelectedItemChanged(object sender, System.Windows.RoutedPropertyChangedEventArgs e) { 29 | Debug.Assert(e.NewValue is RegistryKeyItemBase); 30 | SelectedItem = (RegistryKeyItemBase)e.NewValue; 31 | } 32 | 33 | public RegistryKeyItemBase SelectedItem { 34 | get { return (RegistryKeyItemBase)GetValue(SelectedItemProperty); } 35 | set { SetValue(SelectedItemProperty, value); } 36 | } 37 | 38 | public static readonly DependencyProperty SelectedItemProperty = 39 | DependencyProperty.Register(nameof(SelectedItem), typeof(RegistryKeyItemBase), typeof(SelectedTreeViewItemBehavior), new FrameworkPropertyMetadata(null, 40 | FrameworkPropertyMetadataOptions.BindsTwoWayByDefault | FrameworkPropertyMetadataOptions.AffectsRender)); 41 | 42 | } 43 | } 44 | -------------------------------------------------------------------------------- /RegistryExplorer/Behaviors/ActiveViewBehavior.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Linq; 4 | using System.Text; 5 | using System.Threading.Tasks; 6 | using System.Windows; 7 | using System.Windows.Interactivity; 8 | using System.Windows.Media; 9 | using Prism; 10 | 11 | namespace RegistryExplorer.Behaviors { 12 | class ActiveViewBehavior : Behavior { 13 | protected override void OnAttached() { 14 | base.OnAttached(); 15 | 16 | AssociatedObject.PreviewGotKeyboardFocus += AssociatedObject_PreviewGotKeyboardFocus; 17 | AssociatedObject.PreviewLostKeyboardFocus += AssociatedObject_PreviewLostKeyboardFocus; 18 | } 19 | 20 | private void AssociatedObject_PreviewLostKeyboardFocus(object sender, System.Windows.Input.KeyboardFocusChangedEventArgs e) { 21 | var ctx = AssociatedObject.DataContext as IActiveAware; 22 | if(ctx != null && ctx.IsActive && e.NewFocus != null && !((FrameworkElement)e.NewFocus).IsChildOf(AssociatedObject)) 23 | ctx.IsActive = false; 24 | } 25 | 26 | protected override void OnDetaching() { 27 | AssociatedObject.PreviewGotKeyboardFocus -= AssociatedObject_PreviewGotKeyboardFocus; 28 | AssociatedObject.PreviewLostKeyboardFocus -= AssociatedObject_PreviewLostKeyboardFocus; 29 | 30 | base.OnDetaching(); 31 | } 32 | 33 | private void AssociatedObject_PreviewGotKeyboardFocus(object sender, System.Windows.Input.KeyboardFocusChangedEventArgs e) { 34 | var ctx = AssociatedObject.DataContext as IActiveAware; 35 | if(ctx != null && !ctx.IsActive && e.OldFocus != null && !((FrameworkElement)e.OldFocus).IsChildOf(AssociatedObject)) 36 | ctx.IsActive = true; 37 | } 38 | } 39 | } 40 | -------------------------------------------------------------------------------- /RegistryExplorer/ViewModels/Dialogs/LoadHiveViewModel.cs: -------------------------------------------------------------------------------- 1 | using Microsoft.Win32; 2 | using Prism.Commands; 3 | using System; 4 | using System.Collections.Generic; 5 | using System.Linq; 6 | using System.Text; 7 | using System.Threading.Tasks; 8 | using System.Windows; 9 | 10 | namespace RegistryExplorer.ViewModels.Dialogs { 11 | class LoadHiveViewModel : DialogViewModelBase { 12 | public DelegateCommandBase BrowseCommand { get; } 13 | public DelegateCommandBase LoadCommand { get; } 14 | 15 | public LoadHiveViewModel(DependencyObject dialog) : base(dialog) { 16 | BrowseCommand = new DelegateCommand(() => { 17 | var dlg = new OpenFileDialog { 18 | Title = "Select File", 19 | CheckFileExists = true, 20 | Filter = "Registry Hive Files|*.dat;." 21 | }; 22 | if(dlg.ShowDialog() == true) { 23 | FileName = dlg.FileName; 24 | } 25 | 26 | }); 27 | 28 | LoadCommand = new DelegateCommand(() => Close(true), () => !string.IsNullOrWhiteSpace(Name) && !string.IsNullOrWhiteSpace(FileName)) 29 | .ObservesProperty(() => Name).ObservesProperty(() => FileName); 30 | } 31 | 32 | private string _fileName; 33 | 34 | public string FileName { 35 | get { return _fileName; } 36 | set { SetProperty(ref _fileName, value); } 37 | } 38 | 39 | public IEnumerable LoadHives { 40 | get { 41 | yield return "HKEY_LOCAL_MACHINE"; 42 | yield return "HKEY_USERS"; 43 | } 44 | } 45 | 46 | private int _selectedHive; 47 | 48 | public int SelectedHive { 49 | get { return _selectedHive; } 50 | set { SetProperty(ref _selectedHive, value); } 51 | } 52 | 53 | private string _name; 54 | 55 | public string Name { 56 | get { return _name; } 57 | set { SetProperty(ref _name, value); } 58 | } 59 | 60 | public string Hive => SelectedHive == 0 ? "HKLM" : "HKU"; 61 | 62 | } 63 | } 64 | -------------------------------------------------------------------------------- /RegistryExplorer/ViewModels/RegistryKeyItemBase.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Collections.ObjectModel; 4 | using System.Linq; 5 | using System.Text; 6 | using System.Threading.Tasks; 7 | using Prism.Mvvm; 8 | using System.Diagnostics; 9 | using System.Windows; 10 | 11 | namespace RegistryExplorer.ViewModels { 12 | [Flags] 13 | enum RegistryKeyFlags { 14 | Favorite = 1, 15 | } 16 | 17 | abstract class RegistryKeyItemBase : BindableBase { 18 | private string _text; 19 | protected ObservableCollection _subItems; 20 | 21 | public string Path { get; protected set; } 22 | 23 | public RegistryKeyFlags Flags { get; set; } 24 | 25 | public RegistryKeyItemBase Parent { get; private set; } 26 | 27 | public virtual ObservableCollection SubItems { 28 | get { 29 | if(_subItems == null) 30 | _subItems = new ObservableCollection(); 31 | return _subItems; 32 | } 33 | } 34 | 35 | protected RegistryKeyItemBase(RegistryKeyItemBase parent) { 36 | Parent = parent; 37 | } 38 | 39 | public string TypeName => GetType().Name; 40 | 41 | public virtual void Refresh() { } 42 | 43 | public string Text { 44 | get { return _text; } 45 | set { SetProperty(ref _text, value); } 46 | } 47 | 48 | private bool _isExpanded; 49 | 50 | public bool IsExpanded { 51 | get { return _isExpanded; } 52 | set { SetProperty(ref _isExpanded, value); } 53 | } 54 | 55 | private bool _isSelected; 56 | 57 | public bool IsSelected { 58 | get { return _isSelected; } 59 | set { SetProperty(ref _isSelected, value); } 60 | } 61 | 62 | public T GetSubItem(string name) where T : RegistryKeyItemBase { 63 | return SubItems.FirstOrDefault(i => i.Text.Equals(name, StringComparison.InvariantCultureIgnoreCase)) as T; 64 | } 65 | 66 | public override string ToString() { 67 | return _text.ToString(); 68 | } 69 | } 70 | } 71 | -------------------------------------------------------------------------------- /RegistryExplorer/ViewModels/DataGridViewModel.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Linq; 4 | using System.Text; 5 | using System.Threading.Tasks; 6 | using System.Windows.Data; 7 | using Prism.Commands; 8 | using Prism.Mvvm; 9 | using Zodiacon.WPF; 10 | 11 | namespace RegistryExplorer.ViewModels { 12 | class DataGridViewModel : ViewModelBase, IDisposable { 13 | public MainViewModel MainViewModel { get; } 14 | PropertyFollower _follower; 15 | 16 | public DelegateCommand ClearFilterCommand { get; } 17 | 18 | public DataGridViewModel() { 19 | MainViewModel = App.MainViewModel; 20 | 21 | _follower = new PropertyFollower(MainViewModel, this, nameof(IsReadOnlyMode)); 22 | _follower.Add(nameof(MainViewModel.SelectedItem), _ => { 23 | FilterText = string.Empty; 24 | RaisePropertyChanged(nameof(Values)); 25 | }); 26 | 27 | ClearFilterCommand = new DelegateCommand(() => FilterText = string.Empty); 28 | } 29 | 30 | IEnumerable _values; 31 | 32 | public IEnumerable Values { 33 | get { 34 | var regItem = MainViewModel.SelectedItem as RegistryKeyItem; 35 | return (_values = (regItem != null ? regItem.Values : null)); 36 | } 37 | } 38 | 39 | public bool IsReadOnlyMode { 40 | get { return MainViewModel.IsReadOnlyMode; } 41 | } 42 | 43 | public void Refresh() { 44 | RaisePropertyChanged(nameof(Values)); 45 | } 46 | 47 | private string _filterText; 48 | 49 | public string FilterText { 50 | get { return _filterText; } 51 | set { 52 | if(SetProperty(ref _filterText, value)) { 53 | if(_values != null && string.IsNullOrEmpty(value)) { 54 | CollectionViewSource.GetDefaultView(_values).Filter = null; 55 | } 56 | else if(_values != null) { 57 | CollectionViewSource.GetDefaultView(_values).Filter = obj => { 58 | var theValue = (RegistryValue)obj; 59 | var lvalue = value.ToLower(); 60 | return theValue.Name.ToLower().Contains(lvalue) || theValue.ValueAsString.ToLower().Contains(lvalue); 61 | }; 62 | } 63 | } 64 | } 65 | } 66 | 67 | public void Dispose() { 68 | _follower.Dispose(); 69 | } 70 | 71 | protected override void OnIsActiveChanged() { 72 | base.OnIsActiveChanged(); 73 | 74 | if(IsActive) 75 | ActiveView = this; 76 | } 77 | } 78 | } 79 | -------------------------------------------------------------------------------- /RegistryExplorer/Properties/AssemblyInfo.cs: -------------------------------------------------------------------------------- 1 | using System.Reflection; 2 | using System.Resources; 3 | using System.Runtime.CompilerServices; 4 | using System.Runtime.InteropServices; 5 | using System.Windows; 6 | 7 | // General Information about an assembly is controlled through the following 8 | // set of attributes. Change these attribute values to modify the information 9 | // associated with an assembly. 10 | [assembly: AssemblyTitle("RegistryExplorer")] 11 | [assembly: AssemblyDescription("")] 12 | [assembly: AssemblyConfiguration("")] 13 | [assembly: AssemblyCompany("Wanova")] 14 | [assembly: AssemblyProduct("RegistryExplorer")] 15 | [assembly: AssemblyCopyright("Copyright © Wanova 2015")] 16 | [assembly: AssemblyTrademark("")] 17 | [assembly: AssemblyCulture("")] 18 | 19 | // Setting ComVisible to false makes the types in this assembly not visible 20 | // to COM components. If you need to access a type in this assembly from 21 | // COM, set the ComVisible attribute to true on that type. 22 | [assembly: ComVisible(false)] 23 | 24 | //In order to begin building localizable applications, set 25 | //CultureYouAreCodingWith in your .csproj file 26 | //inside a . For example, if you are using US english 27 | //in your source files, set the to en-US. Then uncomment 28 | //the NeutralResourceLanguage attribute below. Update the "en-US" in 29 | //the line below to match the UICulture setting in the project file. 30 | 31 | //[assembly: NeutralResourcesLanguage("en-US", UltimateResourceFallbackLocation.Satellite)] 32 | 33 | 34 | [assembly: ThemeInfo( 35 | ResourceDictionaryLocation.None, //where theme specific resource dictionaries are located 36 | //(used if a resource is not found in the page, 37 | // or application resource dictionaries) 38 | ResourceDictionaryLocation.SourceAssembly //where the generic resource dictionary is located 39 | //(used if a resource is not found in the page, 40 | // app, or any theme specific resource dictionaries) 41 | )] 42 | 43 | 44 | // Version information for an assembly consists of the following four values: 45 | // 46 | // Major Version 47 | // Minor Version 48 | // Build Number 49 | // Revision 50 | // 51 | // You can specify all the values or you can default the Build and Revision Numbers 52 | // by using the '*' as shown below: 53 | // [assembly: AssemblyVersion("1.0.*")] 54 | [assembly: AssemblyVersion("1.0.0.0")] 55 | [assembly: AssemblyFileVersion("1.0.0.0")] 56 | -------------------------------------------------------------------------------- /RegistryExplorer/CommandManager.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Linq; 4 | using System.Text; 5 | using System.Threading.Tasks; 6 | using Prism.Mvvm; 7 | 8 | namespace RegistryExplorer { 9 | class CommandManager : BindableBase { 10 | public int UndoLevel { get; private set; } 11 | List _undoList; 12 | List _redoList; 13 | 14 | public CommandManager(int undoLevel = 32) { 15 | if(undoLevel < 1) 16 | throw new ArgumentException("Undo level must be at least 1"); 17 | UndoLevel = undoLevel; 18 | 19 | _undoList = new List(UndoLevel); 20 | _redoList = new List(UndoLevel); 21 | } 22 | 23 | public void AddCommand(IAppCommand command, bool execute = true) { 24 | if(execute) 25 | command.Execute(); 26 | _undoList.Add(command); 27 | _redoList.Clear(); 28 | if(UndoLevel > 0 && _undoList.Count > UndoLevel) 29 | _undoList.RemoveAt(0); 30 | UpdateChanges(); 31 | } 32 | 33 | public bool CanUndo { 34 | get { 35 | return _undoList.Count > 0; 36 | } 37 | } 38 | 39 | public bool CanRedo { 40 | get { 41 | return _redoList.Count > 0; 42 | } 43 | } 44 | 45 | public string UndoDescription { 46 | get { 47 | return CanUndo ? _undoList[_undoList.Count - 1].Description : string.Empty; 48 | } 49 | } 50 | 51 | public string RedoDescription { 52 | get { 53 | return CanRedo ? _redoList[_redoList.Count - 1].Description : string.Empty; 54 | } 55 | } 56 | 57 | public virtual void Undo() { 58 | if(!CanUndo) 59 | throw new InvalidOperationException("can't undo"); 60 | int index = _undoList.Count - 1; 61 | _undoList[index].Undo(); 62 | _redoList.Add(_undoList[index]); 63 | _undoList.RemoveAt(index); 64 | UpdateChanges(); 65 | } 66 | 67 | public void UpdateChanges() { 68 | RaisePropertyChanged(nameof(CanUndo)); 69 | RaisePropertyChanged(nameof(CanRedo)); 70 | RaisePropertyChanged(nameof(UndoDescription)); 71 | RaisePropertyChanged(nameof(RedoDescription)); 72 | 73 | } 74 | 75 | public virtual void Redo() { 76 | if(!CanRedo) 77 | throw new InvalidOperationException("Can't redo"); 78 | var cmd = _redoList[_redoList.Count - 1]; 79 | cmd.Execute(); 80 | _redoList.RemoveAt(_redoList.Count - 1); 81 | _undoList.Add(cmd); 82 | UpdateChanges(); 83 | } 84 | 85 | public void Clear() { 86 | _undoList.Clear(); 87 | _redoList.Clear(); 88 | UpdateChanges(); 89 | } 90 | } 91 | } 92 | -------------------------------------------------------------------------------- /RegistryExplorer/Views/Dialogs/LoadHiveView.xaml: -------------------------------------------------------------------------------- 1 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 32 | 35 | 36 | 42 | 43 | 44 | 45 | 46 | 47 | 48 | 49 | 50 | 56 | 57 | 59 | 60 | 64 | 65 | 66 | 71 | 72 | 73 | 74 | -------------------------------------------------------------------------------- /RegistryExplorer/NativeMethods.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Linq; 4 | using System.Runtime.ConstrainedExecution; 5 | using System.Runtime.InteropServices; 6 | using System.Text; 7 | using System.Threading.Tasks; 8 | using Microsoft.Win32; 9 | using Microsoft.Win32.SafeHandles; 10 | 11 | namespace RegistryExplorer { 12 | [Flags] 13 | enum RegistryKeyPermissions { 14 | KEY_ALL_ACCESS = 0xF003F, 15 | KEY_READ = 0x20019, 16 | KEY_CREATE_SUB_KEY = 0x0004, 17 | KEY_ENUMERATE_SUB_KEYS = 0x0008, 18 | KEY_WRITE = 0x20006, 19 | KEY_SET_VALUE = 0x0002 20 | 21 | } 22 | 23 | [Flags] 24 | public enum SHGSI : uint { 25 | SHGSI_ICONLOCATION = 0, 26 | SHGSI_ICON = 0x000000100, 27 | SHGSI_SYSICONINDEX = 0x000004000, 28 | SHGSI_LINKOVERLAY = 0x000008000, 29 | SHGSI_SELECTED = 0x000010000, 30 | SHGSI_LARGEICON = 0x000000000, 31 | SHGSI_SMALLICON = 0x000000001, 32 | SHGSI_SHELLICONSIZE = 0x000000004 33 | } 34 | 35 | [StructLayoutAttribute(LayoutKind.Sequential, CharSet = CharSet.Unicode)] 36 | public struct SHSTOCKICONINFO { 37 | public uint cbSize; 38 | public IntPtr hIcon; 39 | public int iSysIconIndex; 40 | public int iIcon; 41 | [MarshalAs(UnmanagedType.ByValTStr, SizeConst = 260)] 42 | public string szPath; 43 | } 44 | 45 | static class NativeMethods { 46 | [DllImport("Shell32", SetLastError = false)] 47 | public static extern Int32 SHGetStockIconInfo(int siid, SHGSI uFlags, ref SHSTOCKICONINFO psii); 48 | 49 | [DllImport("user32")] 50 | public static extern bool DestroyIcon(IntPtr hIcon); 51 | 52 | [DllImport("advapi32", CharSet = CharSet.Unicode, EntryPoint = "RegLoadKeyW", ExactSpelling = true)] 53 | public static extern int RegLoadKey(SafeRegistryHandle hKey, [MarshalAs(UnmanagedType.LPWStr)] string subKey, [MarshalAs(UnmanagedType.LPWStr)] string file); 54 | 55 | [DllImport("advapi32", CharSet = CharSet.Unicode, EntryPoint = "RegUnLoadKeyW", ExactSpelling = true)] 56 | public static extern int RegUnLoadKey(SafeRegistryHandle hKey, [MarshalAs(UnmanagedType.LPWStr)] string subKey); 57 | 58 | [DllImport("advapi32")] 59 | public static extern int RegLoadAppKey(string file, out SafeRegistryHandle hKey, RegistryKeyPermissions samDesired, uint options, uint reserved); 60 | 61 | [DllImport("advapi32")] 62 | public static extern int RegRenameKey(SafeRegistryHandle hKey, [MarshalAs(UnmanagedType.LPWStr)] string oldname, [MarshalAs(UnmanagedType.LPWStr)] string newname); 63 | 64 | [DllImport("advapi32", CharSet = CharSet.Unicode, EntryPoint ="RegCopyTreeW")] 65 | public static extern int RegCopyTree(SafeRegistryHandle hSourceKey, [MarshalAs(UnmanagedType.LPWStr)] string subKey, SafeRegistryHandle hTarget); 66 | 67 | [DllImport("advapi32", CharSet = CharSet.Unicode, EntryPoint = "RegSaveKeyExW")] 68 | public static extern int RegSaveKeyEx(SafeRegistryHandle hKey, [MarshalAs(UnmanagedType.LPWStr)] string filename, IntPtr secDesc, uint format = 1); 69 | 70 | [DllImport("advapi32", CharSet = CharSet.Unicode, EntryPoint = "RegSaveKeyW")] 71 | public static extern int RegSaveKey(SafeRegistryHandle hKey, [MarshalAs(UnmanagedType.LPWStr)] string filename, IntPtr secAttributes); 72 | 73 | [DllImport("advapi32", CharSet = CharSet.Unicode, EntryPoint = "RegRestoreKeyW", ExactSpelling = true)] 74 | public static extern int RegRestoreKey(SafeRegistryHandle hKey, [MarshalAs(UnmanagedType.LPWStr)] string filename, uint flags = 8); 75 | 76 | static Dictionary _privileges = new Dictionary(); 77 | 78 | public static void EnablePrivilege(string name) { 79 | object privilege; 80 | if(!_privileges.TryGetValue(name, out privilege)) { 81 | Type privilegeType = Type.GetType("System.Security.AccessControl.Privilege"); 82 | privilege = Activator.CreateInstance(privilegeType, name); 83 | _privileges.Add(name, privilege); 84 | } 85 | privilege.GetType().GetMethod("Enable").Invoke(privilege, null); 86 | } 87 | 88 | 89 | public static void DisablePrivilege(string name) { 90 | object privilege = _privileges[name]; 91 | privilege.GetType().GetMethod("Revert").Invoke(privilege, null); 92 | } 93 | 94 | [DllImport("user32")] 95 | public static extern bool MessageBeep(uint type); 96 | 97 | internal static void Dispose() { 98 | foreach(var p in _privileges.Keys) 99 | DisablePrivilege(p); 100 | 101 | } 102 | } 103 | } 104 | -------------------------------------------------------------------------------- /RegistryExplorer/Views/MenuBarView.xaml: -------------------------------------------------------------------------------- 1 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | 44 | 45 | 46 | 47 | 48 | 49 | 50 | 51 | 52 | 53 | 54 | 55 | 56 | 57 | 58 | 59 | 60 | 61 | 62 | 63 | 64 | 65 | 66 | 67 | 68 | 72 | 73 | 74 | 75 | 76 | 77 | 78 | 79 | 80 | 81 | 82 | 83 | 84 | 85 | 86 | 87 | 88 | 89 | 90 | -------------------------------------------------------------------------------- /RegistryExplorer/ViewModels/RegistryKeyItem.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Collections.ObjectModel; 4 | using System.ComponentModel; 5 | using System.IO; 6 | using System.Linq; 7 | using System.Security; 8 | using System.Text; 9 | using System.Threading.Tasks; 10 | using Microsoft.Win32; 11 | using Prism.Commands; 12 | 13 | namespace RegistryExplorer.ViewModels { 14 | class RegistryKeyItem : RegistryKeyItemBase { 15 | RegistryKey _root; 16 | 17 | public RegistryKeyItem(RegistryKeyItem parent, string text) : base(parent) { 18 | _root = parent.Root; 19 | Text = text; 20 | Path = string.Concat(parent.Path, parent.Path != null ? "\\" : string.Empty, text); 21 | } 22 | 23 | public RegistryKeyItem(string rootName, string path) : base(null) { 24 | switch(rootName) { 25 | case "HKEY_LOCAL_MACHINE": _root = Registry.LocalMachine; break; 26 | case "HKEY_CURRENT_USER": _root = Registry.CurrentUser; break; 27 | case "HKEY_USERS": _root = Registry.Users; break; 28 | case "HKEY_CLASSES_ROOT": _root = Registry.ClassesRoot; break; 29 | case "HKEY_CURRENT_CONFIG": _root = Registry.CurrentConfig; break; 30 | } 31 | Path = path; 32 | int index = path.LastIndexOf('\\'); 33 | Text = index < 0 ? path : path.Substring(index + 1); 34 | } 35 | 36 | public RegistryKeyItem(RegistryKeyItemBase parent, RegistryKey root) : base(parent) { 37 | _root = root; 38 | Text = root.Name; 39 | } 40 | 41 | public RegistryKey Root => _root; 42 | 43 | private bool _hiveKey; 44 | 45 | public bool HiveKey { 46 | get { return _hiveKey; } 47 | set { SetProperty(ref _hiveKey, value); } 48 | } 49 | 50 | public override ObservableCollection SubItems { 51 | get { 52 | if(_subItems == null) { 53 | RegistryKey key = null; 54 | string[] names; 55 | if(Path != null) { 56 | key = TryOpenSubKey(_root, Path); 57 | if(key == null) 58 | return null; 59 | names = TryGetSubKeyNames(key); 60 | if(names == null) 61 | return null; 62 | } 63 | else 64 | names = _root.GetSubKeyNames(); 65 | var items = names.OrderBy(n => n).Select(name => new RegistryKeyItem(this, name)); 66 | if(key != null) 67 | key.Dispose(); 68 | _subItems = new ObservableCollection(items); 69 | } 70 | return _subItems; 71 | } 72 | } 73 | 74 | public void DeleteKey(string name) { 75 | using(var key = _root.OpenSubKey(Path, true)) 76 | key.DeleteSubKeyTree(name); 77 | SubItems.Remove(SubItems.First(i => i.Text == name)); 78 | } 79 | 80 | private string[] TryGetSubKeyNames(RegistryKey key) { 81 | try { 82 | return key.GetSubKeyNames(); 83 | } 84 | catch(IOException) { 85 | return null; 86 | } 87 | } 88 | 89 | private RegistryKey TryOpenSubKey(RegistryKey key, string name) { 90 | try { 91 | return key.OpenSubKey(name); 92 | } 93 | catch(SecurityException) { 94 | return null; 95 | } 96 | } 97 | 98 | public RegistryValue[] Values { 99 | get { 100 | if(string.IsNullOrEmpty(Path)) 101 | return null; 102 | 103 | using(var key = TryOpenSubKey(_root, Path)) { 104 | if(key == null) 105 | return null; 106 | 107 | IEnumerable values = key.GetValueNames().OrderBy(name => name); 108 | var defaultMissing = !values.Any() || !string.IsNullOrEmpty(values.First()); 109 | var pvalues = values.Select(name => new RegistryValue(this) { 110 | Name = string.IsNullOrEmpty(name) ? "(Default)" : name, 111 | Value = key.GetValue(name), 112 | DataType = key.GetValueKind(name) 113 | }); 114 | if(defaultMissing) 115 | pvalues = Enumerable.Repeat(new RegistryValue(this) { 116 | Name = "(Default)", 117 | DataType = RegistryValueKind.None 118 | }, 1).Concat(pvalues); 119 | return pvalues.ToArray(); 120 | } 121 | } 122 | } 123 | 124 | public override void Refresh() { 125 | _subItems = null; 126 | RaisePropertyChanged(nameof(SubItems)); 127 | } 128 | 129 | public void SetValueName(string oldname, string newname) { 130 | using(var key = TryOpenSubKey(_root, Path)) { 131 | if(key == null) 132 | return; 133 | key.SetValue(newname, key.GetValue(oldname)); 134 | key.DeleteValue(oldname); 135 | } 136 | } 137 | 138 | public RegistryKeyItem CreateNewKey(string name) { 139 | 140 | using(var key = _root.CreateSubKey(string.Format("{0}\\{1}", Path, name))) { 141 | var newitem = new RegistryKeyItem(this, name); 142 | SubItems.Add(newitem); 143 | return newitem; 144 | } 145 | 146 | } 147 | 148 | public string GenerateUniqueSubKeyName() { 149 | int i = 1; 150 | 151 | for(;;) { 152 | string name = string.Format("NewKey{0}", i); 153 | if(!SubItems.Any(si => si.Text.Equals(name, StringComparison.InvariantCultureIgnoreCase))) 154 | return name; 155 | ++i; 156 | } 157 | } 158 | 159 | 160 | public override bool Equals(object obj) { 161 | var other = obj as RegistryKeyItem; 162 | if(other == null) return false; 163 | 164 | return _root.Name == other.Root.Name && Path == other.Path; 165 | } 166 | 167 | public override int GetHashCode() { 168 | return _root.Name.GetHashCode() ^ (Path != null ? Path.GetHashCode() : 0); 169 | } 170 | 171 | public void RenameKey(string oldname, string newname) { 172 | using(var key = _root.OpenSubKey((Parent as RegistryKeyItem).Path, true)) { 173 | int error = NativeMethods.RegRenameKey(key.Handle, oldname, newname); 174 | if(error != 0) 175 | throw new Win32Exception(error); 176 | } 177 | } 178 | 179 | //public DelegateCommandBase BeginRenameCommand { get; } = App.MainViewModel.BeginRenameCommand; 180 | } 181 | } 182 | -------------------------------------------------------------------------------- /RegistryExplorer/Properties/Resources.resx: -------------------------------------------------------------------------------- 1 | 2 | 3 | 62 | 63 | 64 | 65 | 66 | 67 | 68 | 69 | 70 | 71 | 72 | 73 | 74 | 75 | 76 | 77 | 78 | 79 | 80 | 81 | 82 | 83 | 84 | 85 | 86 | 87 | 88 | 89 | 90 | 91 | 92 | 93 | 94 | 95 | 96 | 97 | 98 | 99 | 100 | 101 | 102 | 103 | 104 | 105 | 106 | text/microsoft-resx 107 | 108 | 109 | 2.0 110 | 111 | 112 | System.Resources.ResXResourceReader, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 113 | 114 | 115 | System.Resources.ResXResourceWriter, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 116 | 117 | -------------------------------------------------------------------------------- /RegistryExplorer/Behaviors/KeyNavigationTreeViewBehavior.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Diagnostics; 4 | using System.Linq; 5 | using System.Text; 6 | using System.Threading.Tasks; 7 | using System.Windows; 8 | using System.Windows.Controls; 9 | using System.Windows.Input; 10 | using System.Windows.Interactivity; 11 | using System.Windows.Media; 12 | using System.Windows.Threading; 13 | using RegistryExplorer.ViewModels; 14 | 15 | namespace RegistryExplorer.Behaviors { 16 | class KeyNavigationTreeViewBehavior : Behavior { 17 | string _searchterm = string.Empty; 18 | DateTime _lastSearch = DateTime.Now; 19 | DispatcherTimer _timer; 20 | 21 | protected override void OnAttached() { 22 | base.OnAttached(); 23 | 24 | AssociatedObject.KeyUp += AssociatedObject_KeyUp; 25 | AssociatedObject.TextInput += AssociatedObject_TextInput; 26 | 27 | _timer = new DispatcherTimer { Interval = TimeSpan.FromSeconds(.8) }; 28 | _timer.Tick += _timer_Tick; 29 | } 30 | 31 | void _timer_Tick(object sender, EventArgs e) { 32 | _timer.Stop(); 33 | 34 | if(string.IsNullOrEmpty(_searchterm)) 35 | return; 36 | 37 | var item = AssociatedObject.SelectedItem as RegistryKeyItemBase; 38 | if(item == null) return; 39 | 40 | var found = SearchSubTree(item); 41 | if(found != null) { 42 | var tv = GetTreeViewItemFromObject(found); 43 | Debug.Assert(tv != null); 44 | found.IsSelected = true; 45 | } 46 | else { 47 | NativeMethods.MessageBeep(0x30); // short beep 48 | } 49 | 50 | _lastSearch = DateTime.Now; 51 | _searchterm = string.Empty; 52 | } 53 | 54 | void AssociatedObject_TextInput(object sender, TextCompositionEventArgs e) { 55 | _timer.Stop(); 56 | _searchterm += e.Text; 57 | 58 | _timer.Start(); 59 | } 60 | 61 | TreeViewItem GetTreeViewItemFromObject(RegistryKeyItemBase item) { 62 | var indices = new List(4); 63 | while(item.Parent != null) { 64 | indices.Add(item.Parent.SubItems.IndexOf(item)); 65 | item = item.Parent; 66 | } 67 | indices.Add(0); 68 | 69 | // search the tree based on indices 70 | 71 | int index = indices.Count; 72 | var currentTreeView = AssociatedObject.ItemContainerGenerator.ContainerFromIndex(indices[--index]) as TreeViewItem; 73 | Debug.Assert(currentTreeView != null); 74 | while(index > 0) { 75 | var container = currentTreeView; 76 | currentTreeView = currentTreeView.ItemContainerGenerator.ContainerFromIndex(indices[--index]) as TreeViewItem; 77 | if(currentTreeView == null) { // virtualized 78 | GetPanelForTreeViewItem(container).BringIntoView(indices[index]); 79 | currentTreeView = container.ItemContainerGenerator.ContainerFromIndex(indices[index]) as TreeViewItem; 80 | } 81 | Debug.Assert(currentTreeView != null); 82 | } 83 | 84 | return currentTreeView; 85 | } 86 | 87 | VirtualizingStackPanelEx GetPanelForTreeViewItem(TreeViewItem container) { 88 | container.ApplyTemplate(); 89 | ItemsPresenter itemsPresenter = 90 | (ItemsPresenter)container.Template.FindName("ItemsHost", container); 91 | if(itemsPresenter != null) { 92 | itemsPresenter.ApplyTemplate(); 93 | } 94 | else { 95 | // The Tree template has not named the ItemsPresenter, 96 | // so walk the descendants and find the child. 97 | itemsPresenter = TreeViewHelper.FindVisualChild(container); 98 | if(itemsPresenter == null) { 99 | container.UpdateLayout(); 100 | 101 | itemsPresenter = TreeViewHelper.FindVisualChild(container); 102 | } 103 | } 104 | 105 | Panel itemsHostPanel = (Panel)VisualTreeHelper.GetChild(itemsPresenter, 0); 106 | 107 | // Ensure that the generator for this panel has been created. 108 | UIElementCollection children = itemsHostPanel.Children; 109 | 110 | var virtualizingPanel = itemsHostPanel as VirtualizingStackPanelEx; 111 | Debug.Assert(virtualizingPanel != null); 112 | 113 | return virtualizingPanel; 114 | } 115 | 116 | RegistryKeyItemBase BinarySearch(IList items) { 117 | int index1 = 0, index2 = items.Count; 118 | string lower = _searchterm.ToLower(); 119 | 120 | while(index1 != index2) { 121 | int i = (index1 + index2) / 2; 122 | if(items[i].Text.StartsWith(_searchterm, StringComparison.CurrentCultureIgnoreCase)) 123 | return items[i]; 124 | if(items[i].Text.ToLower().CompareTo(lower) > 0) 125 | index2 = i; 126 | else 127 | index1 = i; 128 | } 129 | return null; 130 | } 131 | 132 | private RegistryKeyItemBase SearchSubTree(RegistryKeyItemBase item) { 133 | if(item.IsExpanded && item.SubItems != null) { 134 | foreach(var subItem in item.SubItems) { 135 | if(subItem.Text.StartsWith(_searchterm, StringComparison.CurrentCultureIgnoreCase)) { 136 | return subItem; 137 | } 138 | RegistryKeyItemBase newItem; 139 | if(subItem.IsExpanded && (newItem = SearchSubTree(subItem)) != null) { 140 | return newItem; 141 | } 142 | } 143 | } 144 | if(item.Parent != null) { 145 | foreach(var subItem in item.Parent.SubItems.Skip(item.Parent.SubItems.IndexOf(item) + 1)) { 146 | if(subItem.Text.StartsWith(_searchterm, StringComparison.CurrentCultureIgnoreCase)) { 147 | return subItem; 148 | } 149 | } 150 | 151 | //var index = item.Parent.SubItems.IndexOf(item); 152 | //if(index < item.Parent.SubItems.Count) 153 | // return SearchSubTree(item.Parent.SubItems[index]); 154 | } 155 | return null; 156 | } 157 | 158 | protected override void OnDetaching() { 159 | AssociatedObject.KeyUp -= AssociatedObject_KeyUp; 160 | AssociatedObject.TextInput -= AssociatedObject_TextInput; 161 | 162 | base.OnDetaching(); 163 | } 164 | 165 | void AssociatedObject_KeyUp(object sender, System.Windows.Input.KeyEventArgs e) { 166 | if(e.Key < Key.D0) { 167 | _searchterm = string.Empty; 168 | } 169 | } 170 | 171 | 172 | } 173 | } 174 | -------------------------------------------------------------------------------- /RegistryExplorer/Views/DataGridView.xaml: -------------------------------------------------------------------------------- 1 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 30 | 33 | 34 | 45 | 46 | 47 | 56 | 57 | 58 | 59 | 60 | 61 | 62 | 63 | 64 | 65 | 66 | 67 | 68 | 69 | 70 | 71 | 72 | 73 | 74 | 75 | 76 | 77 | 78 | 79 | 80 | 81 | 82 | 83 | 84 | 85 | 86 | 87 | 88 | 89 | 90 | 91 | 92 | 93 | 94 | 95 | 96 | 97 | 98 | 99 | 100 | 101 | 102 | 103 | 104 | 105 | -------------------------------------------------------------------------------- /.nuget/NuGet.targets: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | $(MSBuildProjectDirectory)\..\ 5 | 6 | 7 | false 8 | 9 | 10 | false 11 | 12 | 13 | true 14 | 15 | 16 | false 17 | 18 | 19 | 20 | 21 | 22 | 26 | 27 | 28 | 29 | 30 | $([System.IO.Path]::Combine($(SolutionDir), ".nuget")) 31 | 32 | 33 | 34 | 35 | $(SolutionDir).nuget 36 | 37 | 38 | 39 | $(MSBuildProjectDirectory)\packages.$(MSBuildProjectName.Replace(' ', '_')).config 40 | $(MSBuildProjectDirectory)\packages.$(MSBuildProjectName).config 41 | 42 | 43 | 44 | $(MSBuildProjectDirectory)\packages.config 45 | $(PackagesProjectConfig) 46 | 47 | 48 | 49 | 50 | $(NuGetToolsPath)\NuGet.exe 51 | @(PackageSource) 52 | 53 | "$(NuGetExePath)" 54 | mono --runtime=v4.0.30319 "$(NuGetExePath)" 55 | 56 | $(TargetDir.Trim('\\')) 57 | 58 | -RequireConsent 59 | -NonInteractive 60 | 61 | "$(SolutionDir) " 62 | "$(SolutionDir)" 63 | 64 | 65 | $(NuGetCommand) install "$(PackagesConfig)" -source "$(PackageSources)" $(NonInteractiveSwitch) $(RequireConsentSwitch) -solutionDir $(PaddedSolutionDir) 66 | $(NuGetCommand) pack "$(ProjectPath)" -Properties "Configuration=$(Configuration);Platform=$(Platform)" $(NonInteractiveSwitch) -OutputDirectory "$(PackageOutputDir)" -symbols 67 | 68 | 69 | 70 | RestorePackages; 71 | $(BuildDependsOn); 72 | 73 | 74 | 75 | 76 | $(BuildDependsOn); 77 | BuildPackage; 78 | 79 | 80 | 81 | 82 | 83 | 84 | 89 | 90 | 91 | 92 | 93 | 94 | 95 | 96 | 97 | 99 | 100 | 103 | 104 | 105 | 106 | 108 | 109 | 112 | 113 | 114 | 115 | 116 | 117 | 118 | 119 | 120 | 121 | 122 | 123 | 124 | 125 | 126 | 141 | 142 | 143 | 144 | 145 | -------------------------------------------------------------------------------- /RegistryExplorer/Views/RegistryTreeView.xaml: -------------------------------------------------------------------------------- 1 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | 44 | 45 | 46 | 47 | 48 | 49 | 50 | 51 | 52 | 53 | 54 | 55 | 56 | 57 | 58 | 59 | 60 | 61 | 62 | 63 | 64 | 65 | 66 | 67 | 68 | 69 | 70 | 71 | 72 | 74 | 75 | 76 | 77 | 78 | 79 | 80 | 81 | 82 | 83 | 84 | 85 | 86 | 87 | 88 | 89 | 138 | 139 | 140 | 141 | 142 | 143 | -------------------------------------------------------------------------------- /RegistryExplorer/RegistryExplorer.csproj: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | Debug 6 | AnyCPU 7 | {BEA1DFDC-BB70-49BE-AEE4-73502652C368} 8 | WinExe 9 | Properties 10 | RegistryExplorer 11 | RegistryExplorer 12 | v4.5.2 13 | 512 14 | {60dc8134-eba5-43b8-bcc9-bb4bc16c2548};{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC} 15 | 4 16 | ..\ 17 | true 18 | 19 | 20 | 21 | AnyCPU 22 | true 23 | full 24 | false 25 | bin\Debug\ 26 | DEBUG;TRACE 27 | prompt 28 | 4 29 | false 30 | false 31 | 32 | 33 | AnyCPU 34 | pdbonly 35 | true 36 | bin\Release\ 37 | TRACE 38 | prompt 39 | 4 40 | false 41 | 42 | 43 | app.manifest 44 | 45 | 46 | Images\registry.ico 47 | 48 | 49 | 50 | ..\packages\MahApps.Metro.1.6.0-alpha001\lib\net45\MahApps.Metro.dll 51 | 52 | 53 | 54 | ..\packages\CommonServiceLocator.1.3\lib\portable-net4+sl5+netcore45+wpa81+wp8\Microsoft.Practices.ServiceLocation.dll 55 | True 56 | 57 | 58 | ..\packages\Prism.Core.6.3.0\lib\net45\Prism.dll 59 | 60 | 61 | 62 | 63 | 64 | 65 | 66 | 67 | 68 | 69 | 70 | 4.0 71 | 72 | 73 | 74 | 75 | 76 | ..\packages\Zodiacon.WPF.1.2.3\lib\net45\Zodiacon.WPF.dll 77 | 78 | 79 | 80 | 81 | MSBuild:Compile 82 | Designer 83 | 84 | 85 | 86 | 87 | 88 | 89 | 90 | 91 | 92 | 93 | 94 | 95 | 96 | 97 | 98 | 99 | 100 | 101 | 102 | 103 | 104 | 105 | 106 | 107 | 108 | 109 | 110 | 111 | 112 | 113 | 114 | 115 | DataGridView.xaml 116 | 117 | 118 | LoadHiveView.xaml 119 | 120 | 121 | MenuBarView.xaml 122 | 123 | 124 | RegistryTreeView.xaml 125 | 126 | 127 | ToolBarView.xaml 128 | 129 | 130 | 131 | MSBuild:Compile 132 | Designer 133 | 134 | 135 | App.xaml 136 | Code 137 | 138 | 139 | MainWindow.xaml 140 | Code 141 | 142 | 143 | MSBuild:Compile 144 | Designer 145 | 146 | 147 | Designer 148 | MSBuild:Compile 149 | 150 | 151 | Designer 152 | MSBuild:Compile 153 | 154 | 155 | Designer 156 | MSBuild:Compile 157 | 158 | 159 | Designer 160 | MSBuild:Compile 161 | 162 | 163 | Designer 164 | MSBuild:Compile 165 | 166 | 167 | 168 | 169 | Code 170 | 171 | 172 | True 173 | True 174 | Resources.resx 175 | 176 | 177 | True 178 | Settings.settings 179 | True 180 | 181 | 182 | ResXFileCodeGenerator 183 | Resources.Designer.cs 184 | 185 | 186 | 187 | 188 | SettingsSingleFileGenerator 189 | Settings.Designer.cs 190 | 191 | 192 | 193 | 194 | 195 | 196 | 197 | 198 | 199 | 200 | 201 | 202 | 203 | 204 | 205 | 206 | 207 | 208 | 209 | 210 | 211 | 212 | 213 | 214 | 215 | 216 | 217 | 218 | 219 | 220 | 221 | 222 | 223 | 224 | 225 | 226 | 227 | 228 | 229 | 230 | 231 | 232 | 233 | 234 | 235 | 236 | 237 | 238 | 239 | 240 | 241 | 242 | 243 | 244 | 245 | 246 | 247 | 248 | 249 | 250 | 251 | 252 | 253 | 254 | 255 | 256 | 257 | 258 | 259 | 260 | 261 | 262 | 263 | 264 | 265 | 266 | 267 | 268 | 269 | 270 | 271 | 272 | 273 | 274 | 275 | 276 | 277 | 278 | 279 | 280 | 281 | This project references NuGet package(s) that are missing on this computer. Enable NuGet Package Restore to download them. For more information, see http://go.microsoft.com/fwlink/?LinkID=322105. The missing file is {0}. 282 | 283 | 284 | 285 | 292 | -------------------------------------------------------------------------------- /RegistryExplorer/ViewModels/MainViewModel.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Diagnostics; 4 | using System.IO; 5 | using System.Linq; 6 | using System.Runtime.InteropServices; 7 | using System.Threading.Tasks; 8 | using System.Windows; 9 | using System.Windows.Interop; 10 | using System.Windows.Media; 11 | using System.Windows.Media.Imaging; 12 | using System.Windows.Threading; 13 | using Microsoft.Win32; 14 | using Prism.Commands; 15 | using Prism.Mvvm; 16 | using RegistryExplorer.Model; 17 | using System.Windows.Data; 18 | using MahApps.Metro.Controls.Dialogs; 19 | using RegistryExplorer.Views.Dialogs; 20 | using RegistryExplorer.ViewModels.Dialogs; 21 | using RegistryExplorer.Extensions; 22 | using System.Windows.Input; 23 | using System.IO.IsolatedStorage; 24 | using RegistryExplorer.Serialization; 25 | 26 | namespace RegistryExplorer.ViewModels { 27 | class MainViewModel : ViewModelBase, IDisposable { 28 | public CommandManager CommandManager { get; } = new CommandManager(); 29 | public MenuBarViewModel MenuBar { get; } 30 | public ToolBarViewModel ToolBar { get; } 31 | 32 | public Options Options { get; } = new Options(); 33 | 34 | public DelegateCommandBase LaunchWithAdminRightsCommand { get; } 35 | public DelegateCommandBase ExitCommand { get; } 36 | public DelegateCommandBase LoadHiveCommand { get; } 37 | public DelegateCommandBase EditPermissionsCommand { get; } 38 | public DelegateCommandBase EditNewKeyCommand { get; } 39 | public DelegateCommandBase BeginRenameCommand { get; } 40 | public DelegateCommand UndoCommand { get; } 41 | public DelegateCommand RedoCommand { get; } 42 | public DelegateCommandBase EndEditingCommand { get; } 43 | public DelegateCommandBase ExportCommand { get; } 44 | public DelegateCommandBase CopyKeyNameCommand { get; } 45 | public DelegateCommandBase CopyKeyPathCommand { get; } 46 | public DelegateCommandBase DeleteCommand { get; } 47 | public DelegateCommandBase CreateNewValueCommand { get; } 48 | public DelegateCommandBase AddToFavoritesCommand { get; } 49 | public DelegateCommandBase RemoveFromFavoritesCommand { get; } 50 | public DelegateCommandBase RefreshCommand { get; } 51 | 52 | List _roots; 53 | 54 | public IList RootItems => _roots; 55 | 56 | private RegistryKeyItemBase _selectedItem; 57 | 58 | public RegistryKeyItemBase SelectedItem { 59 | get { return _selectedItem; } 60 | set { 61 | if(SetProperty(ref _selectedItem, value)) { 62 | RaisePropertyChanged(nameof(CurrentPath)); 63 | } 64 | } 65 | } 66 | 67 | public string CurrentPath { 68 | get { 69 | if(SelectedItem == null) 70 | return string.Empty; 71 | 72 | var item = SelectedItem as RegistryKeyItem; 73 | if(item != null) 74 | return item.Root.Name + "\\" + item.Path; 75 | return SelectedItem.Text; 76 | } 77 | } 78 | 79 | public bool IsAdmin { get; private set; } 80 | 81 | public string Title => "Registry Explorer" + (IsAdmin ? " (Admin Privileges)" : string.Empty); 82 | 83 | static ImageSource _shieldIcon; 84 | public static ImageSource ShieldIcon { 85 | get { 86 | if(_shieldIcon == null) { 87 | var sii = new SHSTOCKICONINFO(); 88 | sii.cbSize = (uint)Marshal.SizeOf(typeof(SHSTOCKICONINFO)); 89 | 90 | NativeMethods.SHGetStockIconInfo(77, SHGSI.SHGSI_ICON | SHGSI.SHGSI_SMALLICON, ref sii); 91 | 92 | _shieldIcon = Imaging.CreateBitmapSourceFromHIcon(sii.hIcon, Int32Rect.Empty, BitmapSizeOptions.FromEmptyOptions()); 93 | 94 | NativeMethods.DestroyIcon(sii.hIcon); 95 | } 96 | return _shieldIcon; 97 | } 98 | } 99 | 100 | public IDialogCoordinator DialogCoordinator { get; } 101 | 102 | public MainViewModel(IDialogCoordinator _dialogCoordinator) { 103 | DialogCoordinator = _dialogCoordinator; 104 | 105 | MenuBar = new MenuBarViewModel(this); 106 | ToolBar = new ToolBarViewModel(this); 107 | 108 | try { 109 | NativeMethods.EnablePrivilege("SeBackupPrivilege"); 110 | NativeMethods.EnablePrivilege("SeRestorePrivilege"); 111 | IsAdmin = true; 112 | } 113 | catch { 114 | } 115 | 116 | ActiveView = this; 117 | 118 | var computer = new RegistryKeyItemSpecial(null) { 119 | Text = "Computer", 120 | Icon = "/images/workstation2.png", 121 | IsExpanded = true 122 | }; 123 | computer.SubItems.Add(new RegistryKeyItem(computer, Registry.ClassesRoot)); 124 | computer.SubItems.Add(new RegistryKeyItem(computer, Registry.CurrentUser)); 125 | computer.SubItems.Add(new RegistryKeyItem(computer, Registry.LocalMachine)); 126 | computer.SubItems.Add(new RegistryKeyItem(computer, Registry.CurrentConfig)); 127 | computer.SubItems.Add(new RegistryKeyItem(computer, Registry.Users)); 128 | 129 | _roots = new List { 130 | computer, 131 | //new RegistryKeyItemSpecial(null) { 132 | // Text = "Files", 133 | // Icon = "/images/folder_blue.png" 134 | //}, 135 | new RegistryKeyItemSpecial(null) { 136 | Text = "Favorites", 137 | Icon = "/images/favorites.png", 138 | IsExpanded = true 139 | } 140 | }; 141 | 142 | LoadFavorites(); 143 | 144 | ExitCommand = new DelegateCommand(() => Application.Current.Shutdown()); 145 | 146 | LaunchWithAdminRightsCommand = new DelegateCommand(() => { 147 | var pi = new ProcessStartInfo(Process.GetCurrentProcess().MainModule.FileName) { Verb = "RunAs" }; 148 | try { 149 | if(Process.Start(pi) != null) { 150 | Environment.Exit(0); 151 | } 152 | } 153 | catch(Exception ex) { 154 | MessageBox.Show(ex.Message, App.Name); 155 | } 156 | }, () => !IsAdmin); 157 | 158 | EditNewKeyCommand = new DelegateCommand(item => { 159 | var name = item.GenerateUniqueSubKeyName(); 160 | CommandManager.AddCommand(Commands.CreateKey(new CreateKeyCommandContext { 161 | Key = item, 162 | Name = name 163 | })); 164 | item.IsExpanded = true; 165 | var newItem = item.GetSubItem(name); 166 | newItem.IsSelected = true; 167 | Dispatcher.CurrentDispatcher.InvokeAsync(() => IsEditMode = true, DispatcherPriority.Background); 168 | }, item => !IsReadOnlyMode && item is RegistryKeyItem) 169 | .ObservesProperty(() => IsReadOnlyMode); 170 | 171 | EditPermissionsCommand = new DelegateCommand(() => { 172 | // TODO 173 | }, () => SelectedItem is RegistryKeyItem) 174 | .ObservesProperty(() => SelectedItem); 175 | 176 | CopyKeyNameCommand = new DelegateCommand(_ => Clipboard.SetText(SelectedItem.Text), 177 | _ => SelectedItem != null).ObservesProperty(() => SelectedItem); 178 | 179 | CopyKeyPathCommand = new DelegateCommand(() => Clipboard.SetText(((RegistryKeyItem)SelectedItem).Path ?? SelectedItem.Text), 180 | () => SelectedItem is RegistryKeyItem) 181 | .ObservesProperty(() => SelectedItem); 182 | 183 | RefreshCommand = new DelegateCommand(() => SelectedItem.Refresh(), () => SelectedItem != null) 184 | .ObservesProperty(() => SelectedItem); 185 | 186 | EndEditingCommand = new DelegateCommand(async name => { 187 | try { 188 | var item = SelectedItem as RegistryKeyItem; 189 | Debug.Assert(item != null); 190 | if(name == null || name.Equals(item.Text, StringComparison.InvariantCultureIgnoreCase)) 191 | return; 192 | 193 | if(item.Parent.SubItems.Any(i => name.Equals(i.Text, StringComparison.InvariantCultureIgnoreCase))) { 194 | await DialogCoordinator.ShowMessageAsync(this, App.Name, string.Format("Key name '{0}' already exists", name)); 195 | return; 196 | } 197 | CommandManager.AddCommand(Commands.RenameKey(new RenameKeyCommandContext { 198 | Key = item, 199 | OldName = item.Text, 200 | NewName = name 201 | })); 202 | } 203 | catch(Exception ex) { 204 | MessageBox.Show(ex.Message, App.Name); 205 | } 206 | finally { 207 | IsEditMode = false; 208 | CommandManager.UpdateChanges(); 209 | UndoCommand.RaiseCanExecuteChanged(); 210 | RedoCommand.RaiseCanExecuteChanged(); 211 | } 212 | }, _ => IsEditMode).ObservesCanExecute(() => IsEditMode); 213 | 214 | BeginRenameCommand = new DelegateCommand(() => IsEditMode = true, 215 | () => !IsReadOnlyMode && SelectedItem is RegistryKeyItem && !string.IsNullOrEmpty(((RegistryKeyItem)SelectedItem).Path)) 216 | .ObservesProperty(() => SelectedItem).ObservesProperty(() => IsReadOnlyMode); 217 | 218 | UndoCommand = new DelegateCommand(() => { 219 | CommandManager.Undo(); 220 | RedoCommand.RaiseCanExecuteChanged(); 221 | UndoCommand.RaiseCanExecuteChanged(); 222 | }, () => !IsReadOnlyMode && CommandManager.CanUndo).ObservesProperty(() => IsReadOnlyMode); 223 | 224 | RedoCommand = new DelegateCommand(() => { 225 | CommandManager.Redo(); 226 | UndoCommand.RaiseCanExecuteChanged(); 227 | RedoCommand.RaiseCanExecuteChanged(); 228 | }, () => !IsReadOnlyMode && CommandManager.CanRedo).ObservesProperty(() => IsReadOnlyMode); 229 | 230 | LoadHiveCommand = new DelegateCommand(async () => { 231 | var vm = DialogHelper.ShowDialog(); 232 | if(vm.ShowDialog() == true) { 233 | int error = NativeMethods.RegLoadKey(vm.Hive == "HKLM" ? Registry.LocalMachine.Handle : Registry.Users.Handle, vm.Name, vm.FileName); 234 | if(error != 0) { 235 | await DialogCoordinator.ShowMessageAsync(this, App.Name, string.Format("Error opening file: {0}", error.ToString())); 236 | return; 237 | } 238 | 239 | var item = _roots[0].SubItems[vm.Hive == "HKLM" ? 2 : 4]; 240 | item.Refresh(); 241 | ((RegistryKeyItem)item.SubItems.First(i => i.Text == vm.Name)).HiveKey = true; 242 | } 243 | }, () => IsAdmin && !IsReadOnlyMode) 244 | .ObservesProperty(() => IsReadOnlyMode); 245 | 246 | DeleteCommand = new DelegateCommand(() => { 247 | var item = SelectedItem as RegistryKeyItem; 248 | Debug.Assert(item != null); 249 | 250 | if(!IsAdmin) { 251 | if(MessageBox.Show("Running with standard user rights prevents undo for deletion. Delete anyway?", 252 | App.Name, MessageBoxButton.OKCancel, MessageBoxImage.Exclamation) == MessageBoxResult.Cancel) 253 | return; 254 | CommandManager.Clear(); 255 | } 256 | var tempFile = Path.GetTempFileName(); 257 | CommandManager.AddCommand(Commands.DeleteKey(new DeleteKeyCommandContext { 258 | Key = item, 259 | TempFile = tempFile 260 | })); 261 | CommandManager.UpdateChanges(); 262 | UndoCommand.RaiseCanExecuteChanged(); 263 | RedoCommand.RaiseCanExecuteChanged(); 264 | }, () => !IsReadOnlyMode && SelectedItem is RegistryKeyItem && SelectedItem.Path != null).ObservesProperty(() => IsReadOnlyMode); 265 | 266 | ExportCommand = new DelegateCommand(() => { 267 | var dlg = new SaveFileDialog { 268 | Title = "Select output file", 269 | Filter = "Registry data files|*.dat", 270 | OverwritePrompt = true 271 | }; 272 | if(dlg.ShowDialog() == true) { 273 | var item = SelectedItem as RegistryKeyItem; 274 | Debug.Assert(item != null); 275 | using(var key = item.Root.OpenSubKey(item.Path)) { 276 | File.Delete(dlg.FileName); 277 | int error = NativeMethods.RegSaveKeyEx(key.Handle, dlg.FileName, IntPtr.Zero, 2); 278 | Debug.Assert(error == 0); 279 | } 280 | } 281 | }, () => IsAdmin && SelectedItem is RegistryKeyItem) 282 | .ObservesProperty(() => SelectedItem); 283 | 284 | CreateNewValueCommand = new DelegateCommand(vm => { 285 | 286 | }, vm => !IsReadOnlyMode) 287 | .ObservesProperty(() => IsReadOnlyMode); 288 | 289 | AddToFavoritesCommand = new DelegateCommand(() => { 290 | var item = SelectedItem as RegistryKeyItem; 291 | Debug.Assert(item != null); 292 | 293 | _roots[1].SubItems.Add(new RegistryKeyItem(item.Parent as RegistryKeyItem, item.Text)); 294 | SaveFavorites(); 295 | }, () => SelectedItem is RegistryKeyItem && !string.IsNullOrEmpty(SelectedItem.Path)) 296 | .ObservesProperty(() => SelectedItem); 297 | 298 | RemoveFromFavoritesCommand = new DelegateCommand(() => { 299 | _roots[1].SubItems.Remove(SelectedItem); 300 | SaveFavorites(); 301 | }, () => SelectedItem != null && SelectedItem.Flags.HasFlag(RegistryKeyFlags.Favorite)) 302 | .ObservesProperty(() => SelectedItem); 303 | } 304 | 305 | public void Dispose() { 306 | } 307 | 308 | private bool _isReadOnlyMode = true; 309 | 310 | public bool IsReadOnlyMode { 311 | get { return _isReadOnlyMode; } 312 | set { 313 | if(SetProperty(ref _isReadOnlyMode, value)) { 314 | CommandManager.UpdateChanges(); 315 | } 316 | } 317 | } 318 | 319 | private bool _isEditMode; 320 | 321 | public bool IsEditMode { 322 | get { return _isEditMode; } 323 | set { SetProperty(ref _isEditMode, value); } 324 | } 325 | 326 | public void SaveFavorites() { 327 | using(var stm = IsolatedStorageFile.GetUserStoreForAssembly().OpenFile("favorites.dat", FileMode.OpenOrCreate, FileAccess.ReadWrite)) { 328 | Serializer.SaveKeys(stm, _roots[1].SubItems); 329 | } 330 | } 331 | 332 | public void LoadFavorites() { 333 | try { 334 | using(var stm = IsolatedStorageFile.GetUserStoreForAssembly().OpenFile("favorites.dat", FileMode.Open)) { 335 | var keys = Serializer.LoadKeys(stm); 336 | foreach(var key in keys) { 337 | key.Flags |= RegistryKeyFlags.Favorite; 338 | _roots[1].SubItems.Add(key); 339 | } 340 | } 341 | } 342 | catch { } 343 | } 344 | 345 | public bool IsInFavorites => SelectedItem.Flags.HasFlag(RegistryKeyFlags.Favorite); 346 | public bool IsNotInFavorites => !SelectedItem.Flags.HasFlag(RegistryKeyFlags.Favorite); 347 | } 348 | } 349 | --------------------------------------------------------------------------------