RegistryUtils.cs 3.1 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273
  1. using Microsoft.Win32;
  2. namespace MeloongCore;
  3. public static class RegistryUtils {
  4. /// <summary>在注册表中表示 <c>null</c> 的标记字符串。</summary>
  5. public const string NULL_STRING = "__NULL__";
  6. /// <summary>
  7. /// 读取注册表值。
  8. /// <para/>若键值为 <see cref="NULL_STRING"/>,则返回 <c>null</c>。
  9. /// </summary>
  10. public static (object? result, bool exists) Read(string folder, string entry) {
  11. using RegistryKey? folderKey = GetRegistryKey(folder);
  12. var result = folderKey?.GetValue(entry);
  13. if (result is null) return (null, false);
  14. return (result is string str && str == NULL_STRING ? null : result, true);
  15. }
  16. /// <summary>
  17. /// 读取注册表值,若该值不存在或发生异常则返回 <paramref name="defaultValue"/>。
  18. /// <para/>若键值为 <see cref="NULL_STRING"/>,则返回 <c>null</c>。
  19. /// </summary>
  20. public static object? TryRead(string folder, string entry, object? defaultValue = null) {
  21. try {
  22. var (result, exists) = Read(folder, entry);
  23. return exists ? result : defaultValue;
  24. } catch (Exception ex) {
  25. Logger.Warn(ex, $"读取注册表值失败({folder},{entry})");
  26. return defaultValue;
  27. }
  28. }
  29. /// <summary>
  30. /// 写入注册表值。
  31. /// <para/>会自动创建对应的子键。
  32. /// <para/>若 <paramref name="value"/> 为 <c>null</c>,则写入 <see cref="NULL_STRING"/>。
  33. /// </summary>
  34. public static void Write(string folder, string entry, object? value) {
  35. using RegistryKey folderKey = GetRegistryKey(folder, create: true)!;
  36. folderKey.SetValue(entry, value ?? NULL_STRING);
  37. }
  38. /// <summary>
  39. /// 判断对应的注册表值是否存在。
  40. /// </summary>
  41. public static bool Has(string folder, string entry) {
  42. using RegistryKey? folderKey = GetRegistryKey(folder);
  43. if (folderKey is null) return false;
  44. object notFound = new();
  45. return !ReferenceEquals(folderKey.GetValue(entry, notFound), notFound);
  46. }
  47. /// <summary>
  48. /// 删除注册表值。若不存在则不执行操作。
  49. /// </summary>
  50. public static void Delete(string folder, string entry) {
  51. using RegistryKey? folderKey = GetRegistryKey(folder, writable: true);
  52. folderKey?.DeleteValue(entry, throwOnMissingValue: false);
  53. }
  54. private static RegistryKey? GetRegistryKey(string fullPath, bool writable = false, bool create = false) {
  55. using RegistryKey key = fullPath.BeforeFirst("\\").ToUpperInvariant() switch {
  56. "HKEY_CLASSES_ROOT" => Registry.ClassesRoot,
  57. "HKEY_CURRENT_USER" => Registry.CurrentUser,
  58. "HKEY_LOCAL_MACHINE" => Registry.LocalMachine,
  59. "HKEY_USERS" => Registry.Users,
  60. "HKEY_CURRENT_CONFIG" => Registry.CurrentConfig,
  61. _ => throw new ArgumentException($"注册表路径有误({fullPath})", nameof(fullPath))
  62. };
  63. string subKey = fullPath.AfterFirst("\\");
  64. return create ? key.CreateSubKey(subKey) : key.OpenSubKey(subKey, writable);
  65. }
  66. }