gpt4 book ai didi

c# - 使用动态转储 ComObject 的对象?

转载 作者:行者123 更新时间:2023-11-30 22:32:07 29 4
gpt4 key购买 nike

我正在尝试(不走运)为我在 Office 类型库中访问的对象实现“对象转储程序”。

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

有什么想法吗?

最佳答案

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

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

您的代码中必须有一个 IDispatch 接口(interface):

[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,获取非托管类型信息,从非公共(public) 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);

关于c# - 使用动态转储 ComObject 的对象?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/8869548/

29 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com