使用动态转储 ComObject 对象?

2024-02-07

我正在尝试(不幸的是)为我在 Office 类型库中访问的对象实现“对象转储器”。

这一定是可能的,因为 VS 的调试窗口有一个针对 System.__ComObject 对象的“动态视图”,它可以有效地执行我想要的操作。

有任何想法吗?


我还创建了一个方法来获取可用于访问对象的接口。使用:

using System.Runtime.InteropServices;
using System.Runtime.InteropServices.ComTypes;

您的代码中必须有 IDispatch 接口:

[Guid("00020400-0000-0000-C000-000000000046"), ComImport(), InterfaceType(ComInterfaceType.InterfaceIsIUnknown)]
interface IDispatch 
{ 
    [PreserveSig] 
    int GetTypeInfoCount(out int pctinfo); 

    [PreserveSig] 
    int GetTypeInfo( 
        [MarshalAs(UnmanagedType.U4)] int iTInfo, 
        [MarshalAs(UnmanagedType.U4)] int lcid, 
        out System.Runtime.InteropServices.ComTypes.ITypeInfo ppTInfo); 

    [PreserveSig] 
    int GetIDsOfNames( 
        ref Guid riid, 
        [MarshalAs(UnmanagedType.LPArray, ArraySubType = UnmanagedType.LPWStr)] 
        string[] rgszNames, 
        int cNames, 
        int lcid, 
        [MarshalAs(UnmanagedType.LPArray)] int[] rgDispId); 

    [PreserveSig] 
    int Invoke( 
        int dispIdMember, 
        ref Guid riid, 
        uint lcid, 
        ushort wFlags, 
        ref System.Runtime.InteropServices.ComTypes.DISPPARAMS pDispParams, 
        out object pVarResult, 
        ref System.Runtime.InteropServices.ComTypes.EXCEPINFO pExcepInfo, 
        IntPtr[] puArgErr); 
}

我的方法将 COM 对象转换为 IDispatch,获取非托管类型信息,从非公共 Marshal 方法 GetTypeInfoGuid 获取对象类型 GUID,然后在当前 AppDomain 的程序集中搜索它。

internal static Func<ITypeInfo,Guid> GetTypeInfoGuid = (Func<ITypeInfo,Guid>)Delegate.CreateDelegate(typeof(Func<ITypeInfo,Guid>), typeof(Marshal).GetMethod("GetTypeInfoGuid", BindingFlags.NonPublic | BindingFlags.Static, null, new[]{typeof(ITypeInfo)}, null), true);
public static Type GetCOMObjectType(object comobject)
{
    if(!Marshal.IsComObject(comobject))
    {
        throw new ArgumentException("This is not COM object.", "comobject");
    }
    IDispatch dispatch = (IDispatch)comobject;
    ITypeInfo info;
    dispatch.GetTypeInfo(0,0, out info);
    Guid guid = GetTypeInfoGuid(info);
    foreach(Assembly a in AppDomain.CurrentDomain.GetAssemblies())
    {
        foreach(Type t in a.GetTypes())
        {
            if(t.IsInterface && t.IsImport && t.GUID == guid)
            {
                return t;
            }
        }
    }
    return Type.GetTypeFromCLSID(guid);
}

如果未找到适当的类型,该方法将返回 System.__ComObject 类型。但是,您可以从中获取 GUID 属性值,因此至少您将获得 GUID。 用法:

object controls = axWindowsMediaPlayer1.cdromCollection;
Type t = GetCOMObjectType(controls);
Console.WriteLine(t);
Console.WriteLine(t.GUID);
/*Output:
  WMPLib.IWMPCdromCollection
  ee4c8fe2-34b2-11d3-a3bf-006097c9b344 */

希望这可以帮助。祝你好运。 ☺

编辑: 找到了一个更简单但速度较慢的方法:

object controls = axWindowsMediaPlayer1.cdromCollection;
IDispatch dispatch = (IDispatch)controls;
ITypeInfo info;
dispatch.GetTypeInfo(0,0, out info);
Type t = Marshal.GetTypeForITypeInfo(Marshal.GetIUnknownForObject(info));
Console.WriteLine(t);
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

使用动态转储 ComObject 对象? 的相关文章

