potisanのプログラミングメモ

趣味のプログラマーがプログラミング関係で気になったことや調べたことをいつでも忘れられるようにメモするブログです。はてなブログ無料版なので記事の上の方はたぶん広告です。記事中にも広告挿入されるみたいです。

C# レジストリに登録されたCOMインターフェイスの情報を取得するクラスとサンプル

レジストリに登録されたInterface(HKCR\Interfaceのサブキー)の情報を取得するクラスCOMInterfaceInfoとそのサンプルコードです。

COMInterfaceInfoソースコード

COMInterfaceInfo.cs

using System;
using System.Collections.Generic;
using System.Diagnostics;
using Microsoft.Win32;

namespace ConsoleApp1
{
    [DebuggerDisplay("Name={Name}, ID={ID}")]
    public class COMInterfaceInfo
    {
        public static RegistryKey OpenInterfaceKey(
            bool writable = false,
            RegistryView view = RegistryView.Default)
        {
            using (var key = RegistryKey.OpenBaseKey(RegistryHive.ClassesRoot, view))
            {
                return key.OpenSubKey("Interface", writable);
            }
        }

        public static IEnumerable<Guid> GetInterfaceIDs(
            RegistryView view = RegistryView.Default)
        {
            using (var interfaceKey = OpenInterfaceKey(false, view))
            {
                var result = new List<Guid>();
                foreach (var name in interfaceKey.GetSubKeyNames())
                {
                    if (Guid.TryParseExact(name, "B", out var iid))
                    {
                        result.Add(iid);
                    }
                }
                return result;
            }
        }

        public RegistryView RegistryView { get; }
        public Guid ID { get; }

        public COMInterfaceInfo(Guid id, RegistryView view = RegistryView.Default)
        {
            ID = id;
            RegistryView = view;
        }

        public RegistryKey OpenRegistryKey(bool writable = false)
        {
            using (var key = RegistryKey.OpenBaseKey(RegistryHive.ClassesRoot, RegistryView))
            {
                return key.OpenSubKey("Interface\\" + ID.ToString("B"), writable);
            }
        }

        public RegistryKey OpenRegistrySubKey(string name, bool writable = false)
        {
            using (var key = RegistryKey.OpenBaseKey(RegistryHive.ClassesRoot, RegistryView))
            {
                return key.OpenSubKey("Interface\\" + ID.ToString("B") + "\\" + name, writable);
            }
        }

        protected string GetSubKeyValue(string keyName, string valueName)
        {
            using (var key = OpenRegistrySubKey(keyName))
            {
                return key == null ? null : (string)key.GetValue(valueName);
            }
        }

        public string Name
        {
            get
            {
                using (var key = OpenRegistryKey())
                {
                    return key == null ? null : (string)key.GetValue(String.Empty);
                }
            }
        }

        public Guid? BaseInterface
        {
            get
            {
                var value = GetSubKeyValue("BaseInterface", String.Empty);
                return Guid.TryParseExact(value, "B", out var iid) ? new Guid?(iid) : null;
            }
        }
        public int? NumMethods
        {
            get
            {
                var value = GetSubKeyValue("NumMethods", String.Empty);
                return int.TryParse(value, out var n) ? new int?(n) : null;
            }
        }

        public Guid? ProxyStubClsid32
        {
            get
            {
                var value = GetSubKeyValue("ProxyStubClsid32", String.Empty);
                return Guid.TryParseExact(value, "B", out var clsid) ? new Guid?(clsid) : null;
            }
        }
    }
}

レジストリに登録されたCLSIDに関連付けられたインターフェイスのCLSIDを列挙する

using System;
using System.Linq;
using Microsoft.Win32;

namespace ConsoleApp1
{
    class Program
    {
        static void Main(string[] args)
        {
            var interfaceIds = COMInterfaceInfo.GetInterfaceIDs();
            var interfaces = interfaceIds.Select(id => new COMInterfaceInfo(id));
            var proxyStubClsid32Interfaces = interfaces.Where(
                i => i.ProxyStubClsid32.HasValue);
            foreach (var proxyStubClsid32Interface in proxyStubClsid32Interfaces)
            {
                Console.WriteLine("{0} - {1} ({2} - {3})",
                    proxyStubClsid32Interface.ID.ToString("B"),
                    proxyStubClsid32Interface.ProxyStubClsid32?.ToString("B"),
                    proxyStubClsid32Interface.Name,
                    Utility.GetCLSIDName(proxyStubClsid32Interface.ProxyStubClsid32.Value));
            }
        }
    }

    public static class Utility
    {
        public static string GetCLSIDName(Guid clsid, RegistryView view = RegistryView.Default)
        {
            using (var crkey = RegistryKey.OpenBaseKey(RegistryHive.ClassesRoot, view))
            {
                using (var clsidEntryKey = crkey.OpenSubKey(@"CLSID\" + clsid.ToString("B")))
                {
                    return (string)clsidEntryKey?.GetValue(String.Empty);
                }
            }
        }
    }
}

2021/3/10:この記事は別のブログで投稿した記事を移動したものです。