66

I'd like to get the Tree icon to use for a homegrown app. Does anyone know how to extract the images out as .icon files? I'd like both the 16x16 and 32x32, or I'd just do a screen capture.

Santiago Squarzon
  • 41,465
  • 5
  • 14
  • 37
Jay Mooney
  • 2,208
  • 1
  • 19
  • 23
  • 11
    Note that doing this is a violation of the license. "While the software is running, you may use but not share its icons, images, sounds, and media." – Raymond Chen Mar 29 '13 at 22:45

13 Answers13

78

If anyone is seeking an easy way, just use 7zip to unzip the shell32.dll and look for the folder .src/ICON/

AQN
  • 789
  • 5
  • 2
57

In Visual Studio, choose "File Open..." then "File...". Then pick the Shell32.dll. A folder tree should be opened, and you will find the icons in the "Icon" folder.

To save an Icon, you can right-click on the icon in the folder tree and choose "Export".

Captain Ford
  • 350
  • 1
  • 9
jm.
  • 23,422
  • 22
  • 79
  • 93
  • 2
    when I use this I only have this folder tree and all the icons listed but without a preview and the titles aren't that helpfull (1, 10, 1001, ..) Is there a way to get a preview or do I really have to open all the Icons? – Dominik Jul 23 '15 at 10:46
  • 2
    @MickyD Can't confirm - exporting Icons worked like a charm for me in VS Community 2017 (15.8.3) - just as written in this answer. The menu may have changed a bit - it's now "File" --> "Open" --> "File...". (I copied shell32.dll to my desktop to test this) – RicoBrassers Sep 20 '18 at 06:11
  • 1
    @RicoBrassers well that's embarrassing, works now. I must have done something silly. Thanks buddy :) –  Sep 20 '18 at 06:41
  • It is important to open the shell32.dll file from the Windows\System32 folder, otherwise there is no "Icon" folder. – ViH Dec 24 '21 at 15:24
  • 1
    As of 2023, this solution no longer works in Windows 10 or 11. The [TheManInOz's answer](https://stackoverflow.com/a/71200876/1469208) is the only one correct right now. – trejder Jan 27 '23 at 19:17
22

Another option is to use a tool such as ResourceHacker. It handles way more than just icons as well. Cheers!

OJ.
  • 28,944
  • 5
  • 56
  • 71
19

Not sure if I am 100% correct, but from my testing, the above options for using 7Zip or VS don't work on Windows 10 / 11 versions of imageres.dll or shell32.dll. This is the content I see:

[shell32.dll]
.rsrc\MANIFEST\124
.rsrc\MUI\1
.rsrc\TYPELIB\1
.rsrc\version.txt
.data
.didat
.pdata
.rdata
.reloc
.text
CERTIFICATE

Update: And I think I found why. Link to an article I found. (Sorry for being off-domain). You can find the resources in files in these locations:

"C:\Windows\SystemResources\shell32.dll.mun"
"C:\Windows\SystemResources\imageres.dll.mun"

Icons no longer in imageres.dll in Windows 10 1903 - 4kb file (superuser.com)

TheManInOz
  • 191
  • 1
  • 3
14

I needed to extract icon #238 from shell32.dll and didn't want to download Visual Studio or Resourcehacker, so I found a couple of PowerShell scripts from Technet (thanks John Grenfell and to #https://social.technet.microsoft.com/Forums/windowsserver/en-US/16444c7a-ad61-44a7-8c6f-b8d619381a27/using-icons-in-powershell-scripts?forum=winserverpowershell) that did something similar and created a new script (below) to suit my needs.

The parameters I entered were (the source DLL path, target icon file name and the icon index within the DLL file):

C:\Windows\System32\shell32.dll

C:\Temp\Restart.ico

238

I discovered the icon index that I needed was #238 by trial and error by temporarily creating a new shortcut (right-click on your desktop and select New --> Shortcut and type in calc and press Enter twice). Then right-click the new shortcut and select Properties then click 'Change Icon' button in the Shortcut tab. Paste in path C:\Windows\System32\shell32.dll and click OK. Find the icon you wish to use and work out its index. NB: Index #2 is beneath #1 and not to its right. Icon index #5 was at the top of column two on my Windows 7 x64 machine.

If anyone has a better method that works similarly but obtains higher quality icons then I'd be interested to hear about it. Thanks, Shaun.

#Windows PowerShell Code###########################################################################
# http://gallery.technet.microsoft.com/scriptcenter/Icon-Exporter-e372fe70
#
# AUTHOR: John Grenfell
#
###########################################################################

<#
.SYNOPSIS
   Exports an ico and bmp file from a given source to a given destination
.Description
   You need to set the Source and Destination locations. First version of a script, I found other examples but all I wanted to do as grab and ico file from an exe but found getting a bmp useful. Others might find useful
   No error checking I'm afraid so make sure your source and destination locations exist!
.EXAMPLE
    .\Icon_Exporter.ps1
.Notes
        Version HISTORY:
        1.1 2012.03.8
#>
Param ( [parameter(Mandatory = $true)][string] $SourceEXEFilePath,
        [parameter(Mandatory = $true)][string] $TargetIconFilePath
)
CLS
#"shell32.dll" 238
If ($SourceEXEFilePath.ToLower().Contains(".dll")) {
    $IconIndexNo = Read-Host "Enter the icon index: "
    $Icon = [System.IconExtractor]::Extract($SourceEXEFilePath, $IconIndexNo, $true)    
} Else {
    [void][Reflection.Assembly]::LoadWithPartialName("System.Drawing")
    [void] [System.Reflection.Assembly]::LoadWithPartialName("System.Windows.Forms")
    $image = [System.Drawing.Icon]::ExtractAssociatedIcon("$($SourceEXEFilePath)").ToBitmap()
    $bitmap = new-object System.Drawing.Bitmap $image
    $bitmap.SetResolution(72,72)
    $icon = [System.Drawing.Icon]::FromHandle($bitmap.GetHicon())
}
$stream = [System.IO.File]::OpenWrite("$($TargetIconFilePath)")
$icon.save($stream)
$stream.close()
Write-Host "Icon file can be found at $TargetIconFilePath"
Shaun
  • 366
  • 1
  • 6
  • 15
  • Great method but it doesn't work for me. I am on Windows 7x64 on which script seems to be confirmed to work. But I get `TypeNotFound` errors for `System.Drawing.Icon` and `System.Drawing.Bitmap`. My first try to run a PS-script so maybe I do something wrong? – Danny Lo Jan 18 '16 at 01:07
  • 1
    Ok, I just needed to execute `Add-Type -AssemblyName System.Drawing` first. – Danny Lo Jan 18 '16 at 01:12
  • Worked perfectly without having to add any assembly – David Trevor Jul 08 '20 at 07:02
7

Just open the DLL with IrfanView and save the result as a .gif or .jpg.

I know this question is old, but it's the second google hit from "extract icon from dll", I wanted to avoid installing anything on my workstation and I remembered I use IrfanView.

pocesar
  • 6,860
  • 6
  • 56
  • 88
MannyO
  • 71
  • 1
  • 1
  • I already use IrfanView so this was an easy choice for a quick browse of the icons. Press **F10** to see thumbnails of all the stored images. I did not find a way to identify the image number. Is there a way? – Ben May 12 '22 at 15:48
6

Resources Extract is another tool that will recursively find icons from a lot of DLLs, very handy IMO.

Steve Cadwallader
  • 2,656
  • 4
  • 28
  • 37
  • 3
    While that tool is good for pulling the resource out, they also have a tool IconsExtract https://www.nirsoft.net/utils/iconsext.html that I find more handy in most cases since I can browse the icons and simply link to the system file when I want the icon in an embedded/linked document in Office. – undrline - Reinstate Monica Sep 07 '18 at 18:50
  • As of 2023, this solution no longer works in Windows 10 or 11. The [TheManInOz's answer](https://stackoverflow.com/a/71200876/1469208) is the only one correct right now. – trejder Jan 27 '23 at 19:18
3

Here is an updated version of a solution above. I added a missing assembly that was buried in a link. Novices will not understand that. This is sample will run without modifications.

    <#
.SYNOPSIS
    Exports an ico and bmp file from a given source to a given destination
.Description
    You need to set the Source and Destination locations. First version of a script, I found other examples 
    but all I wanted to do as grab and ico file from an exe but found getting a bmp useful. Others might find useful
.EXAMPLE
    This will run but will nag you for input
    .\Icon_Exporter.ps1
.EXAMPLE
    this will default to shell32.dll automatically for -SourceEXEFilePath
    .\Icon_Exporter.ps1 -TargetIconFilePath 'C:\temp\Myicon.ico' -IconIndexNo 238
.EXAMPLE
    This will give you a green tree icon (press F5 for windows to refresh Windows explorer)
    .\Icon_Exporter.ps1 -SourceEXEFilePath 'C:/Windows/system32/shell32.dll' -TargetIconFilePath 'C:\temp\Myicon.ico' -IconIndexNo 41

.Notes
    Based on http://stackoverflow.com/questions/8435/how-do-you-get-the-icons-out-of-shell32-dll Version 1.1 2012.03.8
    New version: Version 1.2 2015.11.20 (Added missing custom assembly and some error checking for novices)
#>
Param ( 
    [parameter(Mandatory = $true)]
    [string] $SourceEXEFilePath = 'C:/Windows/system32/shell32.dll',
    [parameter(Mandatory = $true)]
    [string] $TargetIconFilePath,
    [parameter(Mandatory = $False)]
    [Int32]$IconIndexNo = 0
)

#https://social.technet.microsoft.com/Forums/windowsserver/en-US/16444c7a-ad61-44a7-8c6f-b8d619381a27/using-icons-in-powershell-scripts?forum=winserverpowershell
$code = @"
using System;
using System.Drawing;
using System.Runtime.InteropServices;

namespace System
{
    public class IconExtractor
    {

     public static Icon Extract(string file, int number, bool largeIcon)
     {
      IntPtr large;
      IntPtr small;
      ExtractIconEx(file, number, out large, out small, 1);
      try
      {
       return Icon.FromHandle(largeIcon ? large : small);
      }
      catch
      {
       return null;
      }

     }
     [DllImport("Shell32.dll", EntryPoint = "ExtractIconExW", CharSet = CharSet.Unicode, ExactSpelling = true, CallingConvention = CallingConvention.StdCall)]
     private static extern int ExtractIconEx(string sFile, int iIndex, out IntPtr piLargeVersion, out IntPtr piSmallVersion, int amountIcons);

    }
}
"@

If  (-not (Test-path -Path $SourceEXEFilePath -ErrorAction SilentlyContinue ) ) {
    Throw "Source file [$SourceEXEFilePath] does not exist!"
}

[String]$TargetIconFilefolder = [System.IO.Path]::GetDirectoryName($TargetIconFilePath) 
If  (-not (Test-path -Path $TargetIconFilefolder -ErrorAction SilentlyContinue ) ) {
    Throw "Target folder [$TargetIconFilefolder] does not exist!"
}

Try {
    If ($SourceEXEFilePath.ToLower().Contains(".dll")) {
        Add-Type -TypeDefinition $code -ReferencedAssemblies System.Drawing
        $form = New-Object System.Windows.Forms.Form
        $Icon = [System.IconExtractor]::Extract($SourceEXEFilePath, $IconIndexNo, $true)    
    } Else {
        [void][Reflection.Assembly]::LoadWithPartialName("System.Drawing")
        [void] [System.Reflection.Assembly]::LoadWithPartialName("System.Windows.Forms")
        $image = [System.Drawing.Icon]::ExtractAssociatedIcon("$($SourceEXEFilePath)").ToBitmap()
        $bitmap = new-object System.Drawing.Bitmap $image
        $bitmap.SetResolution(72,72)
        $icon = [System.Drawing.Icon]::FromHandle($bitmap.GetHicon())
    }
} Catch {
    Throw "Error extracting ICO file"
}

Try {
    $stream = [System.IO.File]::OpenWrite("$($TargetIconFilePath)")
    $icon.save($stream)
    $stream.close()
} Catch {
    Throw "Error saving ICO file [$TargetIconFilePath]"
}
Write-Host "Icon file can be found at [$TargetIconFilePath]"
Mr. Annoyed
  • 541
  • 3
  • 18
  • I had to remove this line to have it to work: $form = New-Object System.Windows.Forms.Form And the output icons are very poor quality ones, like 256 colors (or even 16). Perhaps script has to be tweaked in some way? I am on Windows 10 – luiggig May 12 '20 at 15:55
  • Sorry but your code threw multiple errors, starting from "illegal characters in path" to "error extracting ico file". The code you tried to improve worked immediately for me. – David Trevor Jul 08 '20 at 07:04
2

You can download freeware Resource Hacker and then follow below instructions :

  1. Open any dll file you wish to find icons from.
  2. Browse folders to find specific icons.
  3. From menu bar, select 'action' and then 'save'.
  4. Select destination for .ico file.

Reference : http://techsultan.com/how-to-extract-icons-from-windows-7/

JohnOconor
  • 21
  • 1
2

There is also this resource available, the Visual Studio Image Library, which "can be used to create applications that look visually consistent with Microsoft software", presumably subject to the licensing given at the bottom. https://www.microsoft.com/en-ca/download/details.aspx?id=35825

David Carr
  • 400
  • 4
  • 7
2

This question already has answers here, but for anybody new wondering how to do this, I used 7Zip and navigated to %SystemRoot%\system32\SHELL32.dll\.rsrc\ICON, then copied all the files to a desired location.

If you'd like a pre-extracted directory, you can download the ZIP here.

Note: I extracted the files on a Windows 8.1 installation, so they may vary from the ones on other versions of Windows.

i Mr Oli i
  • 605
  • 5
  • 12
1

If you're on Linux, you can extract icons from a Windows DLL with gExtractWinIcons. It's available in Ubuntu and Debian in the gextractwinicons package.

This blog article has a screenshot and brief explanation.

Smylers
  • 1,673
  • 14
  • 18
0

The following is a similar take to Mr. Annoyed's answer, it uses ExtractIconEx function to extract icons from libraries. Main difference is, this function should be compatible with both, Windows PowerShell 5.1 and PowerShell 7+ and will also extract both icons by default, large and small, from a given index (-InconIndex). The function outputs 2 FileInfo instances pointing to the created icons given in -DestinationFolder. If no destination folder is provided, the icons will be extracted to the PowerShell current directory ($pwd).

function Invoke-ExtractIconEx {
    [CmdletBinding(PositionalBinding = $false)]
    param(
        [Parameter()]
        [ValidateNotNull()]
        [string] $SourceLibrary = 'shell32.dll',

        [Parameter(Position = 0)]
        [string] $DestinationFolder = $pwd.Path,

        [Parameter(Position = 1)]
        [int] $InconIndex
    )

    $refAssemblies = @(
        [Drawing.Icon].Assembly.Location

        if ($IsCoreCLR) {
            $pwshLocation = Split-Path -Path ([psobject].Assembly.Location) -Parent
            $pwshRefAssemblyPattern = [IO.Path]::Combine($pwshLocation, 'ref', '*.dll')
            (Get-Item -Path $pwshRefAssemblyPattern).FullName
        }
    )

    Add-Type -AssemblyName System.Drawing
    Add-Type '
    using System;
    using System.ComponentModel;
    using System.Runtime.InteropServices;
    using System.Drawing;
    using System.IO;

    namespace Win32Native
    {
        internal class SafeIconHandle : SafeHandle
        {
            [DllImport("user32.dll")]
            private static extern bool DestroyIcon(IntPtr hIcon);

            public SafeIconHandle() : base(IntPtr.Zero, true) { }

            public override bool IsInvalid
            {
                get
                {
                    return handle == IntPtr.Zero;
                }
            }

            protected override bool ReleaseHandle()
            {
                return DestroyIcon(handle);
            }
        }

        public static class ShellApi
        {
            [DllImport("shell32.dll", CharSet = CharSet.Unicode, SetLastError = true)]
            private static extern uint ExtractIconExW(
                string szFileName,
                int nIconIndex,
                out SafeIconHandle phiconLarge,
                out SafeIconHandle phiconSmall,
                uint nIcons);

            private static void ExtractIconEx(string fileName, int iconIndex, out SafeIconHandle iconLarge,
                out SafeIconHandle iconSmall)
            {
                if (ExtractIconExW(fileName, iconIndex, out iconLarge, out iconSmall, 1) == uint.MaxValue)
                {
                    throw new Win32Exception();
                }
            }

            public static FileInfo[] ExtractIcon(string sourceExe,
                string destinationFolder, int iconIndex)
            {
                SafeIconHandle largeIconHandle;
                SafeIconHandle smallIconHandle;

                ExtractIconEx(sourceExe, iconIndex, out largeIconHandle, out smallIconHandle);

                using (largeIconHandle)
                using (smallIconHandle)
                using (Icon largeIcon = Icon.FromHandle(largeIconHandle.DangerousGetHandle()))
                using (Icon smallIcon = Icon.FromHandle(smallIconHandle.DangerousGetHandle()))
                {
                    FileInfo[] outFiles = new FileInfo[2]
                    {
                        new FileInfo(Path.Combine(destinationFolder, string.Format("{0}-largeIcon-{1}.bmp", sourceExe, iconIndex))),
                        new FileInfo(Path.Combine(destinationFolder, string.Format("{0}-smallIcon-{1}.bmp", sourceExe, iconIndex)))
                    };

                    largeIcon.ToBitmap().Save(outFiles[0].FullName);
                    smallIcon.ToBitmap().Save(outFiles[1].FullName);

                    return outFiles;
                }
            }
        }
    }
    ' -ReferencedAssemblies $refAssemblies

    $DestinationFolder = $PSCmdlet.GetUnresolvedProviderPathFromPSPath($DestinationFolder)
    [Win32Native.ShellApi]::ExtractIcon($SourceLibrary, $DestinationFolder, $InconIndex)
}

Usage:

# Extracts to PWD
Invoke-ExtractIconEx -InconIndex 1

# Targeting a different library
Invoke-ExtractIconEx -SourceLibrary user32.dll -InconIndex 1

# Using a different target folder
Invoke-ExtractIconEx path\to\my\folder -InconIndex 1
Santiago Squarzon
  • 41,465
  • 5
  • 14
  • 37