2015-03-31 50 views
0

我正在实现一个基于C#中的IShellItem/IShellItem2 COM接口的对象模型,目前正在处理项目枚举。我想避免使用BindToHandler,因为它被认为会对性能产生显着影响,这就是为什么我想使用IParentAndItem接口及其基础缓存机制。实现IParentAndItem COM接口的正确方法

根据MSDN的IParentAndItem接口的方法被定义如下:

HRESULT GetParentAndItem(
    [out, optional] PIDLIST_ABSOLUTE *ppidlParent, 
    [out, optional] IShellFolder **ppsf, 
    [out, optional] PITEMID_CHILD *ppidlChild 
); 

HRESULT SetParentAndItem(
    [in] PCIDLIST_ABSOLUTE pidlParent, 
    [in] IShellFolder *psf, 
    [in] PCUITEMID_CHILD pidlChild 
); 

然而以下翻译成C#COM互界面导致一个AccessViolationException

[ComImport, 
Guid("B3A4B685-B685-4805-99D9-5DEAD2873236"), 
InterfaceType(ComInterfaceType.InterfaceIsIUnknown)] 
public interface IParentAndItem 
{ 
    void GetParentAndItem(out IntPtr ppidlParent, out IShellFolder ppsf, out IntPtr ppidlChild); 

    void SetParentAndItem(IntPtr pidlParent, ref IShellFolder psf, IntPtr pidlChild); 
} 

我使用接口从IShellItem2进行投射以使用其GetParentAndItem方法获得IShellFolder表示法:

IParentAndItem pni = si as IParentAndItem; // 'si' is the IShellItem2 
if(pni != null) 
{ 
    IntPtr ppidlParent, ppidlChild; 
    IShellFolder ppsf; 
    pni.GetParentAndItem(out ppidlParent, out ppsf, out ppidlChild); // <-- throws AccessViolationException 
    // Work with ppsf, e.g. EnumObjects 
} 

UPDATE

IParentAndItem正确的声明由汉斯帕桑特指出:

[ComImport, 
Guid("B3A4B685-B685-4805-99D9-5DEAD2873236"), 
InterfaceType(ComInterfaceType.InterfaceIsIUnknown)] 
public interface IParentAndItem 
{ 
    void SetParentAndItem(IntPtr pidlParent, IShellFolder psf, IntPtr pidlChild); 

    void GetParentAndItem(out IntPtr ppidlParent, out IShellFolder ppsf, out IntPtr ppidlChild); 
} 

实施IParentAndItemGetParentAndItem更换BindToHandler我只能说,这是真的值得去这条路线后性能明智。

请确保在完成这些操作后,通过调用Marshal.FreeCoTaskMem为两个PIDL释放在GetParentAndItem中分配的内存。

回答

1

它应该会崩溃。不知道它是如何发生的,但我可以猜到。 MSDN文档有点笨拙,它没有按照它们出现在界面中的顺序记录这些方法。使用SDK中的ShObjIdl.idl进行验证,首先使用Set方法。所以,现在你正在调用完全错误的方法:)只需在你的C#声明中交换它们。

您的SetParentAndItem()声明有一个错误,您必须从第二个参数中删除ref

+0

你是对的,只需检查并首先声明SetParentAndItem。不知道这个裁判是从哪里来的,因为它清楚地指出在参数 - 谢谢指出。我也错过了释放分配给2个PIDL的内存。 – atomicode 2015-03-31 19:04:37