考虑以下用于COM互操作的代码以及互联网快捷方式:
[ComImport]
[InterfaceType(ComInterfaceType.InterfaceIsIUnknown)]
[Guid("CABB0DA0-DA57-11CF-9974-0020AFD79762")]
public interface IUniformResourceLocatorW
{
void SetUrl([MarshalAs(UnmanagedType.LPWStr)] string pcszUrl, int dwInFlags);
void GetUrl([MarshalAs(UnmanagedType.LPWStr)] out StringBuilder ppszUrl);
void InvokeCommand(IntPtr purlici);
}
[ComImport]
[Guid("FBF23B40-E3F0-101B-8488-00AA003E56F8")]
public class InternetShortcut
{
}
以下按预期方式工作:
var ishort = new InternetShortcut();
((IPersistFile)ishort).Load("MyLink.url", 0);
((IUniformResourceLocatorW)ishort).GetUrl(out url);
然而:
IUniformResourceLocatorW.SetUrl
(我没有使用),IUniformResourceLocatorW.GetUrl
会抛出COMException
(HResult 0x80041001)。IUniformResourceLocatorW.SetUrl
和IUniformResourceLocatorW.GetUrl
之间切换(即前者位于后者之下),则抛出相同的异常IUniformResourceLocatorW.InvokeCommand
,代码运行正常。就好像订单必须“保存”到被调用的方法一样。这种行为是设计的吗?在哪里记录?我问,因为一些COM接口由许多支持类型的方法组成,我宁愿避免定义我不需要的东西。
答案 0 :(得分:3)
订单非常非常,非常重要。 COM中的接口指针是指向函数地址表的指针。前三个是IUnknown方法实现的函数指针(AddRef,Release,QueryInterface)。第四个是服务器的SetUrl()方法的地址,第五个是GetUrl()等。
通过从声明中删除SetUrl(),当程序调用GetUrl()时,CLR认为它应该调用表中的第4个函数。因此,根本不调用GetUrl(),它最终调用SetUrl()。哪个得到完全错误的参数,pcszUrl可能是一个空字符串,dwInFlags包含随机垃圾。 KABOOM!当SetUrl在某种带有垃圾值的WMI调用失败时。
您无法从界面中删除方法。您可以使用占位符,例如DoNotCall()
。
否则,你可以通过修改接口来获得强大的DLL地狱课程。