我正在實現一個基於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);
}
實施IParentAndItem
與GetParentAndItem
更換BindToHandler
我只能說,這是真的值得去這條路線後性能明智。
請確保在完成這些操作後,通過調用Marshal.FreeCoTaskMem
爲兩個PIDL釋放在GetParentAndItem
中分配的內存。
你是對的,只需檢查並首先聲明SetParentAndItem。不知道這個裁判是從哪裏來的,因爲它清楚地指出在參數 - 謝謝指出。我也錯過了釋放分配給2個PIDL的內存。 – atomicode 2015-03-31 19:04:37