diff --git a/mRemoteNG/Tools/WindowsRegistry/IRegistry.cs b/mRemoteNG/Tools/WindowsRegistry/IRegistry.cs index 32cff52a..a6e69061 100644 --- a/mRemoteNG/Tools/WindowsRegistry/IRegistry.cs +++ b/mRemoteNG/Tools/WindowsRegistry/IRegistry.cs @@ -1,8 +1,36 @@ -namespace mRemoteNG.Tools.WindowsRegistry +using Microsoft.Win32; +using System; +using System.Collections.Generic; +using System.Runtime.Versioning; + +namespace mRemoteNG.Tools.WindowsRegistry { + [SupportedOSPlatform("windows")] public interface IRegistry { - Optional GetKeyValue(RegistryHive hive, string keyPath, string propertyName); - string[] GetSubKeyNames(RegistryHive hive, string keyPath); + #region registry reader + string[] GetSubKeyNames(RegistryHive hive, string path); + + Optional GetPropertyValue(WindowsRegistryKey key); + Optional GetPropertyValue(RegistryHive hive, string path, string name); + + WindowsRegistryKey GetWindowsRegistryKey(RegistryHive hive, string path, string name); + WindowsRegistryKey GetWindowsRegistryKey(WindowsRegistryKey key); + + List GetRegistryEntries(RegistryHive hive, string path); + List GetRegistryEntryiesRecursive(RegistryHive hive, string path); + + #endregion + + #region registry writer + void SetRegistryValue(WindowsRegistryKey key); + void SetRegistryValue(RegistryHive hive, string path, string name, object value, RegistryValueKind valueKind); + + #endregion + + #region converter + RegistryHive ConvertStringToRegistryHive(string hiveString); + RegistryValueKind ConvertStringToRegistryValueKind(string valueType); + #endregion } } \ No newline at end of file diff --git a/mRemoteNG/Tools/WindowsRegistry/IRegistryRead.cs b/mRemoteNG/Tools/WindowsRegistry/IRegistryRead.cs new file mode 100644 index 00000000..8c6dfbc3 --- /dev/null +++ b/mRemoteNG/Tools/WindowsRegistry/IRegistryRead.cs @@ -0,0 +1,29 @@ +using Microsoft.Win32; +using System; +using System.Collections.Generic; +using System.Runtime.Versioning; + +namespace mRemoteNG.Tools.WindowsRegistry +{ + [SupportedOSPlatform("windows")] + public interface IRegistryRead + { + #region registry reader + string[] GetSubKeyNames(RegistryHive hive, string path); + + Optional GetPropertyValue(WindowsRegistryKey key); + Optional GetPropertyValue(RegistryHive hive, string path, string name); + + WindowsRegistryKey GetWindowsRegistryKey(RegistryHive hive, string path, string name); + WindowsRegistryKey GetWindowsRegistryKey(WindowsRegistryKey key); + + List GetRegistryEntries(RegistryHive hive, string path); + List GetRegistryEntryiesRecursive(RegistryHive hive, string path); + #endregion + + #region converter + RegistryHive ConvertStringToRegistryHive(string hiveString); + RegistryValueKind ConvertStringToRegistryValueKind(string valueType); + #endregion + } +} \ No newline at end of file diff --git a/mRemoteNG/Tools/WindowsRegistry/IRegistryWrite.cs b/mRemoteNG/Tools/WindowsRegistry/IRegistryWrite.cs new file mode 100644 index 00000000..0e46e449 --- /dev/null +++ b/mRemoteNG/Tools/WindowsRegistry/IRegistryWrite.cs @@ -0,0 +1,21 @@ +using Microsoft.Win32; +using System; +using System.Runtime.Versioning; + +namespace mRemoteNG.Tools.WindowsRegistry +{ + [SupportedOSPlatform("windows")] + public interface IRegistryWrite + { + #region registry writer + void SetRegistryValue(WindowsRegistryKey key); + void SetRegistryValue(RegistryHive hive, string path, string name, object value, RegistryValueKind valueKind); + + #endregion + + #region converter + RegistryHive ConvertStringToRegistryHive(string hiveString); + RegistryValueKind ConvertStringToRegistryValueKind(string valueType); + #endregion} + } +} \ No newline at end of file diff --git a/mRemoteNG/Tools/WindowsRegistry/RegistryHive.cs b/mRemoteNG/Tools/WindowsRegistry/RegistryHive.cs deleted file mode 100644 index 4663bf27..00000000 --- a/mRemoteNG/Tools/WindowsRegistry/RegistryHive.cs +++ /dev/null @@ -1,11 +0,0 @@ -namespace mRemoteNG.Tools.WindowsRegistry -{ - public enum RegistryHive - { - ClassesRoot, - CurrentConfig, - CurrentUser, - Users, - LocalMachine - } -} \ No newline at end of file diff --git a/mRemoteNG/Tools/WindowsRegistry/WindowsRegistry.cs b/mRemoteNG/Tools/WindowsRegistry/WindowsRegistry.cs index f121cd6d..53025028 100644 --- a/mRemoteNG/Tools/WindowsRegistry/WindowsRegistry.cs +++ b/mRemoteNG/Tools/WindowsRegistry/WindowsRegistry.cs @@ -1,39 +1,324 @@ -using System; +using Amazon.EC2.Model; +using Google.Protobuf.WellKnownTypes; +using Microsoft.Win32; +using MySqlX.XDevAPI.Common; +using System; +using System.Collections.Generic; +using System.IO; using System.Linq; using System.Runtime.Versioning; -using Microsoft.Win32; +using System.Security; namespace mRemoteNG.Tools.WindowsRegistry { + /// + /// This class implements the IRegistryRead and IRegistryWrite interfaces and provides methods for interacting with the Windows Registry. + /// [SupportedOSPlatform("windows")] - public class WindowsRegistry : IRegistry + public class WindowsRegistry : IRegistry, IRegistryRead, IRegistryWrite { - public string[] GetSubKeyNames(RegistryHive hive, string keyPath) + #region public read + /// + /// Retrieves the names of subkeys under a specified registry key path. + /// + /// The RegistryHive where the subkeys are located. + /// The path to the registry key containing the subkeys. + /// An array of strings containing the names of subkeys, or an empty array if no subkeys are found. + public string[] GetSubKeyNames(RegistryHive hive, string path) { - keyPath.ThrowIfNull(nameof(keyPath)); + if (hive == 0) + throw new ArgumentException("Unknown or unsupported RegistryHive value.", nameof(hive)); + path.ThrowIfNull(nameof(path)); - using (var key = OpenSubKey(hive, keyPath)) + using (var key = OpenSubKey(hive, path)) { return key.Any() ? key.First().GetSubKeyNames() : new string[0]; } + } + + /// + /// Retrieves the value of a specific property within a Windows Registry key and returns it as an Optional. + /// + /// The WindowsRegistryKey containing information about the registry property. + /// An Optional containing the property value, or Optional.Empty if the value is not found. + public Optional GetPropertyValue(WindowsRegistryKey key) + { + if (!key.IsKeyReadable()) + throw new InvalidOperationException("The Windows Registry key is not ready for reading."); + + return GetPropertyValue(key.Hive, key.Path, key.Name); } - public Optional GetKeyValue(RegistryHive hive, string keyPath, string propertyName) + /// + /// Retrieves the value of a specific property within the Windows Registry and returns it as an Optional. + /// + /// The RegistryHive where the property is located. + /// The path to the registry key containing the property. + /// The name of the property to retrieve. + /// An Optional containing the property value, or Optional.Empty if the value is not found. + public Optional GetPropertyValue(RegistryHive hive, string path, string name) { - keyPath.ThrowIfNull(nameof(keyPath)); - propertyName.ThrowIfNull(nameof(propertyName)); + if (hive == 0) + throw new ArgumentException("Unknown or unsupported RegistryHive value.", nameof(hive)); + path.ThrowIfNull(nameof(path)); + name.ThrowIfNull(nameof(name)); - using (var key = OpenSubKey(hive, keyPath)) + using (var key = OpenSubKey(hive, path)) { if (!key.Any()) return Optional.Empty; - return key.First().GetValue(propertyName) as string; + return key.First().GetValue(name) as string; } } + /// + /// Retrieves a WindowsRegistryKey object for a specific registry hive, path, and value name. + /// + /// The RegistryHive of the key. + /// The path of the key. + /// The name of the value to retrieve. + /// A WindowsRegistryKey object representing the specified registry key and value. + public WindowsRegistryKey GetWindowsRegistryKey(RegistryHive hive, string path, string name) + { + WindowsRegistryKey key = new WindowsRegistryKey + { + Hive = hive, + Path = path, + Name = name + }; + + return GetWindowsRegistryKey(key); + } + + /// + /// Retrieves a WindowsRegistryKey object for a specific WindowsRegistryKey, populating its value and value kind. + /// + /// A WindowsRegistryKey object containing the hive, path, value name and more. + /// A WindowsRegistryKey object representing the specified registry key and value, with value and value kind populated. + public WindowsRegistryKey GetWindowsRegistryKey(WindowsRegistryKey key) + { + if (!key.IsKeyReadable()) + throw new InvalidOperationException("The Windows Registry key is not ready for reading."); + + using (RegistryKey baseKey = RegistryKey.OpenBaseKey(key.Hive, RegistryView.Default), subKey = baseKey.OpenSubKey(key.Path)) + { + if (subKey != null) + { + var value = subKey.GetValue(key.Name); + if (value != null) + key.Value = value.ToString(); + + RegistryValueKind ValueKind; + if (TestValueKindExists(subKey, key.Name, out ValueKind)) + key.ValueKind = ValueKind; + } + } + + return key; + } + + /// + /// Retrieves a list of registry entries (properties) and their values under a given key path. + /// + /// The RegistryHive of the key path. + /// The path of the key from which to retrieve values. + /// A list of WindowsRegistryKey objects, each representing a value within the specified registry key path. + public List GetRegistryEntries(RegistryHive hive, string path) + { + if (hive == 0) + throw new ArgumentException("Unknown or unsupported RegistryHive value.", nameof(hive)); + path.ThrowIfNull(nameof(path)); + + List list = new List(); + using (RegistryKey baseKey = RegistryKey.OpenBaseKey(hive, RegistryView.Default), key = baseKey.OpenSubKey(path)) + { + if (key != null) + { + foreach (string valueName in key.GetValueNames()) + { + list.Add(new WindowsRegistryKey + { + Hive = hive, + Path = path, + Name = valueName, + Value = key.GetValue(valueName).ToString(), + ValueKind = key.GetValueKind(valueName) + } + ); + } + } + + } + return list; + } + + /// + /// Recursively retrieves registry entries under a given key path and its subkeys. + /// + /// The RegistryHive of the key path. + /// The path of the key from which to retrieve values. + /// A list of WindowsRegistryKey objects, each representing a value within the specified registry key path. + public List GetRegistryEntryiesRecursive(RegistryHive hive, string path) + { + if (hive == 0) + throw new ArgumentException("Unknown or unsupported RegistryHive value.", nameof(hive)); + path.ThrowIfNull(nameof(path)); + + List list = GetRegistryEntries(hive, path); + using (RegistryKey baseKey = RegistryKey.OpenBaseKey(hive, RegistryView.Default), key = baseKey.OpenSubKey(path)) + { + if (key != null) + { + foreach (string subPathName in key.GetSubKeyNames()) + { + string subKey = $"{path}\\{subPathName}"; + list.AddRange(GetRegistryEntryiesRecursive(hive, subKey)); + } + } + } + + return list; + } + #endregion + + #region public write methods + /// + /// Sets the value of a specific property within a registry key using individual parameters. + /// + /// The registry hive. + /// The path to the registry key containing the property. + /// The name of the property to set. + /// The value to set for the property. + /// The data type of the value to set. + public void SetRegistryValue(RegistryHive hive, string path, string name, object value, RegistryValueKind valueKind) + { + WindowsRegistryKey key = (new WindowsRegistryKey + { + Hive = hive, + Path = path, + Name = name, + Value = value.ToString(), + ValueKind = valueKind + }); + + CreateOrSetRegistryValue(key); + } + + /// + /// Sets the value of a specific property within a registry key using the provided WindowsRegistryKey object. + /// + /// The WindowsRegistryKey object containing information about the registry property. + public void SetRegistryValue(WindowsRegistryKey key) + { + CreateOrSetRegistryValue(key); + } + #endregion + + #region public methods + /// + /// Converts a string representation of a Registry Hive to the corresponding RegistryHive enum value. + /// + /// A string representation of a Registry Hive, not case-sensitive. + /// The RegistryHive enum value corresponding to the provided string representation. + /// Thrown if the provided string does not match a valid Registry Hive. + public RegistryHive ConvertStringToRegistryHive(string hiveString) + { + switch (hiveString.ToLower()) + { + // ClassesRoot + case "hkcr": + case "hkey_classes_root": + case "classesroot": + return RegistryHive.ClassesRoot; + + // CurrentUser + case "hkcu": + case "hkey_current_user": + case "currentuser": + return RegistryHive.CurrentUser; + + // LocalMachine + case "hklm": + case "hkey_local_machine": + case "localmachine": + return RegistryHive.LocalMachine; + + // Users + case "hku": + case "hkey_users": + case "users": + return RegistryHive.Users; + + // CurrentConfig + case "hkcc": + case "hkey_current_config": + case "currentconfig": + return RegistryHive.CurrentConfig; + + default: + throw new ArgumentException("Invalid registry hive string.", nameof(hiveString)); + } + } + + /// + /// Converts a string representation of a RegistryValueKind to the corresponding RegistryValueKind enum value. + /// + /// A string representation of a RegistryValueKind, not case-sensitive. + /// The RegistryValueKind enum value corresponding to the provided string representation. + /// Thrown if the provided string does not match a valid RegistryValueKind. + public RegistryValueKind ConvertStringToRegistryValueKind(string valueType) + { + switch (valueType.ToLower()) + { + // REG_SZ + case "string": + case "reg_sz": + return RegistryValueKind.String; + + // REG_DWORD + case "dword": + case "reg_dword": + return RegistryValueKind.DWord; + + // REG_BINARY + case "binary": + case "reg_binary": + return RegistryValueKind.Binary; + + // REG_QWORD + case "qword": + case "reg_qword": + return RegistryValueKind.QWord; + + // REG_MULTI_SZ + case "multistring": + case "reg_multi_sz": + return RegistryValueKind.MultiString; + + // REG_EXPAND_SZ + case "expandstring": + case "reg_expand_sz": + return RegistryValueKind.ExpandString; + + default: + throw new ArgumentException("Invalid RegistryValueKind string representation.", nameof(valueType)); + } + } + #endregion + + #region private methods + /// + /// Opens a subkey within the Windows Registry under the specified hive and key path. + /// + /// The Windows Registry hive where the subkey is located. + /// The path to the subkey to be opened. + /// + /// A disposable optional object containing the opened registry subkey if successful; + /// otherwise, it returns an empty optional object. + /// private DisposableOptional OpenSubKey(RegistryHive hive, string keyPath) { switch (hive) @@ -52,5 +337,86 @@ namespace mRemoteNG.Tools.WindowsRegistry throw new ArgumentOutOfRangeException(nameof(hive), hive, null); } } + + /// + /// Attempts to retrieve the value kind of a specific property within a registry subkey. + /// + /// The registry subkey from which to retrieve the value kind. + /// The name of the property for which to retrieve the value kind. + /// An output parameter that will contain the retrieved value kind, or RegistryValueKind.Unknown if the property or value kind is not found. + /// True if the operation is successful, otherwise false. + private bool TestValueKindExists(RegistryKey subKey, string valueName, out RegistryValueKind valueKind) + { + // Set a default value + valueKind = RegistryValueKind.Unknown; + try + { + valueKind = subKey.GetValueKind(valueName); + return true; + } + catch (Exception) + { + return false; + } + } + + /// + /// Creates or sets the value of a specific property within a registry key. + /// + /// The WindowsRegistryKey object containing information about the registry property. + /// Thrown when the Windows Registry key is not ready for writing. + /// Thrown when a security-related error occurs while accessing the registry. + /// Thrown when an I/O error occurs while accessing the registry. + /// Thrown when access to the registry is unauthorized. + /// Thrown for all other exceptions. + private void CreateOrSetRegistryValue(WindowsRegistryKey key) + { + try + { + if (!key.IsKeyWritable()) + throw new InvalidOperationException("The Windows Registry key is not ready for writing."); + + using (RegistryKey baseKey = RegistryKey.OpenBaseKey(key.Hive, RegistryView.Default), registryKey = baseKey.OpenSubKey(key.Path, true)) + { + if (registryKey == null) + { + // The specified subkey doesn't exist, so create it. + using (RegistryKey newKey = baseKey.CreateSubKey(key.Path)) + { + newKey.SetValue(key.Name, key.Value, key.ValueKind); + } + } + else + { + registryKey.SetValue(key.Name, key.Value, key.ValueKind); + } + } + } + catch (SecurityException ex) + { + // Handle or log SecurityException + // For example: log ex.Message + throw; + } + catch (IOException ex) + { + // Handle or log IOException + // For example: log ex.Message + throw; + } + catch (UnauthorizedAccessException ex) + { + // Handle or log UnauthorizedAccessException + // For example: log ex.Message + throw; + } + catch (Exception ex) + { + // For all other exceptions, log and rethrow + // For example: log ex.ToString() + throw; + } + } + #endregion } } \ No newline at end of file diff --git a/mRemoteNG/Tools/WindowsRegistry/WindowsRegistryKey.cs b/mRemoteNG/Tools/WindowsRegistry/WindowsRegistryKey.cs new file mode 100644 index 00000000..cc06b688 --- /dev/null +++ b/mRemoteNG/Tools/WindowsRegistry/WindowsRegistryKey.cs @@ -0,0 +1,213 @@ +using System; +using System.Runtime.Versioning; +using Microsoft.Win32; + + +namespace mRemoteNG.Tools.WindowsRegistry +{ + /// + /// This class provides a convenient way to work with Windows Registry keys + /// by encapsulating information about a registry key, including its path, + /// name, value, and registry hive/type. + /// + [SupportedOSPlatform("windows")] + public class WindowsRegistryKey + { + #region properties + + #region Property registryHive + public RegistryHive Hive + { + get { return _Hive; } + set + { + if (value == 0) + throw new ArgumentNullException("RegistryHive unknown."); + + _Hive = value; + } + } + private RegistryHive _Hive { get; set; } + #endregion + + #region Property path + public string Path + { + get { return _Path; } + set + { + value.ThrowIfNull(nameof(value)); + _Path = value; + } + } + private string _Path { get; set; } + #endregion + + #region Property name + public string Name + { + get { return _Name; } + set + { + value.ThrowIfNull(nameof(value)); + _Name = value; + } + } + private string _Name { get; set; } + #endregion + + #region Property valueKind + public RegistryValueKind ValueKind + { + get { return _ValueKind; } + set { + if (value == 0) + throw new ArgumentNullException("ValueKind unknown."); + + _ValueKind = value; + + // Check if Type is uninitialized (null) + if (_Type == null) + // Initialize Type if it's uninitialized + _Type = ConvertRegistryValueKindToType(value); + } + } + private RegistryValueKind _ValueKind; + #endregion + + #region Property type + public Type Type + { + get { return _Type; } + set { + _Type = value; + + // Check if ValueKind is uninitialized(0) + if (_ValueKind == 0) + // Initialize ValueKind if it's uninitialized + _ValueKind = ConvertTypeToRegistryValueKind(value); + } + } + private Type _Type; + #endregion + + public string Value { get; set; } + #endregion + + #region public methods + /// + /// Checks if the Windows Registry key is ready for reading by ensuring that the hive, + /// path, and name properties are set. + /// + /// True if the key is ready for reading, otherwise false. + public bool IsKeyReadable() { + return (IsHiveSet() && IsPathSet() && IsNameSet()); + } + + /// + /// Checks if the Windows Registry key is ready for a write operation. + /// The key is considered write-ready if none of the following conditions are met: + /// - The hive is set + /// - The registry value type is set + /// - The key path is set + /// - The value name is set + /// - The value data is set + /// + /// Returns true if the key is write-ready, otherwise false. + public bool IsKeyWritable() { + return (IsHiveSet() && IsValueKindSet() && IsPathSet() && IsNameSet()); + //return (IsHiveSet() && IsValueKindSet() && IsPathSet() && IsNameSet() && IsValueSet()); + } + #endregion + + #region private methods + /// + /// Converts a .NET data type to the corresponding RegistryValueKind. + /// + /// The .NET data type to convert. + /// The corresponding RegistryValueKind. + private RegistryValueKind ConvertTypeToRegistryValueKind(Type valueType) + { + switch (Type.GetTypeCode(valueType)) + { + case TypeCode.String: + return RegistryValueKind.String; + case TypeCode.Int32: + return RegistryValueKind.DWord; + case TypeCode.Int64: + return RegistryValueKind.QWord; + case TypeCode.Boolean: + return RegistryValueKind.DWord; + case TypeCode.Byte: + return RegistryValueKind.Binary; + /* + case TypeCode.Single: + return RegistryValueKind; + case TypeCode.Double: + return RegistryValueKind.String; + case TypeCode.DateTime: + return RegistryValueKind.String; // DateTime can be stored as a string or other types + case TypeCode.Char: + return RegistryValueKind.String; // Char can be stored as a string or other types + case TypeCode.Decimal: + return RegistryValueKind.String; // Decimal can be stored as a string or other types + */ + default: + return RegistryValueKind.String; // Default to String for unsupported types + } + } + + /// + /// Converts a RegistryValueKind enumeration value to its corresponding .NET Type. + /// + /// The RegistryValueKind value to be converted. + /// The .NET Type that corresponds to the given RegistryValueKind. + private Type ConvertRegistryValueKindToType(RegistryValueKind valueKind) + { + switch (valueKind) + { + case RegistryValueKind.String: + case RegistryValueKind.ExpandString: + return typeof(string); + case RegistryValueKind.DWord: + return typeof(int); + case RegistryValueKind.QWord: + return typeof(long); + case RegistryValueKind.Binary: + return typeof(byte[]); + case RegistryValueKind.MultiString: + return typeof(string[]); + case RegistryValueKind.Unknown: + default: + return typeof(object); + } + } + + private bool IsHiveSet() + { + return Hive != 0; + } + + private bool IsValueKindSet() + { + return ValueKind != 0; + } + + private bool IsPathSet() + { + return Path != null; ; + //return !string.IsNullOrEmpty(Path); + } + + private bool IsNameSet() + { + return Name != null; + } + + private bool IsValueSet() + { + return !string.IsNullOrEmpty(Value); + } + #endregion + } +} diff --git a/mRemoteNGTests/Tools/Registry/WindowsRegistryTests.cs b/mRemoteNGTests/Tools/Registry/WindowsRegistryTests.cs index 292b1b8a..67d7a6f5 100644 --- a/mRemoteNGTests/Tools/Registry/WindowsRegistryTests.cs +++ b/mRemoteNGTests/Tools/Registry/WindowsRegistryTests.cs @@ -1,50 +1,195 @@ using System; +using System.Collections.Generic; using System.Linq; +using Microsoft.Win32; using mRemoteNG.Tools.WindowsRegistry; +using MySqlX.XDevAPI.Common; +using NSubstitute.ExceptionExtensions; using NUnit.Framework; namespace mRemoteNGTests.Tools.Registry { public class WindowsRegistryTests { - private WindowsRegistry _registry; + private IRegistry _registry; + private IRegistryRead _registryReader; + private IRegistryWrite _registryWriter; [SetUp] public void Setup() { _registry = new WindowsRegistry(); + _registryReader = new WindowsRegistry(); + _registryWriter = new WindowsRegistry(); } + #region GetSubKeyNames() tests [Test] public void CanGetSubkeyNames() { - var subKeyNames = _registry.GetSubKeyNames(RegistryHive.CurrentUser, "Software"); + var subKeyNames = _registryReader.GetSubKeyNames(RegistryHive.CurrentUser, "Software"); Assert.That(subKeyNames, Does.Contain("Microsoft")); } - [Test] public void GetSubkeyNamesThrowsIfGivenNullKeyPath() { - Assert.Throws(() => _registry.GetSubKeyNames(RegistryHive.CurrentUser, null)); + Assert.Throws(() => _registryReader.GetSubKeyNames(RegistryHive.CurrentUser, null)); } - [Test] - public void CanGetKeyValue() + public void GetSubkeyNamesThrowsIfGivenUnknownHive() { - var keyValue = _registry.GetKeyValue(RegistryHive.ClassesRoot, @".dll\PersistentHandler", ""); + Assert.Throws(() => _registryReader.GetSubKeyNames(new RegistryHive(), "Software")); + } + #endregion + + #region GetPropertyValue() tests + [Test] + public void CanGetPropertyValue() + { + var keyValue = _registryReader.GetPropertyValue(RegistryHive.ClassesRoot, @".dll\PersistentHandler", ""); Assert.That(keyValue.FirstOrDefault(), Is.EqualTo("{098f2470-bae0-11cd-b579-08002b30bfeb}")); } [Test] - public void GetKeyValueThrowsIfGivenNullKeyPath() + public void CanGetPropertyValueByRegistryKeyObject() { - Assert.Throws(() => _registry.GetKeyValue(RegistryHive.CurrentUser, null, "")); + WindowsRegistryKey key = new WindowsRegistryKey + { + Hive = RegistryHive.ClassesRoot, + Path = @".dll\PersistentHandler", + Name = "" + }; + + var keyValue = _registryReader.GetPropertyValue(key); + Assert.That(keyValue.FirstOrDefault(), Is.EqualTo("{098f2470-bae0-11cd-b579-08002b30bfeb}")); + } + [Test] + public void GetPropertyValueThrowsIfGivenNullKeyPath() + { + Assert.Throws(() => _registryReader.GetPropertyValue(RegistryHive.CurrentUser, null, "")); } [Test] - public void GetKeyValueThrowsIfGivenNullPropertyName() + public void GetPropertyValueThrowsIfGivenNullPropertyName() { - Assert.Throws(() => _registry.GetKeyValue(RegistryHive.CurrentUser, "", null)); + Assert.Throws(() => _registryReader.GetPropertyValue(RegistryHive.CurrentUser, "", null)); } + #endregion + + #region GetWindowsRegistryKey() tests + [Test] + public void CanGetWindowsRegistryKey() + { + WindowsRegistryKey keyValue = _registryReader.GetWindowsRegistryKey(RegistryHive.ClassesRoot, @".dll\PersistentHandler", ""); + Assert.That(keyValue.Value, Is.EqualTo("{098f2470-bae0-11cd-b579-08002b30bfeb}")); + } + + [Test] + public void CanGetWindowsRegistryKeyByObject() + { + WindowsRegistryKey key = new WindowsRegistryKey + { + Hive = RegistryHive.ClassesRoot, + Path = @".dll\PersistentHandler", + Name = "" + }; + + WindowsRegistryKey keyValue = _registryReader.GetWindowsRegistryKey(key); + Assert.That(keyValue.Value, Is.EqualTo("{098f2470-bae0-11cd-b579-08002b30bfeb}")); + } + + [Test] + public void CanGetWindowsRegistryKeyForKeyNotExists() + { + // No exception. Only null value + WindowsRegistryKey keyValue = _registryReader.GetWindowsRegistryKey(RegistryHive.LocalMachine, @"Software\Testabcdefg", "abcdefg"); + Assert.That(keyValue.Value, Is.EqualTo(null)); + } + + [Test] + public void GetWindowsRegistryThrowNotReadable() + { + WindowsRegistryKey key = new WindowsRegistryKey + { + Hive = RegistryHive.ClassesRoot, + }; + + Assert.Throws(() => _registryReader.GetWindowsRegistryKey(key)); + } + #endregion + + #region GetRegistryEntries() + Recurse tests + [Test] + public void CanGetRegistryEntries() + { + List keys = _registryReader.GetRegistryEntries(RegistryHive.LocalMachine, @"HARDWARE\DESCRIPTION\System\BIOS"); + Assert.That(keys.Count, Is.Not.EqualTo(0)); + } + + [Test] + public void CanGetRegistryEntriesRecurse() + { + List keys = _registryReader.GetRegistryEntryiesRecursive(RegistryHive.LocalMachine, @"SOFTWARE\Microsoft\Windows\Windows Search"); + Assert.That(keys.Count, Is.Not.EqualTo(0)); + } + #endregion + + #region new WindowsRegistryKey() tests + [Test] + public void IsWindowsRegistryKeyValid() + { + // Tests property rules of WindowsRegistryKey + WindowsRegistryKey key = new WindowsRegistryKey(); + + Assert.Multiple(() => + { + Assert.DoesNotThrow(() => key.Hive = RegistryHive.CurrentUser); + Assert.DoesNotThrow(() => key.ValueKind = RegistryValueKind.String); + Assert.DoesNotThrow(() => key.Path = "Software"); + Assert.DoesNotThrow(() => key.Name = "NotThereButOK"); + //Assert.DoesNotThrow(() => key.Value = "Equal", ""); + }); + + } + [Test] + public void WindowsRegistryKeyThrowHiveNullException() + { + WindowsRegistryKey key = new WindowsRegistryKey(); + Assert.Throws(() => key.Hive = 0, "Expected IsHiveValid to throw ArgumentNullException"); + } + + [Test] + public void WindowsRegistryKeyThrowValueKindNullException() + { + WindowsRegistryKey key = new WindowsRegistryKey(); + Assert.Throws(() => key.ValueKind = 0, "Expected IsValueKindValid to throw ArgumentNullException"); + } + [Test] + public void WindowsRegistryKeyThrowPathNullException() + { + WindowsRegistryKey key = new WindowsRegistryKey(); + Assert.Throws(() => key.Path = null, "Expected IsPathValid to throw ArgumentNullException"); + } + [Test] + public void WindowsRegistryKeyThrowNameNullException() + { + WindowsRegistryKey key = new WindowsRegistryKey(); + Assert.Throws(() => key.Name = null, "Expected IsNameValid to throw ArgumentNullException"); + } + #endregion + + #region SetRegistryValue() tests + [Test] + public void CanSetRegistryValue() + { + Assert.DoesNotThrow(() => _registryWriter.SetRegistryValue(RegistryHive.CurrentUser, @"SOFTWARE\mRemoteNGTest", "TestKey", "A value string", RegistryValueKind.String)); + } + + [Test] + public void SetRegistryValueThrowAccessDenied() + { + Assert.Throws(() => _registryWriter.SetRegistryValue(RegistryHive.LocalMachine, @"SOFTWARE\mRemoteNGTest", "TestKey", "A value string", RegistryValueKind.String)); + } + #endregion } }