2015-03-31 40 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