当我执行以下代码行时
dispatch.GetTypeInfoCount(ref typeInfoCount);
抛出以下异常
“System.Int32”类型的对象无法转换为“System.UInt32&”
类型using System.Runtime.InteropServices;
using ComTypes2 = System.Runtime.InteropServices.ComTypes;
public class ComHelper
{
[ComImport(), Guid("00020400-0000-0000-c000-000000000046"), InterfaceType(ComInterfaceType.InterfaceIsIUnknown)]
private interface IDispatch
{
void GetTypeInfoCount(ref uint pctinfo);
void GetTypeInfo(uint itinfo, uint lcid, ref IntPtr pptinfo);
void stub_GetIDsOfNames();
void Invoke(int dispIdMember,
ref Guid riid,
uint lcid,
ushort dwFlags,
ref ComTypes2.DISPPARAMS pDispParams,
ref object pVarResult,
ref IntPtr pExcepInfo,
ref uint pArgErr);
}
public static bool CheckIfComPropertyOrMethodExists<T1>(T1 objectToCheck, string propertyOrMethodName)
{
ComTypes2.ITypeInfo objectTypeInfo = null;
var objectITypeInfo = default(IntPtr);
var pFuncDesc = default(IntPtr);
try
{
// Convert the object to IDispatch
var dispatch = (IDispatch)objectToCheck;
uint typeInfoCount = 0;
// Attempt to get the objects TypeInfo
dispatch.GetTypeInfoCount(ref typeInfoCount);
if (typeInfoCount < 1) throw new ApplicationException("No type info");
dispatch.GetTypeInfo(0, 0, ref objectITypeInfo);
if (objectITypeInfo == IntPtr.Zero) throw new ApplicationException("No ITypeInfo");
objectTypeInfo = (ComTypes2.ITypeInfo)Marshal.GetTypedObjectForIUnknown(objectITypeInfo, typeof(ComTypes2.ITypeInfo));
var pTypeAttr = default(IntPtr);
objectTypeInfo.GetTypeAttr(out pTypeAttr);
var typeAttr = (ComTypes2.TYPEATTR)Marshal.PtrToStructure(pTypeAttr, typeof(ComTypes2.TYPEATTR));
objectTypeInfo.ReleaseTypeAttr(pTypeAttr);
// Find the method we're looking for in the list of COM objects methods
for (var iFunc = 0; iFunc <= typeAttr.cFuncs - 1; iFunc++)
{
objectTypeInfo.GetFuncDesc(iFunc, out pFuncDesc);
var funcDesc = (ComTypes2.FUNCDESC)Marshal.PtrToStructure(pFuncDesc, typeof(ComTypes2.FUNCDESC));
string[] names = { string.Empty };
int pcNames;
objectTypeInfo.GetNames(funcDesc.memid, names, 1, out pcNames);
var funcName = names[0];
if (funcName == propertyOrMethodName)
{
return true;
}
objectTypeInfo.ReleaseFuncDesc(pFuncDesc);
}
return false;
}
finally
{
if (objectTypeInfo != null)
{
objectTypeInfo.ReleaseFuncDesc(pFuncDesc);
}
Marshal.Release(objectITypeInfo);
}
}
}
我确信答案很简单,但我现在无法解决。 GetTypeInfoCount的参数是一个uint。通过引用GetTypeInfoCount方法传递的局部变量typeInfoCount也是一个uint。为什么我会收到类型转换异常?
这个问题涉及以下
How to check if a COM property or method exists without generating an exception?
目前有用的链接
http://msdn.microsoft.com/en-us/library/ebbff4bc-36b2-4861-9efa-ffa45e013eb5%28VS.85%29
答案 0 :(得分:2)
尝试使用out
代替ref
:
void GetTypeInfoCount(out uint pctinfo);
然后:
uint typeInfoCount;
dispatch.GetTypeInfoCount(out typeInfoCount);
顺便说一下,GetTypeInfo
方法存在同样的问题。您使用ref
作为指针,但它应该是out
:
void GetTypeInfo(uint itinfo, uint lcid, out IntPtr pptinfo);
这是IDispatch接口的正确P / Invoke包装器:
[Guid("00020400-0000-0000-C000-000000000046")]
[InterfaceType(ComInterfaceType.InterfaceIsIUnknown)]
internal interface IDispatch
{
void GetTypeInfoCount(out uint pctinfo);
void GetTypeInfo(uint iTInfo, int lcid, out IntPtr info);
void GetIDsOfNames(ref Guid iid, [MarshalAs(UnmanagedType.LPArray, ArraySubType=UnmanagedType.LPWStr, SizeParamIndex=2)] string[] names, uint cNames, int lcid, [Out, MarshalAs(UnmanagedType.LPArray, ArraySubType=UnmanagedType.I4, SizeParamIndex=2)] int[] rgDispId);
void Invoke(int dispIdMember, ref Guid riid, int lcid, INVOKEKIND wFlags, ref DISPPARAMS pDispParams, IntPtr pvarResult, IntPtr pExcepInfo, IntPtr puArgErr);
}