随机推荐

  • 对指针调用 free 两次

    我在讲座中被教导 召唤free 两次使用指针真的非常非常糟糕 我知道这是一个很好的做法 将指针设置为NULL 在释放它之后 然而 我仍然没有听到任何关于为什么会这样的解释 据我了解 方法malloc 有效 从技术上讲 它应该跟踪它已分配并供
  • WebException:服务器违反了协议。 Section=ResponseStatusLine(调用 Marketo SOAP API)

    我正在尝试调用 Marketo SOAP Web 服务 通过 ASP NET C 我成功添加了 Web 服务引用并尝试使用以下代码行调用它 SuccessGetLead lead service getLead paramsgetlead
  • 使用显示时没有底部填充:网格和滚动

    我有一个容器div有一些填充 display grid and overflow auto放 当一个孩子div的高度比父级的高度大 并且出现一个滚动条 它会滚动 以便没有底部填充 这里有一个Fiddler https jsfiddle ne
  • 绘图中的对数色阶

    我正在尝试使用一些异常值来可视化数据Plotly and Python3 异常值导致色阶图例看起来很糟糕 只有很少的高数据点 但图例看起来很糟糕 2k 和 10k 之间的空间太大 所以问题是 如何改变右侧 颜色图例 的外观 见下图 以便它主
  • 仍然可以在节点 run_list 中指定确切的食谱版本吗?

    我的笔记中有这样的内容 run list recipe email protected cdn cgi l email protection 可以明确指定在节点 run list 中使用的说明书版本 但我无法让它工作 也找不到任何文档来说明
  • TryFrom<&[T]> 和 TryFrom> 有什么区别?

    似乎有两种方法可以尝试将向量转换为数组 或者通过切片 fn a 或直接 fn b use std array TryFromSliceError use std convert TryInto type Input Vec
  • 如何将图像从 Laravel 控制器发送到 API Rest [关闭]

    Closed 这个问题需要细节或清晰度 help closed questions 目前不接受答案 我需要从存储中获取图像Laravel并将其从控制器发送到外部 API REST 我正在使用 guzzlehttp multipart 但 A
  • 在 JPA 中使用泛型 @OneToMany

    我有一个班级 分支 我想在这里将其用作 Dictionary 和 Link 类 Entity public class Branch
  • 捕获异常时可以使用gdb进行回溯吗?

    我刚刚开始使用 C 异常并希望得到正确的解决方案 我的想法是在捕获异常时生成某种回溯信息 最初我有类似的想法C 中异常的调用堆栈 https stackoverflow com questions 3222890 call stack fo
  • 如果没有找到任何元素,我可以防止 Cypress cy.get 失败吗?

    我正在使用赛普拉斯cy get抓取元素 但如果没有 我的测试就会失败 我不想让它失败 我希望它继续下去 测试只是列出存在的项目 如果有 const listItemTitle data cy component list item titl
  • 在Python中,是否有一种优雅的方法可以以自定义格式打印列表而无需显式循环?

    我知道你能做到 print str myList to get 1 2 3 你可以做 i 0 for entry in myList print str i entry i 1 to get 0 1 1 2 2 3 但是有没有一种与第一种类
  • canvas.toDataURL() 不是函数 - 错误 node-webGL 包装器

    目前我正在尝试将基于浏览器的客户端体积渲染代码转换为服务器端纯基于 JavaScript 的渲染 我在服务器端使用node webgl 我的主要目标是将服务器的画布内容发送到客户端 然后将该图像数据显示在客户端上 但在此之前我需要检查渲染是
  • mysql 5.7 日志慢查询错误

    我试图在 mysql 5 7 上启用慢查询日志记录并收到此错误 2016 04 27T14 55 51 934612Z 0 错误 未知变量 log slow queries var log mysql query log 2016 04 2
  • 谷歌地图删除所有标记,然后创建新的

    我正在创建一个地图 默认情况下加载地址并显示标记并在搜索框中放置地址 效果很好 但我需要添加单击事件 该事件将首先删除所有标记 然后放置标记 到目前为止 我正在开发满足我需要的所有脚本 但是 当用户单击地图时 搜索框会获取地点地址 但旧标记
  • 为什么这两个代码变体会产生不同的浮点结果?

    给出这个示例 C 代码片段 void floatSurprise these come from some sort of calculation int a 18680 b 3323524 c 121 float m float a c
  • 在R中使用geom_line时显示不正确

    给定一个数据框如下 v1 v2 v3 v4 Tom A Jim B Gary A Shirly A Shirly B Jack B Tom A Jack B v2和v4分别表示v1和v3中的名称属于哪个组 汤姆属于 A 组 吉姆属于 v4
  • 如何检查 JTabbedPane 中的选项卡是否处于活动状态?

    如何检查 JTabbedPane 实例中的选项卡是否处于活动状态 在选项卡 嵌套类 本身的类中而不是在封闭类中 我知道有一个方法booloean isEnabledAt int index 但该方法只能在封闭类中调用 而我想检查当前是否在选
  • 如何进行多线程复制文件

    我想将多个文件复制到一个文件中 但是使用多线程 假设文件A是不同线程复制数据的文件 在这种情况下 每个线程都意味着复制文件A中的一个文件 使用以下过程 procedure ConcatenateFiles const InFileNames
  • 曲面算术/四叉树

    我不久前做了一个使用四叉树进行路径查找的项目 我想提高它的性能 似乎使用 tesseral 算术来确定节点邻接 根据这一页 http www geog ubc ca courses klink gis notes ncgia u37 htm
  • 使用动态转储 ComObject 对象?

    我正在尝试 不幸的是 为我在 Office 类型库中访问的对象实现 对象转储器 这一定是可能的 因为 VS 的调试窗口有一个针对 System ComObject 对象的 动态视图 它可以有效地执行我想要的操作 有任何想法吗 我还创建了一个