dcsimg

Extracting Icons Associated with Files in Visual Basic.NET

WEBINAR:
On-Demand

Building the Right Environment to Support AI, Machine Learning and Deep Learning


Introduction

Every file has an icon. This icon depends on the program that can open the file in question. Obtaining these icons can be tricky, or easy, depending on the route you take. In this article, you will learn how to extract associated icons from files and display them in your programs.

I will demonstrate the different methods of extracting icons. One uses the built-in .NET Framework capabilities, and the other methods demonstrate Windows API methods.

Practical

Open Visual Studio and create a new Visual Basic Windows Forms application. On your form, add the following objects:

  • Two Buttons
  • One ListView
  • One ImageList

Set the following properties for the ListView:

  • View: SmallIcon
  • SmallImageList: The name of your ImageList

Your design should look like Figure 1.

Design
Figure 1: Design

Code

Add the following code:

   Public Sub ExtractIcon_1()

      Dim dInfo As New System.IO.DirectoryInfo("c:\")

      Dim lvItem As ListViewItem

      ListView2.BeginUpdate()

      ListView2.Items.Clear()

      Dim CurrFile As System.IO.FileInfo

      For Each CurrFile In dInfo.GetFiles()

         Dim iFileIcon As Icon = SystemIcons.WinLogo

         lvItem = New ListViewItem(CurrFile.Name, 1)

         If Not (ImageList2.Images.ContainsKey _
               (CurrFile.Extension)) Then

            iFileIcon = System.Drawing.Icon.ExtractAssociatedIcon _
               (CurrFile.FullName)

            ImageList2.Images.Add(CurrFile.Extension, iFileIcon)

         End 

         lvItem.ImageKey = CurrFile.Extension
         ListView2.Items.Add(

      Next CurrFile

      ListView2.EndUpdate()

   End Sub

Add the following subroutine behind the first button:

   Private Sub Button1_Click(sender As Object, e As EventArgs) _
         Handles Button1.Click

      ExtractIcon_1()

   End Sub

The ExtractIcon_1 sub procedure loops through each of the files in the given path, and then makes use of the System.Drawing.Icon.ExtractAssociatedIcon method to extract each icon.

Add the following namespace to allow for working with the Windows API:

Imports System.Runtime.InteropServices

Add the following Windows APIs, Structs, Enums, and Constants:

   <DllImport("shell32.dll", CharSet:=CharSet.Auto)>
   Private Shared Function SHGetFileInfo(ByVal pszPath As String, _
      ByVal dwFileAttributes As Integer, <Out> ByRef _
      psfi As SHFILEINFO, ByVal cbfileInfo As UInteger, _
      ByVal uFlags As SHGFI) As Integer
   End Function
   <StructLayout(LayoutKind.Sequential, CharSet:=CharSet.Auto)>
   Private Structure SHFILEINFO

      Public Sub New(ByVal b As Boolean)

         hIcon = IntPtr.Zero
         iIcon = 0
         dwAttributes = 
         szDisplayName = ""
         szTypeName = ""

      End Sub

      Public hIcon As IntPtr

      Public iIcon As Integer

      Public dwAttributes As UInteger

      <MarshalAs(UnmanagedType.ByValTStr, SizeConst:=MAX_PATH)>
      Public szDisplayName As String

      <MarshalAs(UnmanagedType.ByValTStr, SizeConst:=MAX_TYPE)>
      Public szTypeName As String

   End Structure

   <Flags>
   Enum SHGFI

      Icon = 256
      DisplayName = 512
      TypeName = 1024
      Attributes = 2048
      IconLocation = 4096
      ExeType = 8192
      SysIconIndex = 16384
      LinkOverlay = 32768
      Selected = 65536
      Attr_Specified = 131072
      LargeIcon = 0
      SmallIcon = 1
      OpenIcon = 2
      ShellIconSize = 4
      PIDL = 8
      UseFileAttributes = 16
      AddOverlays = 32
      OverlayIndex = 64

   End Enum

The SHGetFileInfo Windows API function retrieves information about a file or folder. The SHFILEINFO API structure contains information about a file object. Add the following code:

   Private Function GetIcons_2(ByVal strPath As String, _
         ByVal blnSmall As Boolean) As Icon

      Dim shInfo As SHFILEINFO = New SHFILEINFO(

      Dim intInfo As Integer = Marshal.SizeOf(shInfo)

      Dim fSettings As SHGFI

      If blnSmall Then fSettings = SHGFI.Icon Or
         SHGFI.SmallIcon Or SHGFI.UseFileAttributes _
            Else fSettings = SHGFI.Icon Or
         SHGFI.LargeIcon Or SHGFI.UseFileAttributes

      SHGetFileInfo(strPath, 256, shInfo, CUInt(intInfo), _
         fSettings)

      Return Icon.FromHandle(shInfo.hIcon)

   End Function
   Public Sub ExtractIcon_2()

      Dim dInfo As New System.IO.DirectoryInfo("c:\")

      Dim lvItem As ListViewItem

      ListView2.BeginUpdate()

      ListView2.Items.Clear()

      Dim CurrFile As System.IO.FileInfo

      For Each CurrFile In dInfo.GetFiles()

         Dim iFileIcon As Icon = SystemIcons.WinLogo

         lvItem = New ListViewItem(CurrFile.Name, 1)

         If Not (ImageList2.Images.ContainsKey _
               (CurrFile.Extension)) Then

            iFileIcon = GetIcons_2(CurrFile.FullName, True)

            ImageList2.Images.Add(CurrFile.Extension, iFileIcon)

         End If

         lvItem.ImageKey = CurrFile.Extension
         ListView2.Items.Add(lvItem)

      Next CurrFile

      ListView2.EndUpdate()

   End Sub


   Private Sub Button2_Click(sender As Object, e As EventArgs) _
         Handles Button2.Click

      ExtractIcon_2()

   End Sub

You may have noticed that there are many similarities between the first ExtractIcon sub (ExtractIcon_1) and ExtractIcon_2. It is basically verbatim the same, except for the assignment of the icon. ExtractIcon_2 calls the GetIcons_2 method, which returns the specified icon with the specified size and settings. Lastly, add the following code to see another Windows API method to extract icons:

   <DllImport("shell32.dll", CharSet:=CharSet.Auto)>
   Shared Function ExtractIconEx(ByVal szFileName As String,
      ByVal nIconIndex As Integer,
      ByVal phiconLarge() As IntPtr,
      ByVal phiconSmall() As IntPtr,
      ByVal nIcons As Integer) As Integer
   End Function

   <DllImport("user32.dll", EntryPoint:="DestroyIcon", _
      SetLastError:=True)>
   Shared Function DestroyIcon(ByVal hIcon As IntPtr) As Integer
   End Function

   Private Const MAX_PATH As Integer = 260

   Private Const MAX_TYPE As Integer = 80



   Public Function GetIcons_3(ByVal strPath As String, _
         ByVal blnLarge As Boolean) As Icon

      Dim intCount As Integer = 0

      Dim iptLarge As IntPtr() = New IntPtr(0) {IntPtr.Zero}
      Dim iptSmall As IntPtr() = New IntPtr(0) {IntPtr.Zero}

      Try

         If (blnLarge) Then

            intCount = ExtractIconEx(strPath, 0, iptSmall, _
               iptLarge, 1)

         Else

            intCount = ExtractIconEx(strPath, 0, iptLarge, _
               iptSmall, 1)

         End If

         If (intCount > 0 AndAlso Not iptSmall(0).Equals _
               (IntPtr.Zero)) Then

            Dim extractedIcon As Icon = Icon.FromHandle _
               (iptSmall(0)).Clone()

            Return extractedIcon

         Else

            Return Nothing

         End If

      Catch ex As Exception


         Throw New ApplicationException("Error: ", ex)

      Finally

         For Each ptr As IntPtr In iptSmall

            If (Not ptr.Equals(IntPtr.Zero)) Then

               DestroyIcon(ptr)

            End If

            Next ptr

            For Each ptr As IntPtr In iptLarge

               If Not (ptr.Equals(IntPtr.Zero)) Then

                  DestroyIcon(ptr)

               End If

            Next ptr

      End Try

   End Function

The ExtractIconEx function creates an array of handles to icons extracted from the specified file.

Additional Reading

I wrote the following articles some time ago. They should give you more detail on understanding File Associations.

The code for this article is available on GitHub.

Conclusion

Complicated things are sometimes not too complicated. Extracting icons from files will come in handy, and it polishes off your program's little features nicely.



About the Author

Hannes DuPreez

Hannes du Preez is an ex MVP for Visual Basic from 2008 to 2017. He loves technology and loves Visual Basic and C#. He loves writing articles and proving that Visual Basic is more powerful than what most believe. You are most welcome to reach him at: ojdupreez1978[at]gmail[dot]com

Related Articles

Comments

  • There are no comments yet. Be the first to comment!

  • You must have javascript enabled in order to post comments.

Leave a Comment
  • Your email address will not be published. All fields are required.

Top White Papers and Webcasts

  • As all sorts of data becomes available for storage, analysis and retrieval - so called 'Big Data' - there are potentially huge benefits, but equally huge challenges...
  • The agile organization needs knowledge to act on, quickly and effectively. Though many organizations are clamouring for "Big Data", not nearly as many know what to do with it...
  • Cloud-based integration solutions can be confusing. Adding to the confusion are the multiple ways IT departments can deliver such integration...

Most Popular Programming Stories

More for Developers

RSS Feeds

Thanks for your registration, follow us on our social networks to keep up-to-date