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));
}
}