0

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

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

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

4

1 回答 1

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;
    }
}
于 2017-05-09T19:51:23.803 回答