ValueHelper.cs
 1  // Copyright (c) Microsoft Corporation
 2  // The Microsoft Corporation licenses this file to you under the MIT license.
 3  // See the LICENSE file in the project root for more information.
 4  
 5  using System;
 6  using System.Linq;
 7  
 8  using Microsoft.CmdPal.Ext.Registry.Properties;
 9  using Microsoft.Win32;
10  
11  namespace Microsoft.CmdPal.Ext.Registry.Helpers;
12  
13  /// <summary>
14  /// Helper class to easier work with values of a <see cref="RegistryKey"/>
15  /// </summary>
16  internal static class ValueHelper
17  {
18      /// <summary>
19      /// Return a human readable value data, of the given value name inside the given <see cref="RegistryKey"/>
20      /// </summary>
21      /// <param name="key">The <see cref="RegistryKey"/> that should contain the value name.</param>
22      /// <param name="valueName">The name of the value.</param>
23      /// <param name="maxLength">The maximum length for the human readable value.</param>
24      /// <returns>A human readable value data.</returns>
25      internal static string GetValue(in RegistryKey key, in string valueName, int maxLength = int.MaxValue)
26      {
27          var unformattedValue = key.GetValue(valueName);
28  
29          if (unformattedValue is null)
30          {
31              throw new InvalidOperationException($"Cannot proceed when {nameof(unformattedValue)} is null.");
32          }
33  
34          var valueData = key.GetValueKind(valueName) switch
35          {
36              RegistryValueKind.DWord => $"0x{unformattedValue:X8} ({(uint)(int)unformattedValue})",
37              RegistryValueKind.QWord => $"0x{unformattedValue:X16} ({(ulong)(long)unformattedValue})",
38  #pragma warning disable CS8604 // Possible null reference argument.
39              RegistryValueKind.Binary => (unformattedValue as byte[]).Aggregate(string.Empty, (current, singleByte) => $"{current} {singleByte:X2}"),
40  #pragma warning restore CS8604 // Possible null reference argument.
41              _ => $"{unformattedValue}",
42          };
43  
44          return valueData.Length > maxLength
45              ? $"{valueData.Substring(0, maxLength)}..."
46              : valueData;
47      }
48  
49      /// <summary>
50      /// Return the registry type name of a given value name inside a given <see cref="RegistryKey"/>
51      /// </summary>
52      /// <param name="key">The <see cref="RegistryKey"/> that should contain the value name</param>
53      /// <param name="valueName">The name of the value</param>
54      /// <returns>A registry type name</returns>
55      internal static object GetType(RegistryKey key, string valueName)
56      {
57          return key.GetValueKind(valueName) switch
58          {
59              RegistryValueKind.None => Resources.RegistryValueKindNone,
60              RegistryValueKind.Unknown => Resources.RegistryValueKindUnknown,
61              RegistryValueKind.String => "REG_SZ",
62              RegistryValueKind.ExpandString => "REG_EXPAND_SZ",
63              RegistryValueKind.MultiString => "REG_MULTI_SZ",
64              RegistryValueKind.Binary => "REG_BINARY",
65              RegistryValueKind.DWord => "REG_DWORD",
66              RegistryValueKind.QWord => "REG_QWORD",
67              _ => throw new ArgumentOutOfRangeException(nameof(valueName)),
68          };
69      }
70  }