【问题标题】:Is there a way to view COM entries by traversing a TLB file in .NET?有没有办法通过遍历.NET 中的 TLB 文件来查看 COM 条目?
【发布时间】:2021-11-19 05:38:20
【问题描述】:

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

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

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

【问题讨论】:

  • 目前还不是很清楚你为什么要这样做。只需在“属性”窗口中设置“隔离=真”以供参考,从那里开始一切都是自动的。重新发明这个功能,嗯,哎哟。请记住,类型库是不够的,您对组件的代理/存根一无所知。使用 LoadTypeLib() 读取类型库。
  • 我不是在 .NET 项目中这样做
  • 那么使用 [c#] 和 [.net] 标签没有多大意义,是吗?仍然是生成所需 .manifest 文件的最简单方法。
  • 是的,我明白为什么会令人困惑了。如果可以的话,我想使用 .NET 代码生成清单……但我的任务是让大量 COM 项目(本机和托管)相互通信。有很多细微差别,对我来说,老式的方法可以帮助我学习正确的方法,而不是试图排除自动魔法的故障。我的办公桌上有 50 多页关于程序集清单、隔离应用程序、激活 .NET 与托管 COM 组件等的 Microsoft 文档。不过,感谢 LoadTypeLib() 提示,我认为这将是一个巨大的帮助。

标签: typelib registration-free-com


【解决方案1】:

我采纳了 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;
    }
}

【讨论】:

  • 谢谢 - 虽然这很简单,但非常感谢。能够开发简单的命令行工具来做这类事情是非常有用的。
  • 不客气!感谢您的支持。
猜你喜欢
  • 2021-06-25
  • 2019-09-14
  • 2022-01-09
  • 1970-01-01
  • 2021-12-15
  • 1970-01-01
  • 1970-01-01
  • 2010-11-20
  • 1970-01-01
相关资源
最近更新 更多