Skip to content

Instantly share code, notes, and snippets.

@potatoqualitee
Created January 29, 2020 21:22
Show Gist options
  • Star 1 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save potatoqualitee/01e9659e041eed9584ca1c90f7e168c8 to your computer and use it in GitHub Desktop.
Save potatoqualitee/01e9659e041eed9584ca1c90f7e168c8 to your computer and use it in GitHub Desktop.
Export-FileIcon.ps1
Function Export-FileIcon {
<#
.SYNOPSIS
Export-FileIcon exports high-quality icons stored within .DLL and .EXE files.
.DESCRIPTION
Export-FileIcon exports high-quality icons stored within .DLL and .EXE files. The function can export to a number of formats, including
ico, bmp, png, jpg, gif, emf, exif, icon, tiff, and wmf. In addition, it can also export to a different size.
This function quickly exports *all* icons stored within the resource file.
It's ugly but it works.
.PARAMETER FilePath
Path to the .dll or .exe
.PARAMETER Destination
Directory where the exports should be stored. If no directory is specified, all icons will be exported to the TEMP directory.
.PARAMETER Size
This specifies the pixel size of the exported icons. All icons will be squares, so if you want a 16x16 export, it would be -Size 16.
Valid sizes are 8, 16, 24, 32, 48, 64, 96, and 128. The default is 32.
.PARAMETER Type
This is the type of file you would like to export to. The default is .ico
Valid types are ico, bmp, png, jpg, gif, emf, exif, icon, tiff, and wmf. The default is ico.
.NOTES
Author: Chrissy LeMaire
Requires: PowerShell 3.0
Version: 1.0
DateUpdated: 2020-Jan-29
.LINK
https://gallery.technet.microsoft.com/scriptcenter/Export-Icon-from-DLL-and-9d309047
.EXAMPLE
Export-FileIcon -FilePath C:\windows\system32\imageres.dll
Exports all icons stored witin C:\windows\system32\imageres.dll to $env:temp\icons. Creates directory if required and automatically opens output directory.
.EXAMPLE
Export-FileIcon -FilePath "C:\Program Files (x86)\VMware\Infrastructure\Virtual Infrastructure Client\Launcher\VpxClient.exe" -Size 64 -Type png -Destination C:\temp
Exports the high-quality icon within VpxClient.exe to a transparent png in C:\temp\. Resizes the exported image to 64x64. Creates directory if required
and automatically opens output directory.
.EXAMPLE
Get-ChildItem -Path "C:\Program Files (x86)\VMware\Infrastructure\Virtual Infrastructure Client\Launcher\VpxClient.exe" | Export-FileIcon -Size 64 -Type png -Destination C:\temp
Exports the high-quality icon within VpxClient.exe to a transparent png in C:\temp\. Resizes the exported image to 64x64. Creates directory if required
and automatically opens output directory.
#>
[CmdletBinding()]
Param(
[Parameter(Mandatory, ValueFromPipeline)]
[Alias("FullName")]
[System.IO.FileInfo[]]$FilePath,
[string]$Destination = "$([system.io.path]::GetTempPath())\icons",
[ValidateSet(8, 16, 24, 32, 48, 64, 96, 128)]
[int]$Size = 32,
[ValidateSet("ico", "bmp", "png", "jpg", "gif", "jpeg", "emf", "exif", "icon", "tiff", "wmf")]
[string]$Type = "ico"
)
begin {
# Thanks Thomas Levesque at http://bit.ly/1KmLgyN and darkfall http://git.io/vZxRK
$code = '
using System;
using System.Drawing;
using System.Runtime.InteropServices;
using System.IO;
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);
}
}
public class PngIconConverter
{
public static bool Convert(System.IO.Stream input_stream, System.IO.Stream output_stream, int size, bool keep_aspect_ratio = false)
{
System.Drawing.Bitmap input_bit = (System.Drawing.Bitmap)System.Drawing.Bitmap.FromStream(input_stream);
if (input_bit != null)
{
int width, height;
if (keep_aspect_ratio)
{
width = size;
height = input_bit.Height / input_bit.Width * size;
}
else
{
width = height = size;
}
System.Drawing.Bitmap new_bit = new System.Drawing.Bitmap(input_bit, new System.Drawing.Size(width, height));
if (new_bit != null)
{
System.IO.MemoryStream mem_data = new System.IO.MemoryStream();
new_bit.Save(mem_data, System.Drawing.Imaging.ImageFormat.Png);
System.IO.BinaryWriter icon_writer = new System.IO.BinaryWriter(output_stream);
if (output_stream != null && icon_writer != null)
{
icon_writer.Write((byte)0);
icon_writer.Write((byte)0);
icon_writer.Write((short)1);
icon_writer.Write((short)1);
icon_writer.Write((byte)width);
icon_writer.Write((byte)height);
icon_writer.Write((byte)0);
icon_writer.Write((byte)0);
icon_writer.Write((short)0);
icon_writer.Write((short)32);
icon_writer.Write((int)mem_data.Length);
icon_writer.Write((int)(6 + 16));
icon_writer.Write(mem_data.ToArray());
icon_writer.Flush();
return true;
}
}
return false;
}
return false;
}
public static bool Convert(string input_image, string output_icon, int size, bool keep_aspect_ratio = false)
{
System.IO.FileStream input_stream = new System.IO.FileStream(input_image, System.IO.FileMode.Open);
System.IO.FileStream output_stream = new System.IO.FileStream(output_icon, System.IO.FileMode.OpenOrCreate);
bool result = Convert(input_stream, output_stream, size, keep_aspect_ratio);
input_stream.Close();
output_stream.Close();
return result;
}
}'
Add-Type -TypeDefinition $code -ReferencedAssemblies System.Drawing, System.IO -ErrorAction SilentlyContinue
}
process {
# Ensure directory exists if one was specified. Otherwise, create icon directory in TEMP
if (-not (Test-Path -Path $Destination)) {
try { $null = New-Item -Type Directory $Destination -ErrorAction Stop }
catch { throw "Can't create $Destination $_" }
}
foreach ($file in $FilePath) {
switch ($type) {
"jpg" { $type = "jpeg" }
"icon" { $type = "ico" }
}
Write-Verbose -Message "Processing $file as $type"
# Ensure file exists
$file = Resolve-Path -Path $file
if (-not (Test-Path -Path $file)) {
Write-Warning -Message "$file does not exist"
continue
}
# Extract
$tempfile = "$Destination\tempicon.png"
$basename = [Io.Path]::GetFileNameWithoutExtension($file)
$icons = @()
try {
$index = 0
do {
$tempicon = [System.IconExtractor]::Extract($file, $($index++ | Write-Output), $true)
if ($tempicon) {
Write-Verbose -Message "Added $file to collection"
$icons += $tempicon
}
} until ($null -eq $tempicon)
}
catch {
Write-Warning -Message "Could not extract icon from $file. Do you have the proper permissions?"
continue
}
$index = 0
foreach ($icon in $icons) {
$newfile = "$Destination\$basename-$($index++ | Write-Output).$type"
Write-Verbose -Message "Getting ready to write $newfile to disk"
# Convert to bitmap, otherwise it's ugly
$bmp = $icon.ToBitmap()
try {
if ($type -eq "ico") {
$bmp.Save($tempfile, "png")
$null = [PngIconConverter]::Convert($tempfile, $newfile, $size, $true)
# Keep remove-item from complaining about weird directories
Write-Verbose -Message "Wrote $tempfile to disk"
Remove-Item -Path $tempfile -Force -ErrorAction SilentlyContinue
}
else {
try {
if ($bmp.Width -ne $size) {
# Needs to be resized
$newbmp = New-Object System.Drawing.Bitmap($size, $size)
$graph = [System.Drawing.Graphics]::FromImage($newbmp)
# Make it transparent
$graph.clear([System.Drawing.Color]::Transparent)
$graph.DrawImage($bmp, 0, 0, $size, $size)
#save to file
$newbmp.Save($newfile, $type)
$newbmp.Dispose()
}
else {
$bmp.Save($newfile, $type)
}
Write-Verbose -Message "Just wrote $newfile to disk"
}
catch {
Write-Warning -Message $PSitem
$icon.Dispose()
$bmp.Dispose()
continue
}
$bmp.Dispose()
}
$icon.Dispose()
Get-ChildItem -Path $newfile
}
catch {
Write-Warning -Message "Could not convert $file to icon"
continue
}
}
}
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment