.netwindowsvb.netwinapi

What causes ExtractIconExW to leak memory?


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

Solution

  • 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