从托管代码调用SHCreateItemFromParsingName时是否需要释放资源?

时间:2012-02-09 12:20:34

标签: c# .net shell native shell32

我有以下code

[DllImport("shell32.dll", CharSet = CharSet.Unicode, PreserveSig = false)]
static extern void SHCreateItemFromParsingName(
[In][MarshalAs(UnmanagedType.LPWStr)] string pszPath,
[In] IntPtr pbc,
[In][MarshalAs(UnmanagedType.LPStruct)] Guid iIdIShellItem,
[Out][MarshalAs(UnmanagedType.Interface, IidParameterIndex = 2)] out IShellItem iShellItem);


[ComImport]
[InterfaceType(ComInterfaceType.InterfaceIsIUnknown)]
[Guid("43826d1e-e718-42ee-bc55-a1e261c37bfe")]
interface IShellItem
{
}

使用此功能:

IShellItem iShellItem = null;
Guid iIdIShellItem = new Guid("43826d1e-e718-42ee-bc55-a1e261c37bfe");
SHCreateItemFromParsingName(sourceFile, IntPtr.Zero, iIdIShellItem, out iShellItem);

它工作得很好,我用它来获取OS图标位图。我的问题是:

我需要释放任何资源吗?有人可以告诉我怎么做?

提前致谢。

1 个答案:

答案 0 :(得分:4)

IShellItem是一个COM接口。使用[ComImport]属性声明它可确保CLR为它创建一个包装器,即RCW(运行时可调用包装器)。这是本机界面的托管包装器。 RCW的行为与常规的.NET类一样,它们由垃圾收集器管理。使用完全相同的规则,垃圾收集器迟早会看到您的程序不再引用RCW。并输入终结队列。 RCW的终结器调用IUnknown :: Release()方法并销毁本机COM对象。

换句话说,它就像.NET对象一样是自动的。

你在技术上可以通过调用Marshal.ReleaseComObject()来快速进行。它大致相当于IDisposable.Dispose(),RCW没有实现的方法,因为很难看到COM接口指针上的间接引用。使用它是一种拍摄你的脚的好方法,因为你错过了一个引用并且你的程序崩溃了“与它的底层RCW分离的COM对象无法使用”,因此它之间的错误行为完全没有任何影响。只是不需要简单的shell项引用,特别是当您快速使用它时。