有没有办法通过遍历 .NET 中的 TLB 文件来查看 COM 条目?

Is there a way to view COM entries by traversing a TLB file in .NET?

我正在将应用程序转换为使用免注册 COM。有一些第 3 方 COM dll 通常会调用 regsvr32。我测试了我可以通过制作并排清单从这些第 3 方 dll 创建对象。

我使用 Windows 中内置的 OLE/COM 查看器来获取此信息。但是我想制作一个可以手动为我执行此操作的程序,因为这些第 3 方库有很多 类 我需要放入清单中。

有谁知道以编程方式遍历类型库的方法吗?

我采纳了 Hans 的建议并使用了 LoadTypeLib。

对于寻找示例代码的任何人来说,这应该是一个很好的起点。 我今天早上写的,并且能够得到我需要的xml。

原谅我没有释放物品!我现在没有时间完全充实这个答案的其余部分。欢迎编辑。

    [DllImport("oleaut32.dll", PreserveSig = false)]
    public static extern ITypeLib LoadTypeLib([In, MarshalAs(UnmanagedType.LPWStr)] string typelib);

    public static void ParseTypeLib(string filePath)
    {

        string fileNameOnly = Path.GetFileNameWithoutExtension(filePath);
        ITypeLib typeLib = LoadTypeLib(filePath);

        int count = typeLib.GetTypeInfoCount();
        IntPtr ipLibAtt = IntPtr.Zero;
        typeLib.GetLibAttr(out ipLibAtt);

        var typeLibAttr = (System.Runtime.InteropServices.ComTypes.TYPELIBATTR)
            Marshal.PtrToStructure(ipLibAtt, typeof(System.Runtime.InteropServices.ComTypes.TYPELIBATTR));
        Guid tlbId = typeLibAttr.guid;

        for(int i=0; i< count; i++)
        {
            ITypeInfo typeInfo = null;
            typeLib.GetTypeInfo(i, out typeInfo);

            //figure out what guids, typekind, and names of the thing we're dealing with
            IntPtr ipTypeAttr = IntPtr.Zero;
            typeInfo.GetTypeAttr(out ipTypeAttr);

            //unmarshal the pointer into a structure into something we can read
            var typeattr = (System.Runtime.InteropServices.ComTypes.TYPEATTR)
                Marshal.PtrToStructure(ipTypeAttr, typeof(System.Runtime.InteropServices.ComTypes.TYPEATTR));

            System.Runtime.InteropServices.ComTypes.TYPEKIND typeKind = typeattr.typekind;
            Guid typeId = typeattr.guid;

            //get the name of the type
            string strName, strDocString, strHelpFile;
            int dwHelpContext;
            typeLib.GetDocumentation(i, out strName, out strDocString, out dwHelpContext, out strHelpFile);


            if (typeKind == System.Runtime.InteropServices.ComTypes.TYPEKIND.TKIND_COCLASS)
            {
                string xmlComClassFormat = "<comClass clsid=\"{0}\" tlbid=\"{1}\" description=\"{2}\" progid=\"{3}.{4}\"></comClass>";
                string comClassXml = String.Format(xmlComClassFormat, 
                    typeId.ToString("B").ToUpper(),
                    tlbId.ToString("B").ToUpper(),
                    strDocString,
                    fileNameOnly, strName
                    );
                //Debug.WriteLine(comClassXml);
            }
            else if(typeKind == System.Runtime.InteropServices.ComTypes.TYPEKIND.TKIND_INTERFACE)
            {
                string xmlProxyStubFormat = "<comInterfaceExternalProxyStub name=\"{0}\" iid=\"{1}\" tlbid=\"{2}\" proxyStubClsid32=\"{3}\"></comInterfaceExternalProxyStub>";
                string proxyStubXml = String.Format(xmlProxyStubFormat,
                    strName,
                    typeId.ToString("B").ToUpper(),
                    tlbId.ToString("B").ToUpper(),
                    "{00020424-0000-0000-C000-000000000046}"
                );
                //Debug.WriteLine(proxyStubXml);
            }

        }

        return;
    }
}