Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

how to get a specific icon from an icon library? [duplicate]

I have this snippet of code to extract an icon from shell32.dll.

$iconPath = "$env:SystemRoot\system32\shell32.dll"  # Path to the shell32.dll library
$iconIndex = 4  # Index of the folder icon in the library
$icon = [System.Drawing.Icon]::ExtractAssociatedIcon($iconPath)
$icon = [System.Drawing.Icon]::new($icon, 16, 16)

This partially works in that it fetches an icon from shell32.dll, but as you can see, $icon does not reference $iconIndex anywhere, and so I do not get icon '4'. I have tried putting $iconIndex as a 2nd argument to ExtractAssociatedIcon but that generates an error.

How can I get $icon to reference $iconIndex = 4 from the shell32.dll library?

like image 344
YorSubs Avatar asked Sep 16 '25 08:09

YorSubs


1 Answers

[System.Drawing.Icon]::ExtractAssociatedIcon() is not solution to extract a given number of icon in shell32.dll, but only associated one.

But shell32.dll provides istself a method ([Shell32_Extract]::ExtractIconEx()) to do so, this solution is adapted one of Shell32_Extract:


add-type -typeDefinition '

using System;
using System.Runtime.InteropServices;

public class Shell32_Extract {

  [DllImport(
     "Shell32.dll",
      EntryPoint        = "ExtractIconExW",
      CharSet           =  CharSet.Unicode,
      ExactSpelling     =  true,
      CallingConvention =  CallingConvention.StdCall)
  ]

   public static extern int ExtractIconEx(
      string lpszFile          , // Name of the .exe or .dll that contains the icon
      int    iconIndex         , // zero based index of first icon to extract. If iconIndex == 0 and and phiconSmall == null and phiconSmall = null, the number of icons is returnd
      out    IntPtr phiconLarge,
      out    IntPtr phiconSmall,
      int    nIcons
  );

}
';
#
$iconPath = "$env:SystemRoot\system32\shell32.dll"  # Path to the shell32.dll library
$iconIndex = 4  # Index of the folder icon in the library
#$icon = [System.Drawing.Icon]::ExtractAssociatedIcon($iconPath)
#$icon = [System.Drawing.Icon]::new($icon, 16, 16)
#$path = (Get-Location).Path + "\a1.ico"
#$icon.ToBitMap().save($path)

[System.IntPtr] $phiconSmall = 0
[System.IntPtr] $phiconLarge = 0

$nofImages = [Shell32_Extract]::ExtractIconEx($iconPath, -1, [ref] $phiconLarge, [ref] $phiconSmall, 0)

$nofIconsExtracted = [Shell32_Extract]::ExtractIconEx($iconPath, $iconIndex, [ref] $phiconLarge, [ref] $phiconSmall, 1)

if ($nofIconsExtracted -ne 2) {
    Write-Error "iconsExtracted = $nofIconsExtracted"
}

$iconSmall = [System.Drawing.Icon]::FromHandle($phiconSmall);
$iconLarge = [System.Drawing.Icon]::FromHandle($phiconLarge);

$bmpSmall = $iconSmall.ToBitmap()
$bmpLarge = $iconLarge.ToBitmap()

#
#  System.Drawing.Image.Save(), without specifying an encoder, stores
#  the bitmap in png format.
#
$bmpLarge.Save("$(get-location)\small-$iconIndex.png");
$bmpLarge.Save("$(get-location)\large-$iconIndex.png");

#
#  Use System.Drawing.Imaging.ImageFormat to specify a
#  different format:
#

$bmpSmall.Save("$(get-location)\small-$iconIndex.bmp", [System.Drawing.Imaging.ImageFormat]::Bmp );
$bmpLarge.Save("$(get-location)\large-$iconIndex.bmp", [System.Drawing.Imaging.ImageFormat]::Bmp );
   
$bmpSmall.Save("$(get-location)\small-$iconIndex.jpg", [System.Drawing.Imaging.ImageFormat]::Jpeg);
$bmpLarge.Save("$(get-location)\large-$iconIndex.jpg", [System.Drawing.Imaging.ImageFormat]::Jpeg);

This generates images like this:

enter image description here

like image 180
jacouh Avatar answered Sep 18 '25 08:09

jacouh