ComImport接口中的重新排序方法抛出COMException(0x80041001)

时间:2014-05-31 21:22:48

标签: c# .net com com-interop

考虑以下用于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.SetUrlIUniformResourceLocatorW.GetUrl之间切换(即前者位于后者之下),则抛出相同的异常
  • 如果我发表评论IUniformResourceLocatorW.InvokeCommand,代码运行正常。

就好像订单必须“保存”到被调用的方法一样。这种行为是设计的吗?在哪里记录?我问,因为一些COM接口由许多支持类型的方法组成,我宁愿避免定义我不需要的东西。

1 个答案:

答案 0 :(得分:3)

订单非常非常非常重要。 COM中的接口指针是指向函数地址表的指针。前三个是IUnknown方法实现的函数指针(AddRef,Release,QueryInterface)。第四个是服务器的SetUrl()方法的地址,第五个是GetUrl()等。

通过从声明中删除SetUrl(),当程序调用GetUrl()时,CLR认为它应该调用表中的第4个函数。因此,根本不调用GetUrl(),它最终调用SetUrl()。哪个得到完全错误的参数,pcszUrl可能是一个空字符串,dwInFlags包含随机垃圾。 KABOOM!当SetUrl在某种带有垃圾值的WMI调用失败时。

您无法从界面中删除方法。您可以使用占位符,例如DoNotCall()

否则,你可以通过修改接口来获得强大的DLL地狱课程。