レジストリからプロパティシステムの拡張子情報を取得するサンプルコードです。情報源はMicrosoftの公式ドキュメントです。
ドキュメントの記載に従い、HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows\CurrentVersion\PropertySystem\PropertyHandlers
に登録された拡張子の登録情報をHKEY_CLASSES_ROOT\SystemFileAssociations
から取得しています。ここではPropertyHandlers
キーのサブキーに登録されたプロパティハンドラのCLSID
には触れてません。
RegistryPropertyHandlersInfo.cs
#nullable enable using System; using System.Diagnostics.CodeAnalysis; using System.Linq; using Microsoft.Win32; namespace Potisan.Windows.FileSystem { /// <summary> /// レジストリに登録されたプロパティハンドラの情報を取得するクラスです。 /// </summary> /// <seealso cref="https://docs.microsoft.com/en-us/windows/win32/search/-search-3x-wds-extidx-propertyhandlers"/> public sealed class RegistryPropertyHandlersInfo : IDisposable { // 繰り返し使用するリソース private RegistryKey? systemFileAssocsKey; private RegistryKey? propertyHandlersKey; public RegistryPropertyHandlersInfo() { using var hkcr = RegistryKey.OpenBaseKey(RegistryHive.ClassesRoot, RegistryView.Registry64); using var hklm = RegistryKey.OpenBaseKey(RegistryHive.LocalMachine, RegistryView.Registry64); systemFileAssocsKey = hkcr.OpenSubKey(@"SystemFileAssociations"); propertyHandlersKey = hklm.OpenSubKey(@"Software\Microsoft\Windows\CurrentVersion\PropertySystem\PropertyHandlers"); if (systemFileAssocsKey == null || propertyHandlersKey == null) throw new Exception("必要なレジストリキーを開けませんでした。"); } ~RegistryPropertyHandlersInfo() { Dispose(); } public void Dispose() { if (IsDisposed) return; systemFileAssocsKey.Dispose(); propertyHandlersKey.Dispose(); systemFileAssocsKey = null; propertyHandlersKey = null; GC.SuppressFinalize(this); } [MemberNotNullWhen(false, "systemFileAssocsKey", "propertyHandlersKey")] public bool IsDisposed => systemFileAssocsKey == null && propertyHandlersKey == null; [MemberNotNull("systemFileAssocsKey", "propertyHandlersKey")] private void ThrowIfDisposed() { if (IsDisposed) throw new ObjectDisposedException("RegistryPropertyHandlersInfo"); } public string[] GetExtensionNames() { ThrowIfDisposed(); return propertyHandlersKey.GetSubKeyNames() .Where(s => s.StartsWith('.')) .ToArray(); } public Guid? GetPropertyHandlerCLSID(string extensionName) { ThrowIfDisposed(); using var key = propertyHandlersKey.OpenSubKey(extensionName); return key?.GetValue("", null) is string s && Guid.TryParseExact(s, "B", out var ret) ? ret : null; } private RegistryKey? OpenExtensionKey(string extensionName) { ThrowIfDisposed(); return systemFileAssocsKey.OpenSubKey(@$"{extensionName}") is RegistryKey key1 ? key1 : null; } public (string? ExtendedTileInfo, string? FullDetails) GetExtensionRawInfo(string extensionName) { ThrowIfDisposed(); using var key = OpenExtensionKey(extensionName); if (key == null) return (null, null); return (key.GetValue("ExtendedTileInfo", null) is string s1 ? s1 : null, key.GetValue("FullDetails", null) is string s2 ? s2 : null); } public (string[]? ExtendedTileInfo, string[]? FullDetails) GetExtensionInfo(string extensionName) { ThrowIfDisposed(); using var key = OpenExtensionKey(extensionName); if (key == null) return (null, null); var (extendedTileInfoRaw, fullDetailsRaw) = GetExtensionRawInfo(extensionName); var extendedTileInfo = default(string[]); var fullDetails = default(string[]); if (extendedTileInfoRaw != null && extendedTileInfoRaw.StartsWith("prop:")) { extendedTileInfo = extendedTileInfoRaw["prop:".Length..].Split(';'); } if (fullDetailsRaw != null && fullDetailsRaw.StartsWith("prop:")) { fullDetails = fullDetailsRaw["prop:".Length..].Split(';'); } return (extendedTileInfo, fullDetails); } } }
Program.cs
#nullable enable using System; using System.Linq; using Potisan.Windows.FileSystem; using var propHandlersInfo = new RegistryPropertyHandlersInfo(); var extensionInfos = propHandlersInfo.GetExtensionNames() .Select(name => { var info = propHandlersInfo.GetExtensionInfo(name); return (Name: name, info.ExtendedTileInfo, info.FullDetails); }); Console.WriteLine("■ExtendedTileInfo、FullDetailsの登録された拡張子"); var extensionNameWithPSInfo = extensionInfos .Where(info => info.ExtendedTileInfo != null || info.FullDetails != null); foreach (var (name, extendedTileInfo, fullDetails) in extensionNameWithPSInfo) { var s1 = extendedTileInfo is not null ? string.Join<string>(',', extendedTileInfo) : null; var s2 = fullDetails is not null ? string.Join<string>(',', fullDetails) : null; Console.WriteLine($"{name}, {s1}, {s2}"); } Console.WriteLine(); Console.WriteLine("■ExtendedTileInfo、FullDetailsの登録されていない拡張子"); var extensionNameWithoutPSInfo = extensionInfos .Where(info => info.ExtendedTileInfo == null && info.FullDetails == null) .Select(info => info.Name); Console.WriteLine(string.Join<string>(',', extensionNameWithoutPSInfo)); Console.WriteLine();