Hi Peter,
I check through the code in
http://www.codeproject.com/csharp/csdoesshell1.asp and doubt that it is
entirely correct. In the code SHGetMalloc is declared as below:
[DllImport("shell32.dll")]
public static extern Int32 SHGetMalloc(out IntPtr hObject);
Without further qualification, how could the runtime know that hObject is an
interface pointer and know how to release it properly after use? Indeed this
is where the author of the article has missed. Marshal.ReleaseComObject only
releases the interface pointer up to the point where
Marshal.GetTypedObjectForIUnknown is called and a call to Marshal.Release is
required to fully release the interface pointer:
Marshal.Release(hObject);
I have written simple COM servers to research further on returning COM
interface from an unmanaged DLL via PInvoke. For the benefit of other
readers, the outcome of my research follows.
Using SHGetMalloc as an example, the following three methods are equally
correct way of getting an interface pointer via PInvoke and properly
releasing it after use (error handling has been omitted).
Method 1:
[DllImport("shell32.dll")]
public static extern int SHGetMalloc(out IMalloc pMalloc);
IMalloc pMalloc;
SHGetMalloc(out pMalloc);
// Do something useful with pMalloc here
Marshal.ReleaseComObject(pMalloc);
// Calling Marshal.ReleaseComObject is optional
// If it is not called, the runtime will release pMalloc when it is garbage
collected
Method 2:
[DllImport("shell32.dll")]
public static extern int SHGetMalloc(out IntPtr malloc);
IntPtr malloc;
SHGetMalloc(out malloc);
IMalloc pMalloc = (IMalloc)Marshal.GetObjectForIUnknown(malloc);
// Do something useful with pMalloc here
Marshal.ReleaseComObject(pMalloc);
// Calling Marshal.ReleaseComObject is optional
// If it is not called, the runtime will release pMalloc when it is garbage
collected
Marshal.Release(malloc);
Method 3:
[DllImport("shell32.dll")]
public static extern int SHGetMalloc([MarshalAs(UnmanagedType.Interface)]
out object malloc);
object malloc;
SHGetMalloc(out malloc);
IMalloc pMalloc = (IMalloc)malloc;
// Do something useful with pMalloc here
Marshal.ReleaseComObject(pMalloc);
// Equivalently Marshal.ReleaseComObject(malloc);
// Calling Marshal.ReleaseComObject is optional
// If it is not called, the runtime will release pMalloc / malloc
// when it is garbage collected
Thanks.
Best regards,
jorfei
[quoted text, click to view] ""Peter Huang" [MSFT]" wrote:
> Hi Jorfei,
>
> Sorry for delay response, because the concrete implement of .NET 2.0 CLR is
> not public, and based on my research I did not find information about the
> detailed implement detailed.
>
> But from the sample from the code project we should call the
> Marshal.ReleaseComObject to release the IntPtr from P/Invoke.
>
http://www.codeproject.com/csharp/csdoesshell1.asp >
>
http://dotnetdebug.blogspot.com/2005/07/marshalreleasecomobject-and-cpu.html >
> Also I do recommend you call Marshal.ReleaseComObject to explicitly release
> a com object when you will not use the COM any longer.
>
> If you have any concern, please feel free to let me know.
>
> Best regards,
>
> Peter Huang
>
> Microsoft Online Community Support
> ==================================================
> When responding to posts, please "Reply to Group" via your newsreader so
> that others may learn and benefit from your issue.
> ==================================================
> This posting is provided "AS IS" with no warranties, and confers no rights.
>