Skip to content

Instantly share code, notes, and snippets.

@iyre
Created January 25, 2025 07:28
Show Gist options
  • Save iyre/090db4c29de79e4462dbd6eb7c700146 to your computer and use it in GitHub Desktop.
Save iyre/090db4c29de79e4462dbd6eb7c700146 to your computer and use it in GitHub Desktop.
Export an HTML manifest of icons contained in a DLL
# based on https://renenyffenegger.ch/notes/Windows/PowerShell/examples/WinAPI/ExtractIconEx
function Export-IconImageManifest {
param (
[String]$DllPath = "$env:SYSTEMROOT\System32\imageres.dll"
)
if (! (test-path $dllPath)) {
write-output "$dllPath is not a file"
return
}
# https://stackoverflow.com/questions/6872957/how-can-i-use-the-images-within-shell32-dll-in-my-c-sharp-project
# 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
);
}
'@
# User32_DestroyIcon
Add-Type -TypeDefinition @'
using System;
using System.Runtime.InteropServices;
public class User32_DestroyIcon {
[DllImport(
"User32.dll",
EntryPoint = "DestroyIcon"
)]
public static extern int DestroyIcon(IntPtr hIcon);
}
'@
$filenameWithoutSuffix = [IO.Path]::GetFileNameWithoutExtension($dllPath)
New-Item -Force -ItemType Directory -Name "$filenameWithoutSuffix/images" -EA 0 1>$null
"<html><head>
<title>Icons in $filenameWithoutSuffix.dll</title></head><body>
<h1>Icons in $filenameWithoutSuffix.dll</h1>
<table><tr>" | out-file "$filenameWithoutSuffix/$filenameWithoutSuffix.html"
[Reflection.Assembly]::LoadWithPartialName('System.Drawing') 1>$null
[Reflection.Assembly]::LoadWithPartialName('System.Drawing.Imaging') 1>$null
[System.IntPtr]$phiconSmall = 0
[System.IntPtr]$phiconLarge = 0
$nofImages = [Shell32_Extract]::ExtractIconEx($dllPath, -1, [ref]$phiconLarge, [ref]$phiconSmall, 0)
Write-Information -Infa 2 "Total icons: $nofImages"
foreach ($iconIndex in 0..($nofImages-1)) {
$nofIconsExtracted = [Shell32_Extract]::ExtractIconEx($dllPath, $iconIndex, [ref]$phiconLarge, [ref]$phiconSmall, 1)
$iconLarge = [System.Drawing.Icon]::FromHandle($phiconLarge)
$bmpLarge = $iconLarge.ToBitmap()
$iconIndex_0 = '{0,3:000}' -f $iconIndex
$imgName = "images/$filenameWithoutSuffix-$iconIndex_0.png"
$bmpLarge.Save("$(Get-Location)/$filenameWithoutSuffix/$imgName")
if ($iconIndex -and (! ($iconIndex % 10))) {
"</tr><tr>" | Out-File "$filenameWithoutSuffix/$filenameWithoutSuffix.html" -Append
}
"<td>$iconIndex_0</td><td><img src='$imgName'/></td>" | Out-File "$filenameWithoutSuffix/$filenameWithoutSuffix.html" -Append
[User32_DestroyIcon]::DestroyIcon($phiconSmall) 1>$null
[User32_DestroyIcon]::DestroyIcon($phiconLarge) 1>$null
}
"</table></body></html>" | Out-File "$filenameWithoutSuffix/$filenameWithoutSuffix.html" -Append
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment