using Microsoft.Win32; using Pulsar.Common.Utilities; using System; using System.Collections.Generic; using System.Linq; namespace Pulsar.Client.Extensions { /// /// Provides extensions for registry key and value operations. /// public static class RegistryKeyExtensions { /// /// Determines if the registry key by the name provided is null or has the value of null. /// /// The name associated with the registry key. /// The actual registry key. /// True if the provided name is null or empty, or the key is null; False if otherwise. private static bool IsNameOrValueNull(this string keyName, RegistryKey key) { return (string.IsNullOrEmpty(keyName) || (key == null)); } /// /// Attempts to get the string value of the key using the specified key name. This method assumes /// correct input. /// /// The key of which we obtain the value of. /// The name of the key. /// The default value if value can not be determined. /// Returns the value of the key using the specified key name. If unable to do so, /// defaultValue will be returned instead. public static string GetValueSafe(this RegistryKey key, string keyName, string defaultValue = "") { try { return key.GetValue(keyName, defaultValue).ToString(); } catch { return defaultValue; } } /// /// Attempts to obtain a readonly (non-writable) sub key from the key provided using the /// specified name. Exceptions thrown will be caught and will only return a null key. /// This method assumes the caller will dispose of the key when done using it. /// /// The key of which the sub key is obtained from. /// The name of the sub-key. /// Returns the sub-key obtained from the key and name provided; Returns null if /// unable to obtain a sub-key. public static RegistryKey OpenReadonlySubKeySafe(this RegistryKey key, string name) { try { return key.OpenSubKey(name, false); } catch { return null; } } /// /// Attempts to obtain a writable sub key from the key provided using the specified /// name. This method assumes the caller will dispose of the key when done using it. /// /// The key of which the sub key is obtained from. /// The name of the sub-key. /// Returns the sub-key obtained from the key and name provided; Returns null if /// unable to obtain a sub-key. public static RegistryKey OpenWritableSubKeySafe(this RegistryKey key, string name) { try { return key.OpenSubKey(name, true); } catch { return null; } } /// /// Attempts to create a sub key from the key provided using the specified /// name. This method assumes the caller will dispose of the key when done using it. /// /// The key of which the sub key is to be created from. /// The name of the sub-key. /// Returns the sub-key that was created for the key and name provided; Returns null if /// unable to create a sub-key. public static RegistryKey CreateSubKeySafe(this RegistryKey key, string name) { try { return key.CreateSubKey(name); } catch { return null; } } /// /// Attempts to delete a sub-key and its children from the key provided using the specified /// name. /// /// The key of which the sub-key is to be deleted from. /// The name of the sub-key. /// Returns true if the action succeeded, otherwise false. public static bool DeleteSubKeyTreeSafe(this RegistryKey key, string name) { try { key.DeleteSubKeyTree(name, true); return true; } catch { return false; } } /* * Derived and Adapted from drdandle's article, * Copy and Rename Registry Keys at Code project. * Copy and Rename Registry Keys (Post Date: November 11, 2006) * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ * This is a work that is not of the original. It * has been modified to suit the needs of another * application. * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ * First Modified by StingRaptor on January 21, 2016 * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ * Original Source: * http://www.codeproject.com/Articles/16343/Copy-and-Rename-Registry-Keys */ /// /// Attempts to rename a sub-key to the key provided using the specified old /// name and new name. /// /// The key of which the subkey is to be renamed from. /// The old name of the sub-key. /// The new name of the sub-key. /// Returns true if the action succeeded, otherwise false. public static bool RenameSubKeySafe(this RegistryKey key, string oldName, string newName) { try { //Copy from old to new key.CopyKey(oldName, newName); //Dispose of the old key key.DeleteSubKeyTree(oldName); return true; } catch { //Try to dispose of the newKey (The rename failed) key.DeleteSubKeyTreeSafe(newName); return false; } } /// /// Attempts to copy a old subkey to a new subkey for the key /// provided using the specified old name and new name. (throws exceptions) /// /// The key of which the subkey is to be deleted from. /// The old name of the sub-key. /// The new name of the sub-key. public static void CopyKey(this RegistryKey key, string oldName, string newName) { //Create a new key using (RegistryKey newKey = key.CreateSubKey(newName)) { //Open old key using (RegistryKey oldKey = key.OpenSubKey(oldName, true)) { //Copy from old to new RecursiveCopyKey(oldKey, newKey); } } } /// /// Attempts to rename a sub-key to the key provided using the specified old /// name and new name. /// /// The source key to copy from. /// The destination key to copy to. private static void RecursiveCopyKey(RegistryKey sourceKey, RegistryKey destKey) { //Copy all of the registry values foreach (string valueName in sourceKey.GetValueNames()) { object valueObj = sourceKey.GetValue(valueName); RegistryValueKind valueKind = sourceKey.GetValueKind(valueName); destKey.SetValue(valueName, valueObj, valueKind); } //Copy all of the subkeys foreach (string subKeyName in sourceKey.GetSubKeyNames()) { using (RegistryKey sourceSubkey = sourceKey.OpenSubKey(subKeyName)) { using (RegistryKey destSubKey = destKey.CreateSubKey(subKeyName)) { //Recursive call to copy the sub key data RecursiveCopyKey(sourceSubkey, destSubKey); } } } } /// /// Attempts to set a registry value for the key provided using the specified /// name, data and kind. If the registry value does not exist it will be created /// /// The key of which the value is to be set for. /// The name of the value. /// The data of the value /// The value kind of the value /// Returns true if the action succeeded, otherwise false. public static bool SetValueSafe(this RegistryKey key, string name, object data, RegistryValueKind kind) { try { // handle type conversion if (kind != RegistryValueKind.Binary && data.GetType() == typeof(byte[])) { switch (kind) { case RegistryValueKind.String: case RegistryValueKind.ExpandString: data = ByteConverter.ToString((byte[])data); break; case RegistryValueKind.DWord: data = ByteConverter.ToUInt32((byte[])data); break; case RegistryValueKind.QWord: data = ByteConverter.ToUInt64((byte[])data); break; case RegistryValueKind.MultiString: data = ByteConverter.ToStringArray((byte[])data); break; } } key.SetValue(name, data, kind); return true; } catch { return false; } } /// /// Attempts to delete a registry value for the key provided using the specified /// name. /// /// The key of which the value is to be delete from. /// The name of the value. /// Returns true if the action succeeded, otherwise false. public static bool DeleteValueSafe(this RegistryKey key, string name) { try { key.DeleteValue(name); return true; } catch { return false; } } /// /// Attempts to rename a registry value to the key provided using the specified old /// name and new name. /// /// The key of which the registry value is to be renamed from. /// The old name of the registry value. /// The new name of the registry value. /// Returns true if the action succeeded, otherwise false. public static bool RenameValueSafe(this RegistryKey key, string oldName, string newName) { try { //Copy from old to new key.CopyValue(oldName, newName); //Dispose of the old value key.DeleteValue(oldName); return true; } catch { //Try to dispose of the newKey (The rename failed) key.DeleteValueSafe(newName); return false; } } /// /// Attempts to copy a old registry value to a new registry value for the key /// provided using the specified old name and new name. (throws exceptions) /// /// The key of which the registry value is to be copied. /// The old name of the registry value. /// The new name of the registry value. public static void CopyValue(this RegistryKey key, string oldName, string newName) { RegistryValueKind valueKind = key.GetValueKind(oldName); object valueData = key.GetValue(oldName); key.SetValue(newName, valueData, valueKind); } /// /// Checks if the specified subkey exists in the key /// /// The key of which to search. /// The name of the sub-key to find. /// Returns true if the action succeeded, otherwise false. public static bool ContainsSubKey(this RegistryKey key, string name) { foreach (string subkey in key.GetSubKeyNames()) { if (subkey == name) { return true; } } return false; } /// /// Checks if the specified registry value exists in the key /// /// The key of which to search. /// The name of the registry value to find. /// Returns true if the action succeeded, otherwise false. public static bool ContainsValue(this RegistryKey key, string name) { foreach (string value in key.GetValueNames()) { if (value == name) { return true; } } return false; } /// /// Gets all of the value names associated with the registry key and returns /// formatted strings of the filtered values. /// /// The registry key of which the values are obtained. /// Yield returns formatted strings of the key and the key value. public static IEnumerable> GetKeyValues(this RegistryKey key) { if (key == null) yield break; foreach (var k in key.GetValueNames().Where(keyVal => !keyVal.IsNameOrValueNull(key)).Where(k => !string.IsNullOrEmpty(k))) { yield return new Tuple(k, key.GetValueSafe(k)); } } /// /// Gets the default value for a given data type of a registry value. /// /// The data type of the registry value. /// The default value for the given . public static object GetDefault(this RegistryValueKind valueKind) { switch (valueKind) { case RegistryValueKind.Binary: return new byte[] { }; case RegistryValueKind.MultiString: return new string[] { }; case RegistryValueKind.DWord: return 0; case RegistryValueKind.QWord: return (long)0; case RegistryValueKind.String: case RegistryValueKind.ExpandString: return ""; default: return null; } } } }