From 5f5700b948bfcf5ca8b1d865b02c778893dec54e Mon Sep 17 00:00:00 2001 From: Schmitti91 Date: Tue, 23 Jan 2024 12:54:43 +0100 Subject: [PATCH] extend Registry handling capabilities in preparation for Registry settings Enhanced the functionality of Registry handling in preparation for managing Registry settings --- mRemoteNG/Tools/WindowsRegistry/IRegistry.cs | 17 +- .../WindowsRegistry/IRegistryAdvanced.cs | 53 +++ .../WindowsRegistry/IRegistryAdvancedRead.cs | 47 +++ .../Tools/WindowsRegistry/IRegistryRead.cs | 14 +- .../Tools/WindowsRegistry/IRegistryWrite.cs | 10 +- .../Tools/WindowsRegistry/WindowsRegistry.cs | 147 ++++++- .../WindowsRegistryAdvanced.cs | 116 ++++++ .../WindowsRegistry/WindowsRegistryKey.cs | 135 +------ .../WindowsRegistryKeyBoolean.cs | 75 ++++ .../WindowsRegistryKeyInteger.cs | 78 ++++ .../WindowsRegistryKeyString.cs | 121 ++++++ .../Registry/WindowsRegistryAdvancedTests.cs | 181 +++++++++ .../Tools/Registry/WindowsRegistryKeyTests.cs | 374 ++++++++++++++++++ .../Tools/Registry/WindowsRegistryTests.cs | 32 +- 14 files changed, 1240 insertions(+), 160 deletions(-) create mode 100644 mRemoteNG/Tools/WindowsRegistry/IRegistryAdvanced.cs create mode 100644 mRemoteNG/Tools/WindowsRegistry/IRegistryAdvancedRead.cs create mode 100644 mRemoteNG/Tools/WindowsRegistry/WindowsRegistryAdvanced.cs create mode 100644 mRemoteNG/Tools/WindowsRegistry/WindowsRegistryKeyBoolean.cs create mode 100644 mRemoteNG/Tools/WindowsRegistry/WindowsRegistryKeyInteger.cs create mode 100644 mRemoteNG/Tools/WindowsRegistry/WindowsRegistryKeyString.cs create mode 100644 mRemoteNGTests/Tools/Registry/WindowsRegistryAdvancedTests.cs create mode 100644 mRemoteNGTests/Tools/Registry/WindowsRegistryKeyTests.cs diff --git a/mRemoteNG/Tools/WindowsRegistry/IRegistry.cs b/mRemoteNG/Tools/WindowsRegistry/IRegistry.cs index 77b0c799..c79aeae3 100644 --- a/mRemoteNG/Tools/WindowsRegistry/IRegistry.cs +++ b/mRemoteNG/Tools/WindowsRegistry/IRegistry.cs @@ -1,17 +1,21 @@ using Microsoft.Win32; +using System; using System.Collections.Generic; using System.Runtime.Versioning; namespace mRemoteNG.Tools.WindowsRegistry { [SupportedOSPlatform("windows")] + /// + /// Interface for the Registry class providing methods for interacting with the Windows Registry. + /// public interface IRegistry { #region registry reader string[] GetSubKeyNames(RegistryHive hive, string path); - - Optional GetPropertyValue(WindowsRegistryKey key); - Optional GetPropertyValue(RegistryHive hive, string path, string name); + string GetPropertyValue(WindowsRegistryKey key); + string GetPropertyValue(RegistryHive hive, string path, string name); + bool GetBoolValue(RegistryHive hive, string path, string propertyName, bool defaultValue = false); WindowsRegistryKey GetWindowsRegistryKey(RegistryHive hive, string path, string name); WindowsRegistryKey GetWindowsRegistryKey(WindowsRegistryKey key); @@ -24,12 +28,15 @@ namespace mRemoteNG.Tools.WindowsRegistry #region registry writer void SetRegistryValue(WindowsRegistryKey key); void SetRegistryValue(RegistryHive hive, string path, string name, object value, RegistryValueKind valueKind); + void DeleteRegistryKey(RegistryHive hive, string path, bool ignoreNotFound = false); #endregion - #region converter - RegistryHive ConvertStringToRegistryHive(string hiveString); + #region registry tools + RegistryHive ConvertStringToRegistryHive(string hiveString); RegistryValueKind ConvertStringToRegistryValueKind(string valueType); + RegistryValueKind ConvertTypeToRegistryValueKind(Type valueType); + Type ConvertRegistryValueKindToType(RegistryValueKind valueKind); #endregion } } \ No newline at end of file diff --git a/mRemoteNG/Tools/WindowsRegistry/IRegistryAdvanced.cs b/mRemoteNG/Tools/WindowsRegistry/IRegistryAdvanced.cs new file mode 100644 index 00000000..6cab5cc5 --- /dev/null +++ b/mRemoteNG/Tools/WindowsRegistry/IRegistryAdvanced.cs @@ -0,0 +1,53 @@ +using Microsoft.Win32; +using System; +using System.Collections.Generic; +using System.Runtime.Versioning; +using static mRemoteNG.Config.Settings.Registry.RegistryController; + +namespace mRemoteNG.Tools.WindowsRegistry +{ + [SupportedOSPlatform("windows")] + /// + /// Interface for the RegistryWorker class providing functionality to interact with the Windows Registry to retrieve registry settings. + /// + public interface IRegistryAdvanced + { + #region WindowsRegistry reader + string[] GetSubKeyNames(RegistryHive hive, string path); + string GetPropertyValue(WindowsRegistryKey key); + string 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 WindowsRegistry writer + void SetRegistryValue(WindowsRegistryKey key); + void SetRegistryValue(RegistryHive hive, string path, string name, object value, RegistryValueKind valueKind); + void DeleteRegistryKey(RegistryHive hive, string path, bool ignoreNotFound = false); + #endregion + + #region WindowsRegistry tools + RegistryHive ConvertStringToRegistryHive(string hiveString); + RegistryValueKind ConvertStringToRegistryValueKind(string valueType); + RegistryValueKind ConvertTypeToRegistryValueKind(Type valueType); + Type ConvertRegistryValueKindToType(RegistryValueKind valueKind); + #endregion + + #region WindowsRegistryAdvanced GetInteger + WindowsRegistryKeyInteger GetInteger(RegistryHive hive, string path, string propertyName, int? defaultValue = null); + #endregion + + #region WindowsRegistryAdvanced GetString + WindowsRegistryKeyString GetString(RegistryHive hive, string path, string propertyName, string defaultValue = null); + WindowsRegistryKeyString GetStringValidated(RegistryHive hive, string path, string propertyName, string[] allowedValues, bool caseSensitive = false, string defaultValue = null); + #endregion + + #region WindowsRegistryAdvanced GetBoolean + WindowsRegistryKeyBoolean GetBoolean(RegistryHive hive, string path, string propertyName, bool? defaultValue = null); + #endregion + } +} \ No newline at end of file diff --git a/mRemoteNG/Tools/WindowsRegistry/IRegistryAdvancedRead.cs b/mRemoteNG/Tools/WindowsRegistry/IRegistryAdvancedRead.cs new file mode 100644 index 00000000..ac9df674 --- /dev/null +++ b/mRemoteNG/Tools/WindowsRegistry/IRegistryAdvancedRead.cs @@ -0,0 +1,47 @@ +using Microsoft.Win32; +using System; +using System.Collections.Generic; +using System.Runtime.Versioning; +using static mRemoteNG.Config.Settings.Registry.RegistryController; + +namespace mRemoteNG.Tools.WindowsRegistry +{ + [SupportedOSPlatform("windows")] + /// + /// Interface for the RegistryWorker class providing functionality to interact with the Windows Registry to retrieve registry settings. + /// + public interface IRegistryAdvancedRead + { + #region WindowsRegistry reader + string[] GetSubKeyNames(RegistryHive hive, string path); + string GetPropertyValue(WindowsRegistryKey key); + string 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 WindowsRegistry tools + RegistryHive ConvertStringToRegistryHive(string hiveString); + RegistryValueKind ConvertStringToRegistryValueKind(string valueType); + RegistryValueKind ConvertTypeToRegistryValueKind(Type valueType); + Type ConvertRegistryValueKindToType(RegistryValueKind valueKind); + #endregion + + #region WindowsRegistryAdvanced GetInteger + WindowsRegistryKeyInteger GetInteger(RegistryHive hive, string path, string propertyName, int? defaultValue = null); + #endregion + + #region WindowsRegistryAdvanced GetString + WindowsRegistryKeyString GetString(RegistryHive hive, string path, string propertyName, string defaultValue = null); + WindowsRegistryKeyString GetStringValidated(RegistryHive hive, string path, string propertyName, string[] allowedValues, bool caseSensitive = false, string defaultValue = null); + #endregion + + #region WindowsRegistryAdvanced GetBoolean + WindowsRegistryKeyBoolean GetBoolean(RegistryHive hive, string path, string propertyName, bool? defaultValue = null); + #endregion + } +} \ No newline at end of file diff --git a/mRemoteNG/Tools/WindowsRegistry/IRegistryRead.cs b/mRemoteNG/Tools/WindowsRegistry/IRegistryRead.cs index 8c6dfbc3..356ba368 100644 --- a/mRemoteNG/Tools/WindowsRegistry/IRegistryRead.cs +++ b/mRemoteNG/Tools/WindowsRegistry/IRegistryRead.cs @@ -6,13 +6,17 @@ using System.Runtime.Versioning; namespace mRemoteNG.Tools.WindowsRegistry { [SupportedOSPlatform("windows")] + /// + /// Interface for the Registry class providing methods for interacting with read actions in the Windows Registry. + /// public interface IRegistryRead { #region registry reader string[] GetSubKeyNames(RegistryHive hive, string path); - Optional GetPropertyValue(WindowsRegistryKey key); - Optional GetPropertyValue(RegistryHive hive, string path, string name); + string GetPropertyValue(WindowsRegistryKey key); + string GetPropertyValue(RegistryHive hive, string path, string name); + bool GetBoolValue(RegistryHive hive, string path, string propertyName, bool defaultValue = false); WindowsRegistryKey GetWindowsRegistryKey(RegistryHive hive, string path, string name); WindowsRegistryKey GetWindowsRegistryKey(WindowsRegistryKey key); @@ -20,10 +24,12 @@ namespace mRemoteNG.Tools.WindowsRegistry List GetRegistryEntries(RegistryHive hive, string path); List GetRegistryEntryiesRecursive(RegistryHive hive, string path); #endregion - - #region converter + + #region registry tools RegistryHive ConvertStringToRegistryHive(string hiveString); RegistryValueKind ConvertStringToRegistryValueKind(string valueType); + RegistryValueKind ConvertTypeToRegistryValueKind(Type valueType); + Type ConvertRegistryValueKindToType(RegistryValueKind valueKind); #endregion } } \ No newline at end of file diff --git a/mRemoteNG/Tools/WindowsRegistry/IRegistryWrite.cs b/mRemoteNG/Tools/WindowsRegistry/IRegistryWrite.cs index 0d938532..edc5d510 100644 --- a/mRemoteNG/Tools/WindowsRegistry/IRegistryWrite.cs +++ b/mRemoteNG/Tools/WindowsRegistry/IRegistryWrite.cs @@ -1,9 +1,13 @@ using Microsoft.Win32; +using System; using System.Runtime.Versioning; namespace mRemoteNG.Tools.WindowsRegistry { [SupportedOSPlatform("windows")] + /// + /// Interface for the Registry class providing methods for interacting with write actions in the Windows Registry. + /// public interface IRegistryWrite { #region registry writer @@ -12,9 +16,11 @@ namespace mRemoteNG.Tools.WindowsRegistry #endregion - #region converter + #region registry tools RegistryHive ConvertStringToRegistryHive(string hiveString); RegistryValueKind ConvertStringToRegistryValueKind(string valueType); - #endregion} + RegistryValueKind ConvertTypeToRegistryValueKind(Type valueType); + Type ConvertRegistryValueKindToType(RegistryValueKind valueKind); + #endregion } } \ No newline at end of file diff --git a/mRemoteNG/Tools/WindowsRegistry/WindowsRegistry.cs b/mRemoteNG/Tools/WindowsRegistry/WindowsRegistry.cs index f0dc353a..9899adf7 100644 --- a/mRemoteNG/Tools/WindowsRegistry/WindowsRegistry.cs +++ b/mRemoteNG/Tools/WindowsRegistry/WindowsRegistry.cs @@ -40,7 +40,7 @@ namespace mRemoteNG.Tools.WindowsRegistry /// /// 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) + public string GetPropertyValue(WindowsRegistryKey key) { if (!key.IsKeyReadable()) throw new InvalidOperationException("The Windows Registry key is not ready for reading."); @@ -55,7 +55,7 @@ namespace mRemoteNG.Tools.WindowsRegistry /// 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) + public string GetPropertyValue(RegistryHive hive, string path, string name) { if (hive == 0) throw new ArgumentException("Unknown or unsupported RegistryHive value.", nameof(hive)); @@ -65,12 +65,41 @@ namespace mRemoteNG.Tools.WindowsRegistry using (var key = OpenSubKey(hive, path)) { if (!key.Any()) - return Optional.Empty; + return null; - return key.First().GetValue(name) as string; + var keyValue = key.First().GetValue(name); + + if (keyValue == null) + return null; + + return keyValue.ToString(); } } + /// + /// Gets a boolean value from the Windows Registry based on the specified registry path and property name. + /// If the value is not found or cannot be parsed, it returns a specified default value. + /// + /// The Registry hive where the value is located. + /// The registry path to the key containing the property. + /// The name of the property to retrieve. + /// The default value to return if the property is not found or cannot be parsed. Default is false. + /// The boolean value of the specified property or the default value if not found or cannot be parsed. + public bool GetBoolValue(RegistryHive hive, string path, string propertyName, bool defaultValue = false) + { + var value = GetPropertyValue(hive, path, propertyName); + + if (!string.IsNullOrEmpty(value)) + { + if (int.TryParse(value, out int intValue)) + return intValue == 1; + if (bool.TryParse(value, out bool boolValue)) + return boolValue; + } + + return defaultValue; + } + /// /// Retrieves a WindowsRegistryKey object for a specific registry hive, path, and value name. /// @@ -80,7 +109,7 @@ namespace mRemoteNG.Tools.WindowsRegistry /// A WindowsRegistryKey object representing the specified registry key and value. public WindowsRegistryKey GetWindowsRegistryKey(RegistryHive hive, string path, string name) { - WindowsRegistryKey key = new WindowsRegistryKey + WindowsRegistryKey key = new() { Hive = hive, Path = path, @@ -108,8 +137,7 @@ namespace mRemoteNG.Tools.WindowsRegistry if (value != null) key.Value = value.ToString(); - RegistryValueKind ValueKind; - if (TestValueKindExists(subKey, key.Name, out ValueKind)) + if (TestValueKindExists(subKey, key.Name, out RegistryValueKind ValueKind)) key.ValueKind = ValueKind; } } @@ -212,6 +240,32 @@ namespace mRemoteNG.Tools.WindowsRegistry { CreateOrSetRegistryValue(key); } + + /// + /// Deletes a registry key and its subkeys. + /// + /// The registry hive to open. + /// The path of the registry key to delete. + /// Set to true to ignore if the key is not found. + public void DeleteRegistryKey(RegistryHive hive, string path, bool ignoreNotFound = false) + { + try + { + using (RegistryKey key = RegistryKey.OpenBaseKey(hive, RegistryView.Default)) + { + if (key != null) + { + key.DeleteSubKeyTree(path, ignoreNotFound); + } + } + } + catch (Exception ex) + { + // Handle any exceptions according to your requirements + Console.WriteLine($"Error deleting registry key: {ex.Message}"); + throw; + } + } #endregion #region public methods @@ -304,6 +358,69 @@ namespace mRemoteNG.Tools.WindowsRegistry throw new ArgumentException("Invalid RegistryValueKind string representation.", nameof(valueType)); } } + + + /// + /// Converts a .NET data type to the corresponding RegistryValueKind. + /// + /// The .NET data type to convert. + /// The corresponding RegistryValueKind. + public 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. + public 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); + } + } #endregion #region private methods @@ -391,26 +508,18 @@ namespace mRemoteNG.Tools.WindowsRegistry } catch (SecurityException ex) { - // Handle or log SecurityException - // For example: log ex.Message - throw; + throw ex; } catch (IOException ex) { - // Handle or log IOException - // For example: log ex.Message - throw; + throw ex; } catch (UnauthorizedAccessException ex) { - // Handle or log UnauthorizedAccessException - // For example: log ex.Message - throw; + throw ex; } - catch (Exception ex) + catch (Exception) { - // For all other exceptions, log and rethrow - // For example: log ex.ToString() throw; } } diff --git a/mRemoteNG/Tools/WindowsRegistry/WindowsRegistryAdvanced.cs b/mRemoteNG/Tools/WindowsRegistry/WindowsRegistryAdvanced.cs new file mode 100644 index 00000000..92842956 --- /dev/null +++ b/mRemoteNG/Tools/WindowsRegistry/WindowsRegistryAdvanced.cs @@ -0,0 +1,116 @@ +using Microsoft.Win32; +using mRemoteNG.App.Info; +using mRemoteNG.Security.SymmetricEncryption; +using System.Runtime.Versioning; + +namespace mRemoteNG.Tools.WindowsRegistry +{ + [SupportedOSPlatform("windows")] + /// + /// Extends the functionality of interacting with the Windows Registry, building upon the base WindowsRegistry class. + /// + public class WindowsRegistryAdvanced : WindowsRegistry , IRegistryAdvanced, IRegistryAdvancedRead + { + #region dword methods + /// + /// Retrieves a DWORD (32-bit integer) value from the Windows Registry based on the specified registry information. + /// + /// The registry hive. + /// The path to the registry key. + /// The name of the registry property. + /// Optional default value to be used if the registry key is not present (default is null). + /// A WindowsRegistryKeyInteger instance representing the retrieved DWORD value. + public WindowsRegistryKeyInteger GetInteger(RegistryHive hive, string path, string propertyName, int? defaultValue = null) + { + // Retrieve the Windows Registry key + var key = GetWindowsRegistryKey(hive, path, propertyName); + + // Create a WindowsRegistryKeyInteger instance and initialize it from the retrieved key + WindowsRegistryKeyInteger IntKey = new(); + IntKey.ConvertFromWindowsRegistryKey(key); + + return IntKey; + } + #endregion + + #region string methods + /// + /// Retrieves a string value from the Windows Registry based on the specified registry information. + /// + /// The registry hive. + /// The path to the registry key. + /// The name of the registry property. + /// Optional default value to be used if the registry key is not present (default is null). + /// A WindowsRegistryKeyString instance representing the retrieved string value. + public WindowsRegistryKeyString GetString(RegistryHive hive, string path, string propertyName, string defaultValue = null) + { + // Retrieve the Windows Registry key + var key = GetWindowsRegistryKey(hive, path, propertyName); + + // Create a WindowsRegistryKeyString instance and initialize it from the retrieved key + WindowsRegistryKeyString StrKey = new(); + StrKey.ConvertFromWindowsRegistryKey(key, defaultValue); + + return StrKey; + } + + /// + /// Retrieves a string value from the Windows Registry based on the specified registry information and validates it against a set of allowed values. + /// + /// The registry hive. + /// The path to the registry key. + /// The name of the registry property. + /// An array of valid values against which the retrieved string is validated. + /// Optional parameter indicating whether the validation is case-sensitive (default is false). + /// A WindowsRegistryKeyString instance representing the retrieved and validated string value. + public WindowsRegistryKeyString GetStringValidated(RegistryHive hive, string path, string propertyName, string[] allowedValues, bool caseSensitive = false, string defaultValue = null) + { + // Retrieve the Windows Registry key + var key = GetWindowsRegistryKey(hive, path, propertyName); + + // Create a WindowsRegistryKeyString instance and initialize it from the retrieved key + WindowsRegistryKeyString StrKey = new(); + StrKey.AllowedValues = allowedValues; + StrKey.IsCaseSensitiveValidation = caseSensitive; + StrKey.ConvertFromWindowsRegistryKey(key, defaultValue); + + return StrKey; + } + + /*public WindowsRegistryKeySecureString GetSecureString(RegistryHive hive, string path, string propertyName) + { + // Retrieve the Windows Registry key, the key should be encrypted + var key = GetWindowsRegistryKey(hive, path, propertyName); + + // Create a WindowsRegistryKeyBoolean instance and initialize it from the retrieved key + WindowsRegistryKeySecureString secureKey = new (); // class not exsists + secureKey.ConvertFromWindowsRegistryKey(key); // no default possible! + return secureKey + }*/ + + #endregion + + #region bool methods + /// + /// Retrieves a boolean value from the Windows Registry based on the specified registry information. + /// + /// The registry hive. + /// The path to the registry key. + /// The name of the registry property. + /// An optional default value to use if the registry key is not present or if the value is not a valid boolean. + /// A WindowsRegistryKeyBoolean instance representing the retrieved boolean value. + public WindowsRegistryKeyBoolean GetBoolean(RegistryHive hive, string path, string propertyName, bool? defaultValue = null) + { + // Retrieve the Windows Registry key + var key = GetWindowsRegistryKey(hive, path, propertyName); + + // Create a WindowsRegistryKeyBoolean instance and initialize it from the retrieved key + WindowsRegistryKeyBoolean boolKey = new (); + boolKey.ConvertFromWindowsRegistryKey(key, defaultValue); + + return boolKey; + } + + #endregion + } +} \ No newline at end of file diff --git a/mRemoteNG/Tools/WindowsRegistry/WindowsRegistryKey.cs b/mRemoteNG/Tools/WindowsRegistry/WindowsRegistryKey.cs index 474cd026..f1308269 100644 --- a/mRemoteNG/Tools/WindowsRegistry/WindowsRegistryKey.cs +++ b/mRemoteNG/Tools/WindowsRegistry/WindowsRegistryKey.cs @@ -6,9 +6,8 @@ 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. + /// Represents a Windows Registry key with a default string value, providing a flexible abstraction for registry operations. + /// This class can be extended by inherited classes to customize behavior for specific data types. /// [SupportedOSPlatform("windows")] public class WindowsRegistryKey @@ -56,42 +55,22 @@ namespace mRemoteNG.Tools.WindowsRegistry private string _Name { get; set; } #endregion - #region Property valueKind - public RegistryValueKind ValueKind + #region Property value + public virtual string Value { - 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); + get => _value; + set + { + _value = value; + UpdateIsProvidedState(); } } - private RegistryValueKind _ValueKind; + private string _value; #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 RegistryValueKind ValueKind { get; set; } = RegistryValueKind.Unknown; - public string Value { get; set; } + public bool IsKeyPresent { get; set; } = false; #endregion #region public methods @@ -118,94 +97,20 @@ namespace mRemoteNG.Tools.WindowsRegistry } #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) + #region protected methods + protected void UpdateIsProvidedState() { - 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 - } + // Key is present when RegistryKey value is not null + IsKeyPresent = Value != null; } - /// - /// 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); - } - } + protected bool IsHiveSet() => Hive != 0; - private bool IsHiveSet() - { - return Hive != 0; - } + protected bool IsValueKindSet() => ValueKind != 0; - private bool IsValueKindSet() - { - return ValueKind != 0; - } + protected bool IsPathSet() => Path != null; - private bool IsPathSet() - { - return Path != null; ; - //return !string.IsNullOrEmpty(Path); - } - - private bool IsNameSet() - { - return Name != null; - } - - private bool IsValueSet() - { - return !string.IsNullOrEmpty(Value); - } + protected bool IsNameSet() => Name != null; #endregion } } diff --git a/mRemoteNG/Tools/WindowsRegistry/WindowsRegistryKeyBoolean.cs b/mRemoteNG/Tools/WindowsRegistry/WindowsRegistryKeyBoolean.cs new file mode 100644 index 00000000..aad4265d --- /dev/null +++ b/mRemoteNG/Tools/WindowsRegistry/WindowsRegistryKeyBoolean.cs @@ -0,0 +1,75 @@ +using System; +using System.Runtime.Versioning; + +namespace mRemoteNG.Tools.WindowsRegistry +{ + /// + /// Represents a boolean Windows Registry key, extending the base class WindowsRegistryKey. + /// + [SupportedOSPlatform("windows")] + public class WindowsRegistryKeyBoolean : WindowsRegistryKey + { + /// + /// Gets or sets the default boolean value for a Windows Registry key. + /// + /// + /// The default value is initially set to `false`. + /// + public bool DefaultValue { get; private set; } = false; + + /// + /// Gets or sets the boolean value for a Windows Registry key. + /// + public new bool Value + { + get => BoolValue; + private set + { + BoolValue = value; + UpdateIsProvidedState(); + } + } + private bool BoolValue; + + /// + /// Converts and initializes a WindowsRegistryKeyBoolean from a base WindowsRegistryKey, with an optional default value. + /// + /// The base WindowsRegistryKey to convert from. + /// Optional default value to set for the WindowsRegistryKeyBoolean. + public void ConvertFromWindowsRegistryKey(WindowsRegistryKey baseKey, bool? defaultValue = null) + { + SetDefaultValue(defaultValue); + FromBaseKey(baseKey); + } + + private void FromBaseKey(WindowsRegistryKey baseKey) + { + if (baseKey == null) + throw new ArgumentNullException(nameof(baseKey)); + + Hive = baseKey.Hive; + Path = baseKey.Path; + Name = baseKey.Name; + ValueKind = baseKey.ValueKind; + IsKeyPresent = baseKey.IsKeyPresent; + + ConvertToBool(baseKey.Value); + } + + private void SetDefaultValue(bool? defaultValue) + { + if (defaultValue.HasValue) + DefaultValue = (bool)defaultValue; + } + + private void ConvertToBool(string newValue) + { + if (IsKeyPresent && bool.TryParse(newValue, out bool boolValue)) + BoolValue = boolValue; + else if (IsKeyPresent && int.TryParse(newValue, out int intValue)) + BoolValue = intValue == 1; + else + BoolValue = DefaultValue; + } + } +} diff --git a/mRemoteNG/Tools/WindowsRegistry/WindowsRegistryKeyInteger.cs b/mRemoteNG/Tools/WindowsRegistry/WindowsRegistryKeyInteger.cs new file mode 100644 index 00000000..aeb6818d --- /dev/null +++ b/mRemoteNG/Tools/WindowsRegistry/WindowsRegistryKeyInteger.cs @@ -0,0 +1,78 @@ +using Microsoft.Win32; +using System; +using System.Runtime.Versioning; + +namespace mRemoteNG.Tools.WindowsRegistry +{ + /// + /// Represents a integer Windows Registry key, extending the base class WindowsRegistryKey. + /// + [SupportedOSPlatform("windows")] + public class WindowsRegistryKeyInteger : WindowsRegistryKey + { + /// + /// Gets or sets the default integer value for a Windows Registry key. + /// + /// + /// The default value is initially set to `-1`. + /// + public int DefaultValue { get; private set; } = -1; + + + /// + /// Gets or sets the integer value for a Windows Registry key. + /// + public new int Value + { + get => IntegerValue; + private set + { + IntegerValue = value; + UpdateIsProvidedState(); + } + } + private int IntegerValue; + + /// + /// Converts and initializes a WindowsRegistryKeyInteger from a base WindowsRegistryKey, with an optional default value. + /// + /// The base WindowsRegistryKey to convert from. + /// Optional default value to set for the WindowsRegistryKeyBoolean. + public void ConvertFromWindowsRegistryKey(WindowsRegistryKey baseKey, int? defaultValue = null) + { + SetDefaultValue(defaultValue); + FromBaseKey(baseKey); + } + + private void FromBaseKey(WindowsRegistryKey baseKey) + { + if (baseKey == null) + throw new ArgumentNullException(nameof(baseKey)); + + Hive = baseKey.Hive; + Path = baseKey.Path; + Name = baseKey.Name; + ValueKind = baseKey.ValueKind; + IsKeyPresent = baseKey.IsKeyPresent; + + ConvertToInteger(baseKey.Value); + } + + private void SetDefaultValue (int? defaultValue) + { + if (defaultValue.HasValue) + DefaultValue = (int)defaultValue; + } + + private void ConvertToInteger(string newValue) + { + if (ValueKind != RegistryValueKind.DWord) + IsKeyPresent = false; + + if (IsKeyPresent && int.TryParse(newValue.ToString(), out int intValue)) + IntegerValue = intValue; + else + IntegerValue = DefaultValue; + } + } +} diff --git a/mRemoteNG/Tools/WindowsRegistry/WindowsRegistryKeyString.cs b/mRemoteNG/Tools/WindowsRegistry/WindowsRegistryKeyString.cs new file mode 100644 index 00000000..d616754d --- /dev/null +++ b/mRemoteNG/Tools/WindowsRegistry/WindowsRegistryKeyString.cs @@ -0,0 +1,121 @@ +using Microsoft.Win32; +using System; +using System.Linq; +using System.Runtime.Versioning; + +namespace mRemoteNG.Tools.WindowsRegistry +{ + /// + /// Represents a string Windows Registry key, extending the base class WindowsRegistryKey, can be evaluated with a value set. + /// + [SupportedOSPlatform("windows")] + public class WindowsRegistryKeyString : WindowsRegistryKey + { + /// + /// Gets or sets the default integer value for a Windows Registry key. + /// + public string DefaultValue { get; private set; } + + /// + /// Gets or sets an array of allowed values for validation. + /// + public string[] AllowedValues { get; set; } + + /// + /// Gets or sets a boolean flag indicating whether validation is case-sensitive. + /// + public bool IsCaseSensitiveValidation { get; set; } = false; + + /// + /// Gets a boolean indicating whether the value is valid based on the validation rules. + /// + public bool IsValid { get; private set; } = false; + + + public new string Value + { + get => StringValue; + private set + { + StringValue = value; + UpdateIsProvidedState(); + Validate(); + } + } + private string StringValue; + + /// + /// Converts and initializes a WindowsRegistryKeyString from a base WindowsRegistryKey, with an optional default value. + /// + /// The base WindowsRegistryKey to convert from. + /// Optional default value to set for the WindowsRegistryKeyBoolean. + public void ConvertFromWindowsRegistryKey(WindowsRegistryKey baseKey, string defaultValue = null) + { + SetDefaultValue(defaultValue); + FromBaseKey(baseKey); + Validate(); + } + + private void FromBaseKey(WindowsRegistryKey baseKey) + { + if (baseKey == null) + throw new ArgumentNullException(nameof(baseKey)); + + Hive = baseKey.Hive; + Path = baseKey.Path; + Name = baseKey.Name; + ValueKind = baseKey.ValueKind; + IsKeyPresent = baseKey.IsKeyPresent; + + ConvertToString(baseKey.Value); + } + + private void SetDefaultValue (string defaultValue) + { + DefaultValue = defaultValue; + } + private void ConvertToString(string newValue) + { + if (IsKeyPresent && newValue != null) + StringValue = newValue; + else + StringValue = DefaultValue; + } + + /// + /// Validates a Windows Registry key value against a set of allowed values, considering case sensitivity. + /// + /// Array of allowed values. + /// Optional parameter to specify case sensitivity in validation. + public void Validate(string[] allowedValues = null, bool? caseSensitive = null) + { + // Key must be present to evaluate + if (!IsKeyPresent) + return; + + if (caseSensitive.HasValue) + IsCaseSensitiveValidation = caseSensitive.Value; + + if (allowedValues != null && allowedValues.Length >= 1) + AllowedValues = allowedValues; + + // AllowedValues array cannot be null or empty. + if (AllowedValues == null || AllowedValues.Length == 0 || !IsKeyPresent) + return; + + if (IsKeyPresent && AllowedValues.Any(v => + IsCaseSensitiveValidation ? v == Value : v.Equals(Value, StringComparison.OrdinalIgnoreCase))) + { + // Set to true when the value is found in the valid values + IsValid = true; + } + else + { + // Set to false when the value is not found in the valid values + IsValid = false; + StringValue = DefaultValue; + } + } + + } +} diff --git a/mRemoteNGTests/Tools/Registry/WindowsRegistryAdvancedTests.cs b/mRemoteNGTests/Tools/Registry/WindowsRegistryAdvancedTests.cs new file mode 100644 index 00000000..820a11b3 --- /dev/null +++ b/mRemoteNGTests/Tools/Registry/WindowsRegistryAdvancedTests.cs @@ -0,0 +1,181 @@ +using Microsoft.Win32; +using mRemoteNG.Tools.WindowsRegistry; +using NUnit.Framework; + +namespace mRemoteNGTests.Tools.Registry +{ + internal class WindowsRegistryAdvancedTests : WindowsRegistryAdvanced + { + private const string _TestRootKey = @"Software\mRemoteNGTest"; + private const RegistryHive _TestHive = RegistryHive.CurrentUser; + + [SetUp] + public void Setup() + { + // GetBoolean && GetBoolValue (GetBoolValue -> Not Advanced but not tested jet) + SetRegistryValue(_TestHive, _TestRootKey, "TestBoolAsString", "true", RegistryValueKind.String); + SetRegistryValue(_TestHive, _TestRootKey, "TestBoolAsDWord", 0, RegistryValueKind.DWord); + + // GetInteger Tests + SetRegistryValue(_TestHive, _TestRootKey, "TestInteger", "4711", RegistryValueKind.DWord); + + // GetString Tests + SetRegistryValue(_TestHive, _TestRootKey, "TestString1", "Banane", RegistryValueKind.String); + SetRegistryValue(_TestHive, _TestRootKey, "TestString2", "Hund", RegistryValueKind.String); + } + + [TearDown] + public void Cleanup() + { + // Delete the registry keys here + DeleteRegistryKey(_TestHive, _TestRootKey, true); + } + + #region GetBoolean() Tests + // Non object returns + [Test] + public void GetBooleanFromString_ReturnsTrue() + { + var key = GetBoolean(_TestHive, _TestRootKey, "TestBoolAsString"); + Assert.That(key.Value, Is.EqualTo(true)); + } + + + [Test] + public void GetBooleanFromDword_ReturnsFalse() + { + var key = GetBoolean(_TestHive, _TestRootKey, "TestBoolAsDWord"); + Assert.That(key.Value, Is.EqualTo(false)); + } + + [Test] + public void GetBooleanNotProvided_ReturnsDefaultTrue() + { + var key = GetBoolean(_TestHive, _TestRootKey, "TestBoolNotProvided", true); + Assert.Multiple(() => + { + Assert.That(key.Value, Is.EqualTo(true), "Value should be the default (true)"); + Assert.That(key.IsKeyPresent, Is.EqualTo(false), "IsProvided should be false"); + }); + } + #endregion + + #region GetBoolValue()___No Object, just bool value returns + [Test] + public void GetBoolValueFromString_ReturnsTrue() + { + var key = GetBoolValue(_TestHive, _TestRootKey, "TestBoolAsString"); + Assert.That(key, Is.EqualTo(true)); + } + [Test] + public void GetBoolValueFromDword_ReturnsFalse() + { + var key = GetBoolValue(_TestHive, _TestRootKey, "TestBoolAsDWord", true); + Assert.That(key, Is.EqualTo(false)); + } + [Test] + public void GetBoolValue_ReturnsDefaultTrue() + { + var key = GetBoolValue(_TestHive, _TestRootKey, "TestBoolNotProvided", true); + Assert.That(key, Is.EqualTo(true)); + } + #endregion + + #region GetInteger() + [Test] + public void GetInteger() + { + var key = GetInteger(_TestHive, _TestRootKey, "TestInteger"); + Assert.Multiple(() => + { + Assert.That(key.Value, Is.EqualTo(4711)); + Assert.That(key.IsKeyPresent, Is.EqualTo(true)); + }); + } + [Test] + public void GetInteger_returnObjectDefault() + { + var key = GetInteger(_TestHive, _TestRootKey, "TestIntegerNotProvided"); + Assert.Multiple(() => + { + Assert.That(key.Value, Is.EqualTo(-1), "Value should be the default (-1)"); + Assert.That(key.IsKeyPresent, Is.EqualTo(false)); + }); + } + + [Test] + public void GetInteger_returnSpecifiedDefault() + { + var key = GetInteger(_TestHive, _TestRootKey, "TestIntegerNotProvided", 2096); + Assert.Multiple(() => + { + Assert.That(key.Value, Is.EqualTo(-1), "Value should be the default (-1)"); + Assert.That(key.IsKeyPresent, Is.EqualTo(false)); + }); + } + #endregion + + #region GetString() + [Test] + public void GetString() + { + var key = GetString(_TestHive, _TestRootKey, "TestString1"); + Assert.Multiple(() => + { + Assert.That(key.Value, Is.EqualTo("Banane")); + Assert.That(key.IsKeyPresent, Is.EqualTo(true)); + }); + } + + [Test] + public void GetString_ReturnsDefault() + { + var key = GetString(_TestHive, _TestRootKey, "TestStringNotProvided", "Banane"); + Assert.Multiple(() => + { + Assert.That(key.Value, Is.EqualTo("Banane")); + Assert.That(key.IsKeyPresent, Is.EqualTo(false)); + }); + } + + [Test] + public void GetStringValidated_Valid() + { + string[] fruits = { "Banane", "Erdbeere", "Apfel" }; + var key = GetStringValidated(_TestHive, _TestRootKey, "TestString1", fruits); + Assert.Multiple(() => + { + Assert.That(key.Value, Is.EqualTo("Banane")); + Assert.That(key.IsKeyPresent, Is.EqualTo(true)); + Assert.That(key.IsValid, Is.EqualTo(true)); + }); + } + + [Test] + public void GetStringValidated_NotValidNull() + { + string[] fruits = { "Banane", "Erdbeere", "Apfel" }; + var key = GetStringValidated(_TestHive, _TestRootKey, "TestString2", fruits); + Assert.Multiple(() => + { + Assert.That(key.Value, Is.EqualTo(null)); + Assert.That(key.IsKeyPresent, Is.EqualTo(true)); + Assert.That(key.IsValid, Is.EqualTo(false)); + }); + } + + [Test] + public void GetStringValidated_NotValidDefault() + { + string[] fruits = { "Banane", "Erdbeere", "Apfel" }; + var key = GetStringValidated(_TestHive, _TestRootKey, "TestString2", fruits, false, "Banane"); + Assert.Multiple(() => + { + Assert.That(key.Value, Is.EqualTo("Banane")); + Assert.That(key.IsKeyPresent, Is.EqualTo(true)); + Assert.That(key.IsValid, Is.EqualTo(false)); + }); + } + #endregion + } +} diff --git a/mRemoteNGTests/Tools/Registry/WindowsRegistryKeyTests.cs b/mRemoteNGTests/Tools/Registry/WindowsRegistryKeyTests.cs new file mode 100644 index 00000000..717b8239 --- /dev/null +++ b/mRemoteNGTests/Tools/Registry/WindowsRegistryKeyTests.cs @@ -0,0 +1,374 @@ +using Microsoft.Win32; +using mRemoteNG.Tools.WindowsRegistry; +using NUnit.Framework; +using static System.Windows.Forms.VisualStyles.VisualStyleElement.Rebar; + +namespace mRemoteNGTests.Tools.Registry +{ + internal class WindowsRegistryKeyTests + { + private WindowsRegistryKey CompleteRegistryKey { get; set; } + private WindowsRegistryKey PartialRegistryKey { get; set; } + + [SetUp] + public void Setup() + { + CompleteRegistryKey = new WindowsRegistryKey() + { + Hive = RegistryHive.CurrentUser, + ValueKind = RegistryValueKind.String, + Name = "Test", + Path = @"SOFTWARE\TEST\TEST\Test", + Value = "CompleteRegistryKey" + }; + + PartialRegistryKey = new WindowsRegistryKey() + { + Hive = RegistryHive.CurrentUser, + ValueKind = RegistryValueKind.DWord, + }; + } + + #region WindowsRegistryKey() tests + [Test] + public void WindowsRegistryKeyReadable() + { + Assert.That(CompleteRegistryKey.IsKeyReadable, Is.EqualTo(true)); + } + + [Test] + public void WindowsRegistryKeyNotReadable() + { + Assert.That(PartialRegistryKey.IsKeyReadable, Is.EqualTo(false)); + } + + [Test] + public void WindowsRegistryKeyWriteable() + { + Assert.That(CompleteRegistryKey.IsKeyWritable, Is.EqualTo(true)); + } + + [Test] + public void WindowsRegistryKeyNotWriteable() + { + Assert.That(PartialRegistryKey.IsKeyWritable, Is.EqualTo(false)); + } + + [Test] + public void WindowsRegistryKeyProvided() + { + Assert.That(CompleteRegistryKey.IsKeyPresent, Is.EqualTo(true)); + } + + [Test] + public void WindowsRegistryKeyNotProvided() + { + Assert.That(PartialRegistryKey.IsKeyPresent, Is.EqualTo(false)); + } + #endregion + + #region WindowsRegistryKeyBoolean tests + [Test] + public void WindowsRegistryKeyBoolean_FromStringTrue() + { + + WindowsRegistryKey TestKey = new() + { + Hive = RegistryHive.CurrentUser, + ValueKind = RegistryValueKind.String, + Name = "TestBoolString", + Path = @"SOFTWARE\Test", + Value = "true" + }; + + WindowsRegistryKeyBoolean boolKey = new (); + boolKey.ConvertFromWindowsRegistryKey(TestKey); + + Assert.That(boolKey.IsKeyPresent, Is.EqualTo(true)); + Assert.That(boolKey.Value, Is.EqualTo(true)); + } + + [Test] + public void WindowsRegistryKeyBoolean_FromStringFalse() + { + + WindowsRegistryKey TestKey = new() + { + Hive = RegistryHive.CurrentUser, + ValueKind = RegistryValueKind.String, + Name = "TestBoolString", + Path = @"SOFTWARE\Test", + Value = "false" + }; + + WindowsRegistryKeyBoolean boolKey = new(); + boolKey.ConvertFromWindowsRegistryKey(TestKey); + + Assert.That(boolKey.IsKeyPresent, Is.EqualTo(true)); + Assert.That(boolKey.Value, Is.EqualTo(false)); + } + + [Test] + public void WindowsRegistryKeyBoolean_FromDwordTrue() + { + + WindowsRegistryKey TestKey = new() + { + Hive = RegistryHive.CurrentUser, + ValueKind = RegistryValueKind.DWord, + Name = "TestBoolString", + Path = @"SOFTWARE\Test", + Value = "1" + }; + + WindowsRegistryKeyBoolean boolKey = new(); + boolKey.ConvertFromWindowsRegistryKey(TestKey); + + Assert.That(boolKey.IsKeyPresent, Is.EqualTo(true)); + Assert.That(boolKey.Value, Is.EqualTo(true)); + } + + [Test] + public void WindowsRegistryKeyBoolean_FromDwordFalse() + { + + WindowsRegistryKey TestKey = new() + { + Hive = RegistryHive.CurrentUser, + ValueKind = RegistryValueKind.DWord, + Name = "TestBoolString", + Path = @"SOFTWARE\Test", + Value = "0" + }; + + WindowsRegistryKeyBoolean boolKey = new(); + boolKey.ConvertFromWindowsRegistryKey(TestKey); + + Assert.That(boolKey.IsKeyPresent, Is.EqualTo(true)); + Assert.That(boolKey.Value, Is.EqualTo(false)); + } + + [Test] + public void WindowsRegistryKeyBoolean_ReturnDefault() + { + WindowsRegistryKey TestKey = new() + { + Hive = RegistryHive.CurrentUser, + ValueKind = RegistryValueKind.DWord, + Name = "TestBoolString", + Path = @"SOFTWARE\Test", + Value = null + }; + + WindowsRegistryKeyBoolean boolKey = new(); + boolKey.ConvertFromWindowsRegistryKey(TestKey, true); + + Assert.That(boolKey.IsKeyPresent, Is.EqualTo(false)); + Assert.That(boolKey.Value, Is.EqualTo(true)); + } + #endregion + + #region WindowsRegistryKeyInteger tests + [Test] + public void WindowsRegistryKeyInteger() + { + WindowsRegistryKey TestKey = new() + { + Hive = RegistryHive.CurrentUser, + ValueKind = RegistryValueKind.DWord, + Name = "TestIntigerString", + Path = @"SOFTWARE\Test", + Value = "4711" + }; + + WindowsRegistryKeyInteger IntKey = new(); + IntKey.ConvertFromWindowsRegistryKey(TestKey); + + Assert.That(IntKey.IsKeyPresent, Is.EqualTo(true)); + Assert.That(IntKey.Value, Is.EqualTo(4711)); + } + [Test] + public void WindowsRegistryKeyInteger_ReturnDefault() + { + WindowsRegistryKey TestKey = new() + { + Hive = RegistryHive.CurrentUser, + ValueKind = RegistryValueKind.DWord, + Name = "TestIntigerString", + Path = @"SOFTWARE\Test", + Value = null + }; + + WindowsRegistryKeyInteger IntKey = new(); + IntKey.ConvertFromWindowsRegistryKey(TestKey, 2096); + + Assert.That(IntKey.IsKeyPresent, Is.EqualTo(false)); + Assert.That(IntKey.Value, Is.EqualTo(2096)); + } + #endregion + + #region WindowsRegistryKeyString tests + [Test] + public void WindowsRegistryKeyString() + { + WindowsRegistryKey TestKey = new() + { + Hive = RegistryHive.CurrentUser, + ValueKind = RegistryValueKind.DWord, + Name = "TestRegString", + Path = @"SOFTWARE\Test", + Value = "The Big Bang Theory" + }; + + WindowsRegistryKeyString StrKey = new(); + StrKey.ConvertFromWindowsRegistryKey(TestKey); + + Assert.That(StrKey.IsKeyPresent, Is.EqualTo(true)); + Assert.That(StrKey.Value, Is.EqualTo("The Big Bang Theory")); + } + [Test] + public void WindowsRegistryKeyString_ReturnDefault() + { + WindowsRegistryKey TestKey = new() + { + Hive = RegistryHive.CurrentUser, + ValueKind = RegistryValueKind.DWord, + Name = "TestRegString", + Path = @"SOFTWARE\Test", + Value = null + }; + + WindowsRegistryKeyString StrKey = new(); + StrKey.ConvertFromWindowsRegistryKey(TestKey, "South Park"); + + Assert.That(StrKey.IsKeyPresent, Is.EqualTo(false)); + Assert.That(StrKey.Value, Is.EqualTo("South Park")); + } + + [Test] + public void WindowsRegistryKeyString_ValidateSuccess() + { + WindowsRegistryKey TestKey = new() + { + Hive = RegistryHive.CurrentUser, + ValueKind = RegistryValueKind.DWord, + Name = "TestRegString", + Path = @"SOFTWARE\Test", + Value = "Big Bang" + }; + + WindowsRegistryKeyString StrKey = new(); + StrKey.AllowedValues = new[] { "Big Bang", "Big Bang Theory", "The Big Bang Theory" }; + StrKey.ConvertFromWindowsRegistryKey(TestKey); + + Assert.That(StrKey.IsKeyPresent, Is.EqualTo(true)); + Assert.That(StrKey.IsValid, Is.EqualTo(true)); + } + + [Test] + public void WindowsRegistryKeyString_ValidateNotSuccess() + { + WindowsRegistryKey TestKey = new() + { + Hive = RegistryHive.CurrentUser, + ValueKind = RegistryValueKind.DWord, + Name = "TestRegString", + Path = @"SOFTWARE\Test", + Value = "ig ang" + }; + + WindowsRegistryKeyString StrKey = new(); + StrKey.AllowedValues = new[] { "Big Bang", "Big Bang Theory", "The Big Bang Theory" }; + StrKey.ConvertFromWindowsRegistryKey(TestKey); + + Assert.That(StrKey.IsKeyPresent, Is.EqualTo(true)); + Assert.That(StrKey.IsValid, Is.EqualTo(false)); + } + + [Test] + public void WindowsRegistryKeyString_ValidateSuccessCase() + { + WindowsRegistryKey TestKey = new() + { + Hive = RegistryHive.CurrentUser, + ValueKind = RegistryValueKind.DWord, + Name = "TestRegString", + Path = @"SOFTWARE\Test", + Value = "BiG BAng" + }; + + WindowsRegistryKeyString StrKey = new(); + StrKey.AllowedValues = new[] { "BiG BAng", "Big Bang Theory", "The Big Bang Theory" }; + StrKey.IsCaseSensitiveValidation = true; + StrKey.ConvertFromWindowsRegistryKey(TestKey); + + Assert.That(StrKey.IsKeyPresent, Is.EqualTo(true)); + Assert.That(StrKey.IsValid, Is.EqualTo(true)); + } + + [Test] + public void WindowsRegistryKeyString_ValidateNotSuccessCase() + { + WindowsRegistryKey TestKey = new() + { + Hive = RegistryHive.CurrentUser, + ValueKind = RegistryValueKind.DWord, + Name = "TestRegString", + Path = @"SOFTWARE\Test", + Value = "BiG BAng" + }; + + WindowsRegistryKeyString StrKey = new(); + StrKey.AllowedValues = new[] { "Big Bang", "Big Bang Theory", "The Big Bang Theory" }; + StrKey.IsCaseSensitiveValidation = true; + StrKey.ConvertFromWindowsRegistryKey(TestKey); + + Assert.That(StrKey.IsKeyPresent, Is.EqualTo(true)); + Assert.That(StrKey.IsValid, Is.EqualTo(false)); + } + + [Test] + public void WindowsRegistryKeyString_ValidateNotSuccessReturnNull() + { + WindowsRegistryKey TestKey = new() + { + Hive = RegistryHive.CurrentUser, + ValueKind = RegistryValueKind.DWord, + Name = "TestRegString", + Path = @"SOFTWARE\Test", + Value = "ig ang" + }; + + WindowsRegistryKeyString StrKey = new(); + StrKey.AllowedValues = new[] { "Big Bang", "Big Bang Theory", "The Big Bang Theory" }; + StrKey.ConvertFromWindowsRegistryKey(TestKey); + + Assert.That(StrKey.IsKeyPresent, Is.EqualTo(true)); + Assert.That(StrKey.IsValid, Is.EqualTo(false)); + Assert.That(StrKey.Value, Is.EqualTo(null)); + } + + [Test] + public void WindowsRegistryKeyString_ValidateNotSuccessValidValue() + { + WindowsRegistryKey TestKey = new() + { + Hive = RegistryHive.CurrentUser, + ValueKind = RegistryValueKind.DWord, + Name = "TestRegString", + Path = @"SOFTWARE\Test", + Value = "ig ang" + }; + + WindowsRegistryKeyString StrKey = new(); + StrKey.AllowedValues = new[] { "Big Bang", "Big Bang Theory", "The Big Bang Theory" }; + StrKey.ConvertFromWindowsRegistryKey(TestKey, "Big Bang Theory"); + + Assert.That(StrKey.IsKeyPresent, Is.EqualTo(true)); + Assert.That(StrKey.IsValid, Is.EqualTo(false)); + Assert.That(StrKey.Value, Is.EqualTo("Big Bang Theory")); + } + + #endregion + } +} diff --git a/mRemoteNGTests/Tools/Registry/WindowsRegistryTests.cs b/mRemoteNGTests/Tools/Registry/WindowsRegistryTests.cs index 7007de7a..2bf2d06c 100644 --- a/mRemoteNGTests/Tools/Registry/WindowsRegistryTests.cs +++ b/mRemoteNGTests/Tools/Registry/WindowsRegistryTests.cs @@ -1,6 +1,7 @@ using System; using System.Collections.Generic; using System.Linq; +using System.Windows.Forms; using Microsoft.Win32; using mRemoteNG.Tools.WindowsRegistry; using NUnit.Framework; @@ -9,14 +10,12 @@ namespace mRemoteNGTests.Tools.Registry { public class WindowsRegistryTests { - private IRegistry _registry; private IRegistryRead _registryReader; private IRegistryWrite _registryWriter; [SetUp] public void Setup() { - _registry = new WindowsRegistry(); _registryReader = new WindowsRegistry(); _registryWriter = new WindowsRegistry(); } @@ -28,11 +27,13 @@ namespace mRemoteNGTests.Tools.Registry var subKeyNames = _registryReader.GetSubKeyNames(RegistryHive.CurrentUser, "Software"); Assert.That(subKeyNames, Does.Contain("Microsoft")); } + [Test] public void GetSubkeyNamesThrowsIfGivenNullKeyPath() { Assert.Throws(() => _registryReader.GetSubKeyNames(RegistryHive.CurrentUser, null)); } + [Test] public void GetSubkeyNamesThrowsIfGivenUnknownHive() { @@ -45,13 +46,13 @@ namespace mRemoteNGTests.Tools.Registry public void CanGetPropertyValue() { var keyValue = _registryReader.GetPropertyValue(RegistryHive.ClassesRoot, @".dll\PersistentHandler", ""); - Assert.That(keyValue.FirstOrDefault(), Is.EqualTo("{098f2470-bae0-11cd-b579-08002b30bfeb}")); + Assert.That(keyValue, Is.EqualTo("{098f2470-bae0-11cd-b579-08002b30bfeb}")); } [Test] public void CanGetPropertyValueByRegistryKeyObject() { - WindowsRegistryKey key = new WindowsRegistryKey + WindowsRegistryKey key = new() { Hive = RegistryHive.ClassesRoot, Path = @".dll\PersistentHandler", @@ -59,7 +60,7 @@ namespace mRemoteNGTests.Tools.Registry }; var keyValue = _registryReader.GetPropertyValue(key); - Assert.That(keyValue.FirstOrDefault(), Is.EqualTo("{098f2470-bae0-11cd-b579-08002b30bfeb}")); + Assert.That(keyValue, Is.EqualTo("{098f2470-bae0-11cd-b579-08002b30bfeb}")); } [Test] public void GetPropertyValueThrowsIfGivenNullKeyPath() @@ -85,7 +86,7 @@ namespace mRemoteNGTests.Tools.Registry [Test] public void CanGetWindowsRegistryKeyByObject() { - WindowsRegistryKey key = new WindowsRegistryKey + WindowsRegistryKey key = new() { Hive = RegistryHive.ClassesRoot, Path = @".dll\PersistentHandler", @@ -107,11 +108,11 @@ namespace mRemoteNGTests.Tools.Registry [Test] public void GetWindowsRegistryThrowNotReadable() { - WindowsRegistryKey key = new WindowsRegistryKey + WindowsRegistryKey key = new() { Hive = RegistryHive.ClassesRoot, }; - + Assert.Throws(() => _registryReader.GetWindowsRegistryKey(key)); } #endregion @@ -137,7 +138,7 @@ namespace mRemoteNGTests.Tools.Registry public void IsWindowsRegistryKeyValid() { // Tests property rules of WindowsRegistryKey - WindowsRegistryKey key = new WindowsRegistryKey(); + WindowsRegistryKey key = new(); Assert.Multiple(() => { @@ -152,26 +153,27 @@ namespace mRemoteNGTests.Tools.Registry [Test] public void WindowsRegistryKeyThrowHiveNullException() { - WindowsRegistryKey key = new WindowsRegistryKey(); + WindowsRegistryKey key = new(); Assert.Throws(() => key.Hive = 0, "Expected IsHiveValid to throw ArgumentNullException"); } [Test] - public void WindowsRegistryKeyThrowValueKindNullException() + public void WindowsRegistryKeyValueKindUnknown() { - WindowsRegistryKey key = new WindowsRegistryKey(); - Assert.Throws(() => key.ValueKind = 0, "Expected IsValueKindValid to throw ArgumentNullException"); + WindowsRegistryKey key = new(); + Assert.That(key.ValueKind, Is.EqualTo(RegistryValueKind.Unknown)); + } [Test] public void WindowsRegistryKeyThrowPathNullException() { - WindowsRegistryKey key = new WindowsRegistryKey(); + WindowsRegistryKey key = new(); Assert.Throws(() => key.Path = null, "Expected IsPathValid to throw ArgumentNullException"); } [Test] public void WindowsRegistryKeyThrowNameNullException() { - WindowsRegistryKey key = new WindowsRegistryKey(); + WindowsRegistryKey key = new(); Assert.Throws(() => key.Name = null, "Expected IsNameValid to throw ArgumentNullException"); } #endregion