When I'm calling ExtractIconExW
a couple of hundres times my application crashes with all sorts of random errors, mainly "out of memory" related (even though Task Manager indicates it only uses a couple of hundred megabytes).
I've tried cleanup up after it with the DeleteObject
function, but to no avail.
This is my implementation:
Public Shared Function ExtractIcon(ref As String) As BitmapSource
Dim s() As String = Split(ref, ","), icon As IntPtr, iconl As IntPtr
Try
Functions.ExtractIconEx(s(0), s(1), iconl, icon, 1)
If Not IntPtr.Zero.Equals(icon) Then
Return System.Windows.Interop.Imaging.CreateBitmapSourceFromHIcon(icon, Int32Rect.Empty, BitmapSizeOptions.FromEmptyOptions()))
End If
Finally
Functions.DeleteObject(icon)
Functions.DeleteObject(iconl)
End Try
Return Nothing
End Function
I use these declarations:
<DllImport("Shell32.dll", EntryPoint:="ExtractIconExW", CharSet:=CharSet.Unicode, ExactSpelling:=True, CallingConvention:=CallingConvention.StdCall)>
Public Shared Function ExtractIconEx(sFile As String, iIndex As Integer, ByRef piLargeVersion As IntPtr, ByRef piSmallVersion As IntPtr, amountIcons As Integer) As Integer
End Function
<DllImport("gdi32.dll", SetLastError:=True)>
Public Shared Function DeleteObject(ByVal hObject As IntPtr) As Boolean
End Function
The documentation for ExtractIconEx
states that:
When they are no longer needed, you must destroy all icons extracted by ExtractIconEx by calling the DestroyIcon function.
This means calling DeleteObject
is not what you should do. For proper cleanup you should call DestroyIcon
.
The Pinvoke signature for it for vb.net is:
<DllImport("user32.dll", SetLastError:=True)> _
Private Shared Function DestroyIcon(ByVal hIcon As IntPtr) As Boolean
End Function