2012-02-09 84 views
2

我有以下code从托管代码调用SHCreateItemFromParsingName时是否需要释放资源?

[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图标位图。我的问题是:

我需要释放任何资源吗?有人能告诉我如何?

在此先感谢。

回答

4

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

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

您在技术上可以通过调用Marshal.ReleaseComObject()来快速启动它。它大致相当于IDisposable.Dispose(),这是RCW不实现的方法,因为在COM接口指针上看到间接引用是非常困难的。使用它是一种很好的方式,但是在它之间的不正当行为根本没有任何作用,因为你错过了一个参考,并以“与其基础RCW分离的COM对象不能使用”的方式崩溃了程序。只需一个简单的shell引用就不需要了,特别是当你快速使用它时。