using Microsoft.Win32; namespace Vanara.Windows.Shell; /// Base class for registry based settings. public abstract class RegBasedSettings : IDisposable, IEquatable, IComparable { /// The base key from which to perform all queries. protected internal RegistryKey key; /// Initializes a new instance of the class. /// The key to use as the base key for queries. /// if set to true the supplied was opened read-only. protected RegBasedSettings(RegistryKey key, bool readOnly) { this.key = key ?? throw new ArgumentNullException(nameof(key)); ReadOnly = readOnly; } /// Gets a value indicating whether this instance is system wide. /// if this instance is system wide; otherwise, . public bool IsSystemWide => !key.Name.StartsWith("HKEY_CURRENT_USER"); /// Gets or sets a value indicating whether these settings are read-only. public bool ReadOnly { get; } /// Gets the absolute (qualified) name of the key. public string RegPath => key.Name; /// public int CompareTo(RegBasedSettings? other) => string.Compare(key.Name, other?.key.Name, StringComparison.InvariantCulture); /// public bool Equals(RegBasedSettings? other) => CompareTo(other) == 0; /// public override int GetHashCode() => key?.Name.GetHashCode() ?? 0; /// public override string ToString() => key?.ToString() ?? ""; /// public virtual void Dispose() { key?.Close(); ShellRegistrar.NotifyShell(); } /// Checks the ReadOnly flag and throws an exception if it is true. protected void EnsureWritable() { if (ReadOnly) throw new InvalidOperationException("Object is read only and its values cannot be changed."); } /// Toggles the value identified by having a named subkey present. /// The name of the subkey. /// if set to true, creates a subkey named ; otherwise deletes that subkey. protected void ToggleKeyValue(string name, bool set) { EnsureWritable(); if (!set) key.DeleteSubKey(name, false); else key.CreateSubKey(name)?.Close(); } /// Toggles the value identified by having a named value present. /// The name of the value. /// if set to true, creates a value named ; otherwise deletes that value. protected void ToggleValue(string name, bool set) { EnsureWritable(); if (!set) key.DeleteValue(name, false); else key.SetValue(name, "", RegistryValueKind.String); } /// Updates the value identified by having a named subkey with its default value set. /// The name of the subkey. /// The value of the default value. /// The value that, if equal to , causes the removal of the subkey. protected internal void UpdateKeyValue(string name, string? value, string? deleteIfValue = null) { EnsureWritable(); if (Equals(value, deleteIfValue)) key.DeleteSubKey(name, false); else key.CreateSubKey(name, value).Close(); } /// Updates the value identified by having a named value. /// Type of the value /// The name of the value. /// The value of the value. /// Kind of the value. /// The value that, if equal to , causes the removal of the value. protected internal void UpdateValue(string? name, T? value, RegistryValueKind valueKind = RegistryValueKind.Unknown, T? deleteIfValue = default) { EnsureWritable(); if (name is not null && Equals(value, deleteIfValue)) key.DeleteValue(name, false); else if (value is not null) { var o = value is Guid g ? (object)g.ToRegString() : value; key.SetValue(name, value, valueKind == RegistryValueKind.Unknown && o is string ? RegistryValueKind.ExpandString : valueKind); } else throw new ArgumentNullException(nameof(value)); } }