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?
[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: