C#でWindows 10のレジストリキーハンドルの情報を取得するには非公開のWin32 API NtQueryKey
が使用できます。NtQueryKey
関数に渡す構造体は可変長配列を含みますが、バイト配列で受け取ってSystem.BitConverter
、System.TextEncoding.Unicode.GetString
を使えばポインタやunsafe
を使わず扱えます。
using System; using System.Runtime.InteropServices; using System.Text; using Microsoft.Win32; using Microsoft.Win32.SafeHandles; class Program { static void Main() { using var key = Registry.ClassesRoot.OpenSubKey(".txt"); var basicInfo = QueryRegistryKey.QueryBasicInfo(key.Handle); // LastWriteTime: ... // Name: ".txt" // TitleIndex: 0 var name = QueryRegistryKey.QueryNameInfo(key.Handle); // \REGISTRY\USER\<ログオンユーザーのSID>_Classes\.txt } } internal static class QueryRegistryKey { private static class NativeMethods { [DllImport("ntdll.dll")] public static extern int NtQueryKey( SafeRegistryHandle KeyHandle, KEY_INFORMATION_CLASS KeyInformationClass, byte[] KeyInformation, uint Length, out uint ResultLength); } public static KeyBasicInformation QueryBasicInfo(SafeRegistryHandle handle) { var buffer = QueryInfo(handle, KEY_INFORMATION_CLASS.KeyBasicInformation); var info = new KeyBasicInformation(); info.LastWriteTime = new DateTime(BitConverter.ToInt64(buffer, 0)); info.LastWriteTime = info.LastWriteTime.AddYears(1600); info.TitleIndex = BitConverter.ToUInt32(buffer, 8); var nameLength = BitConverter.ToUInt32(buffer, 12); info.Name = Encoding.Unicode.GetString(buffer, 16, (int)nameLength); return info; } public static string QueryNameInfo(SafeRegistryHandle handle) { var buffer = QueryInfo(handle, KEY_INFORMATION_CLASS.KeyNameInformation); var nameLength = BitConverter.ToUInt32(buffer, 0); return Encoding.Unicode.GetString(buffer, 4, (int)nameLength); } private static byte[] QueryInfo(SafeRegistryHandle handle, KEY_INFORMATION_CLASS infoClass) { const int STATUS_BUFFER_TOO_SMALL = unchecked((int)0xC0000023); var ret = NativeMethods.NtQueryKey( handle, infoClass, null, 0, out var length); if (ret != STATUS_BUFFER_TOO_SMALL) return null; var buffer = new byte[length]; ret = NativeMethods.NtQueryKey( handle, infoClass, buffer, length, out length); return (ret == 0) ? buffer : null; } public enum KEY_INFORMATION_CLASS : int { KeyBasicInformation, KeyNodeInformation, KeyFullInformation, KeyNameInformation, KeyCachedInformation, KeyFlagsInformation, KeyVirtualizationInformation, KeyHandleTagsInformation, KeyTrustInformation, KeyLayerInformation, MaxKeyInfoClass } public struct KeyBasicInformation { public DateTime LastWriteTime; public uint TitleIndex; public string Name; } }