
アイコンを「レジストリ」形式で直接表示する方法を知っている人はいますか? たとえば、「%SystemRoot%\system32\shell32.dll,112」、つまり C:\Windows\System32\shell32.dll,112 は、通常、レジストリ データの「IconPath」値にあるアイコンの ID です。パスは実際のもので、「112」アイコン コードはランダムな数字です。
ポイントは、dllが何百ものアイコンで構成されている場合、次のようなツールを使用したとしても、正しいアイコンを見つけるのが面倒だということです。アイコン抽出ツール、カーソルをアイコンの上に置くとアイコン情報が表示されます。これらのツールはすべて逆方向にのみ機能するようです。つまり、まず dll をロードし、次に、対応するコードでアイコンを見つけようとします。
答え1
ファイル タイプのアイコンは、既知の DLL に埋め込まれたリソース (つまり、あらゆる種類の画像、メディアなど) です。アイコン番号 (またはアイコン グループ インデックス) はランダムではありません。DLL ファイルには、これらのリソースを格納するセクションがあります。各アイコンは、一意の番号で格納されます。1 つのアイコン タイプは、さまざまなアイコン サイズ、寸法、およびビット深度で構成できます。そのアイコン ID はアイコン グループ番号から取得されるため、ユーザーがズーム レベルを変更すると、アイコン自体ではなくアイコン サイズのみが変更されます。
これは例で簡単に理解できます。この例では、リソースハッカー以下は、Resource Hacker のショートカット ファイル (.LNK 拡張子) のアイコンのスクリーンショットです (アイコンは異なる場合があります)。
レジストリ設定は次のとおりです。
Windows Registry Editor Version 5.00
[HKEY_LOCAL_MACHINE\SOFTWARE\Classes\.lnk\ShellNew]
"Handler"="{ceefea1b-3e29-4ef1-b34c-fec79c4f70af}"
"IconPath"="%SystemRoot%\system32\shell32.dll,-16769"
"ItemName"="@shell32.dll,-30397"
"MenuText"="@shell32.dll,-30318"
"NullFile"=""
「16769」という数字を見て、スクリーンショットと照らし合わせてください。しかし、どうやって開くのでしょうか?リソースハッカー? 回答: そのソフトウェアをダウンロードして実行します -->shell32.dll
デスクトップ/作業フォルダにコピーします (または任意の dll/exe ファイル) --> そのファイルを Resource Hacker ウィンドウにドラッグします --> 「アイコン グループ」をダブルクリックします --> その番号までスクロールします。1 つのアイコン グループに、16x16、20x20 などの寸法のアイコンが多数あることがわかります。これらは、ファイル エクスプローラーの異なるズーム レベル用です。
代替ソフトウェア:代替ソフトウェアを探す代替案: リソースハッカー以下にいくつか例を挙げます。
参考文献:
答え2
dllが何百ものアイコンで構成されている場合、正しいアイコンを見つけるのは面倒です
次の Powershell スクリプトを使用できます.\DisplayIcon.ps1
。
<#
.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
)
$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
$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]"
# Loosely based on http://www.vistax64.com/powershell/202216-display-image-powershell.html
[void][reflection.assembly]::LoadWithPartialName("System.Windows.Forms")
$img = [System.Drawing.Image]::Fromfile($TargetIconFilePath);
# This tip from http://stackoverflow.com/questions/3358372/windows-forms-look-different-in-powershell-and-powershell-ise-why/3359274#3359274
[System.Windows.Forms.Application]::EnableVisualStyles();
$form = new-object Windows.Forms.Form
$form.Text = "Image Viewer"
$form.Width = $img.Size.Width;
$form.Height = $img.Size.Height;
$pictureBox = new-object Windows.Forms.PictureBox
$pictureBox.Width = $img.Size.Width;
$pictureBox.Height = $img.Size.Height;
$pictureBox.Image = $img;
$form.controls.add($pictureBox)
$form.Add_Shown( { $form.Activate() } )
$form.ShowDialog()
#$form.Show();
出力例:
> .\DisplayIcon.ps1 -SourceEXEFilePath 'C:\Windows\system32\shell32.dll' -TargetIconFilePath 'f:\test\Myicon.ico' -IconIndexNo 41
Icon file can be found at [f:\test\Myicon.ico]
ノート:
出典: