mirror of
https://github.com/mRemoteNG/mRemoteNG.git
synced 2026-02-17 14:07:46 +08:00
mRemoteNG tools WindowsRegistry has been revised and the Windows Registry reading capabilities have been expanded in preparation for working with Registry Keys options. The "RegistryHive" enum was deleted because it is contained in "Microsoft.Win32".
This commit is contained in:
@@ -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<string> GetKeyValue(RegistryHive hive, string keyPath, string propertyName);
|
||||
string[] GetSubKeyNames(RegistryHive hive, string keyPath);
|
||||
#region registry reader
|
||||
string[] GetSubKeyNames(RegistryHive hive, string path);
|
||||
|
||||
Optional<string> GetPropertyValue(WindowsRegistryKey key);
|
||||
Optional<string> GetPropertyValue(RegistryHive hive, string path, string name);
|
||||
|
||||
WindowsRegistryKey GetWindowsRegistryKey(RegistryHive hive, string path, string name);
|
||||
WindowsRegistryKey GetWindowsRegistryKey(WindowsRegistryKey key);
|
||||
|
||||
List<WindowsRegistryKey> GetRegistryEntries(RegistryHive hive, string path);
|
||||
List<WindowsRegistryKey> 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
|
||||
}
|
||||
}
|
||||
29
mRemoteNG/Tools/WindowsRegistry/IRegistryRead.cs
Normal file
29
mRemoteNG/Tools/WindowsRegistry/IRegistryRead.cs
Normal file
@@ -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<string> GetPropertyValue(WindowsRegistryKey key);
|
||||
Optional<string> GetPropertyValue(RegistryHive hive, string path, string name);
|
||||
|
||||
WindowsRegistryKey GetWindowsRegistryKey(RegistryHive hive, string path, string name);
|
||||
WindowsRegistryKey GetWindowsRegistryKey(WindowsRegistryKey key);
|
||||
|
||||
List<WindowsRegistryKey> GetRegistryEntries(RegistryHive hive, string path);
|
||||
List<WindowsRegistryKey> GetRegistryEntryiesRecursive(RegistryHive hive, string path);
|
||||
#endregion
|
||||
|
||||
#region converter
|
||||
RegistryHive ConvertStringToRegistryHive(string hiveString);
|
||||
RegistryValueKind ConvertStringToRegistryValueKind(string valueType);
|
||||
#endregion
|
||||
}
|
||||
}
|
||||
21
mRemoteNG/Tools/WindowsRegistry/IRegistryWrite.cs
Normal file
21
mRemoteNG/Tools/WindowsRegistry/IRegistryWrite.cs
Normal file
@@ -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}
|
||||
}
|
||||
}
|
||||
@@ -1,11 +0,0 @@
|
||||
namespace mRemoteNG.Tools.WindowsRegistry
|
||||
{
|
||||
public enum RegistryHive
|
||||
{
|
||||
ClassesRoot,
|
||||
CurrentConfig,
|
||||
CurrentUser,
|
||||
Users,
|
||||
LocalMachine
|
||||
}
|
||||
}
|
||||
@@ -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
|
||||
{
|
||||
/// <summary>
|
||||
/// This class implements the IRegistryRead and IRegistryWrite interfaces and provides methods for interacting with the Windows Registry.
|
||||
/// </summary>
|
||||
[SupportedOSPlatform("windows")]
|
||||
public class WindowsRegistry : IRegistry
|
||||
public class WindowsRegistry : IRegistry, IRegistryRead, IRegistryWrite
|
||||
{
|
||||
public string[] GetSubKeyNames(RegistryHive hive, string keyPath)
|
||||
#region public read
|
||||
/// <summary>
|
||||
/// Retrieves the names of subkeys under a specified registry key path.
|
||||
/// </summary>
|
||||
/// <param name="hive">The RegistryHive where the subkeys are located.</param>
|
||||
/// <param name="path">The path to the registry key containing the subkeys.</param>
|
||||
/// <returns>An array of strings containing the names of subkeys, or an empty array if no subkeys are found.</returns>
|
||||
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];
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Retrieves the value of a specific property within a Windows Registry key and returns it as an Optional<string>.
|
||||
/// </summary>
|
||||
/// <param name="key">The WindowsRegistryKey containing information about the registry property.</param>
|
||||
/// <returns>An Optional<string> containing the property value, or Optional<string>.Empty if the value is not found.</returns>
|
||||
public Optional<string> 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<string> GetKeyValue(RegistryHive hive, string keyPath, string propertyName)
|
||||
/// <summary>
|
||||
/// Retrieves the value of a specific property within the Windows Registry and returns it as an Optional<string>.
|
||||
/// </summary>
|
||||
/// <param name="hive">The RegistryHive where the property is located.</param>
|
||||
/// <param name="path">The path to the registry key containing the property.</param>
|
||||
/// <param name="name">The name of the property to retrieve.</param>
|
||||
/// <returns>An Optional<string> containing the property value, or Optional<string>.Empty if the value is not found.</returns>
|
||||
public Optional<string> 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<string>.Empty;
|
||||
|
||||
return key.First().GetValue(propertyName) as string;
|
||||
return key.First().GetValue(name) as string;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Retrieves a WindowsRegistryKey object for a specific registry hive, path, and value name.
|
||||
/// </summary>
|
||||
/// <param name="hive">The RegistryHive of the key.</param>
|
||||
/// <param name="path">The path of the key.</param>
|
||||
/// <param name="name">The name of the value to retrieve.</param>
|
||||
/// <returns>A WindowsRegistryKey object representing the specified registry key and value.</returns>
|
||||
public WindowsRegistryKey GetWindowsRegistryKey(RegistryHive hive, string path, string name)
|
||||
{
|
||||
WindowsRegistryKey key = new WindowsRegistryKey
|
||||
{
|
||||
Hive = hive,
|
||||
Path = path,
|
||||
Name = name
|
||||
};
|
||||
|
||||
return GetWindowsRegistryKey(key);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Retrieves a WindowsRegistryKey object for a specific WindowsRegistryKey, populating its value and value kind.
|
||||
/// </summary>
|
||||
/// <param name="key">A WindowsRegistryKey object containing the hive, path, value name and more.</param>
|
||||
/// <returns>A WindowsRegistryKey object representing the specified registry key and value, with value and value kind populated.</returns>
|
||||
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;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Retrieves a list of registry entries (properties) and their values under a given key path.
|
||||
/// </summary>
|
||||
/// <param name="hive">The RegistryHive of the key path.</param>
|
||||
/// <param name="path">The path of the key from which to retrieve values.</param>
|
||||
/// <returns>A list of WindowsRegistryKey objects, each representing a value within the specified registry key path.</returns>
|
||||
public List<WindowsRegistryKey> GetRegistryEntries(RegistryHive hive, string path)
|
||||
{
|
||||
if (hive == 0)
|
||||
throw new ArgumentException("Unknown or unsupported RegistryHive value.", nameof(hive));
|
||||
path.ThrowIfNull(nameof(path));
|
||||
|
||||
List<WindowsRegistryKey> list = new List<WindowsRegistryKey>();
|
||||
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;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Recursively retrieves registry entries under a given key path and its subkeys.
|
||||
/// </summary>
|
||||
/// <param name="hive">The RegistryHive of the key path.</param>
|
||||
/// <param name="path">The path of the key from which to retrieve values.</param>
|
||||
/// <returns>A list of WindowsRegistryKey objects, each representing a value within the specified registry key path.</returns>
|
||||
public List<WindowsRegistryKey> GetRegistryEntryiesRecursive(RegistryHive hive, string path)
|
||||
{
|
||||
if (hive == 0)
|
||||
throw new ArgumentException("Unknown or unsupported RegistryHive value.", nameof(hive));
|
||||
path.ThrowIfNull(nameof(path));
|
||||
|
||||
List<WindowsRegistryKey> 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
|
||||
/// <summary>
|
||||
/// Sets the value of a specific property within a registry key using individual parameters.
|
||||
/// </summary>
|
||||
/// <param name="hive">The registry hive.</param>
|
||||
/// <param name="path">The path to the registry key containing the property.</param>
|
||||
/// <param name="name">The name of the property to set.</param>
|
||||
/// <param name="value">The value to set for the property.</param>
|
||||
/// <param name="valueKind">The data type of the value to set.</param>
|
||||
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);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Sets the value of a specific property within a registry key using the provided WindowsRegistryKey object.
|
||||
/// </summary>
|
||||
/// <param name="key">The WindowsRegistryKey object containing information about the registry property.</param>
|
||||
public void SetRegistryValue(WindowsRegistryKey key)
|
||||
{
|
||||
CreateOrSetRegistryValue(key);
|
||||
}
|
||||
#endregion
|
||||
|
||||
#region public methods
|
||||
/// <summary>
|
||||
/// Converts a string representation of a Registry Hive to the corresponding RegistryHive enum value.
|
||||
/// </summary>
|
||||
/// <param name="hiveString">A string representation of a Registry Hive, not case-sensitive.</param>
|
||||
/// <returns>The RegistryHive enum value corresponding to the provided string representation.</returns>
|
||||
/// <exception cref="ArgumentException">Thrown if the provided string does not match a valid Registry Hive.</exception>
|
||||
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));
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Converts a string representation of a RegistryValueKind to the corresponding RegistryValueKind enum value.
|
||||
/// </summary>
|
||||
/// <param name="valueType">A string representation of a RegistryValueKind, not case-sensitive.</param>
|
||||
/// <returns>The RegistryValueKind enum value corresponding to the provided string representation.</returns>
|
||||
/// <exception cref="ArgumentException">Thrown if the provided string does not match a valid RegistryValueKind.</exception>
|
||||
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
|
||||
/// <summary>
|
||||
/// Opens a subkey within the Windows Registry under the specified hive and key path.
|
||||
/// </summary>
|
||||
/// <param name="hive">The Windows Registry hive where the subkey is located.</param>
|
||||
/// <param name="keyPath">The path to the subkey to be opened.</param>
|
||||
/// <returns>
|
||||
/// A disposable optional object containing the opened registry subkey if successful;
|
||||
/// otherwise, it returns an empty optional object.
|
||||
/// </returns>
|
||||
private DisposableOptional<RegistryKey> OpenSubKey(RegistryHive hive, string keyPath)
|
||||
{
|
||||
switch (hive)
|
||||
@@ -52,5 +337,86 @@ namespace mRemoteNG.Tools.WindowsRegistry
|
||||
throw new ArgumentOutOfRangeException(nameof(hive), hive, null);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Attempts to retrieve the value kind of a specific property within a registry subkey.
|
||||
/// </summary>
|
||||
/// <param name="subKey">The registry subkey from which to retrieve the value kind.</param>
|
||||
/// <param name="valueName">The name of the property for which to retrieve the value kind.</param>
|
||||
/// <param name="valueKind">An output parameter that will contain the retrieved value kind, or RegistryValueKind.Unknown if the property or value kind is not found.</param>
|
||||
/// <returns>True if the operation is successful, otherwise false.</returns>
|
||||
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;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Creates or sets the value of a specific property within a registry key.
|
||||
/// </summary>
|
||||
/// <param name="key">The WindowsRegistryKey object containing information about the registry property.</param>
|
||||
/// <exception cref="InvalidOperationException">Thrown when the Windows Registry key is not ready for writing.</exception>
|
||||
/// <exception cref="SecurityException">Thrown when a security-related error occurs while accessing the registry.</exception>
|
||||
/// <exception cref="IOException">Thrown when an I/O error occurs while accessing the registry.</exception>
|
||||
/// <exception cref="UnauthorizedAccessException">Thrown when access to the registry is unauthorized.</exception>
|
||||
/// <exception cref="Exception">Thrown for all other exceptions.</exception>
|
||||
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
|
||||
}
|
||||
}
|
||||
213
mRemoteNG/Tools/WindowsRegistry/WindowsRegistryKey.cs
Normal file
213
mRemoteNG/Tools/WindowsRegistry/WindowsRegistryKey.cs
Normal file
@@ -0,0 +1,213 @@
|
||||
using System;
|
||||
using System.Runtime.Versioning;
|
||||
using Microsoft.Win32;
|
||||
|
||||
|
||||
namespace mRemoteNG.Tools.WindowsRegistry
|
||||
{
|
||||
/// <summary>
|
||||
/// 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.
|
||||
/// </summary>
|
||||
[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
|
||||
/// <summary>
|
||||
/// Checks if the Windows Registry key is ready for reading by ensuring that the hive,
|
||||
/// path, and name properties are set.
|
||||
/// </summary>
|
||||
/// <returns>True if the key is ready for reading, otherwise false.</returns>
|
||||
public bool IsKeyReadable() {
|
||||
return (IsHiveSet() && IsPathSet() && IsNameSet());
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 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
|
||||
/// </summary>
|
||||
/// <returns>Returns true if the key is write-ready, otherwise false.</returns>
|
||||
public bool IsKeyWritable() {
|
||||
return (IsHiveSet() && IsValueKindSet() && IsPathSet() && IsNameSet());
|
||||
//return (IsHiveSet() && IsValueKindSet() && IsPathSet() && IsNameSet() && IsValueSet());
|
||||
}
|
||||
#endregion
|
||||
|
||||
#region private methods
|
||||
/// <summary>
|
||||
/// Converts a .NET data type to the corresponding RegistryValueKind.
|
||||
/// </summary>
|
||||
/// <param name="valueType">The .NET data type to convert.</param>
|
||||
/// <returns>The corresponding RegistryValueKind.</returns>
|
||||
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
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Converts a RegistryValueKind enumeration value to its corresponding .NET Type.
|
||||
/// </summary>
|
||||
/// <param name="valueKind">The RegistryValueKind value to be converted.</param>
|
||||
/// <returns>The .NET Type that corresponds to the given RegistryValueKind.</returns>
|
||||
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
|
||||
}
|
||||
}
|
||||
@@ -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<ArgumentNullException>(() => _registry.GetSubKeyNames(RegistryHive.CurrentUser, null));
|
||||
Assert.Throws<ArgumentNullException>(() => _registryReader.GetSubKeyNames(RegistryHive.CurrentUser, null));
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void CanGetKeyValue()
|
||||
public void GetSubkeyNamesThrowsIfGivenUnknownHive()
|
||||
{
|
||||
var keyValue = _registry.GetKeyValue(RegistryHive.ClassesRoot, @".dll\PersistentHandler", "");
|
||||
Assert.Throws<ArgumentException>(() => _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<ArgumentNullException>(() => _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<ArgumentNullException>(() => _registryReader.GetPropertyValue(RegistryHive.CurrentUser, null, ""));
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void GetKeyValueThrowsIfGivenNullPropertyName()
|
||||
public void GetPropertyValueThrowsIfGivenNullPropertyName()
|
||||
{
|
||||
Assert.Throws<ArgumentNullException>(() => _registry.GetKeyValue(RegistryHive.CurrentUser, "", null));
|
||||
Assert.Throws<ArgumentNullException>(() => _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<InvalidOperationException>(() => _registryReader.GetWindowsRegistryKey(key));
|
||||
}
|
||||
#endregion
|
||||
|
||||
#region GetRegistryEntries() + Recurse tests
|
||||
[Test]
|
||||
public void CanGetRegistryEntries()
|
||||
{
|
||||
List<WindowsRegistryKey> keys = _registryReader.GetRegistryEntries(RegistryHive.LocalMachine, @"HARDWARE\DESCRIPTION\System\BIOS");
|
||||
Assert.That(keys.Count, Is.Not.EqualTo(0));
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void CanGetRegistryEntriesRecurse()
|
||||
{
|
||||
List<WindowsRegistryKey> 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<ArgumentNullException>(() => key.Hive = 0, "Expected IsHiveValid to throw ArgumentNullException");
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void WindowsRegistryKeyThrowValueKindNullException()
|
||||
{
|
||||
WindowsRegistryKey key = new WindowsRegistryKey();
|
||||
Assert.Throws<ArgumentNullException>(() => key.ValueKind = 0, "Expected IsValueKindValid to throw ArgumentNullException");
|
||||
}
|
||||
[Test]
|
||||
public void WindowsRegistryKeyThrowPathNullException()
|
||||
{
|
||||
WindowsRegistryKey key = new WindowsRegistryKey();
|
||||
Assert.Throws<ArgumentNullException>(() => key.Path = null, "Expected IsPathValid to throw ArgumentNullException");
|
||||
}
|
||||
[Test]
|
||||
public void WindowsRegistryKeyThrowNameNullException()
|
||||
{
|
||||
WindowsRegistryKey key = new WindowsRegistryKey();
|
||||
Assert.Throws<ArgumentNullException>(() => 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<UnauthorizedAccessException>(() => _registryWriter.SetRegistryValue(RegistryHive.LocalMachine, @"SOFTWARE\mRemoteNGTest", "TestKey", "A value string", RegistryValueKind.String));
|
||||
}
|
||||
#endregion
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user