5 votes

Comment puis-je afficher directement une icône avec un ID de dll connu ?

Quelqu'un sait comment afficher directement une icône dans son format "Registre" ? Par exemple, "%SystemRoot%". \system32\shell32.dll ,112", c'est-à-dire C:\Windows\System32\shell32.dll 112, est généralement l'ID d'une icône telle qu'elle se trouve dans les données du registre pour la valeur "IconPath". Le chemin est réel, le code de l'icône "112" est juste un nombre aléatoire.

Le fait est qu'il est fastidieux de trouver l'icône correcte lorsque la dll est composée de centaines d'icônes, même en utilisant un outil comme Extracteur d'icônes qui affichera des informations sur les icônes lorsque le curseur les survolera. Tous ces outils ne semblent fonctionner que dans l'autre sens : il faut charger la dll, puis espérer localiser l'icône avec le code correspondant.

4voto

Biswapriyo Points 9951

Les icônes des types de fichiers sont des ressources (c'est-à-dire tout type d'image, de média, etc.) intégrées dans des DLL connues. Le numéro de l'icône (ou l'index du groupe d'icônes) n'est pas aléatoire. Les fichiers DLL ont une section pour stocker ces ressources. Chaque icône est stockée avec un numéro unique. Un type d'icône peut être composé de différentes tailles, dimensions et profondeur de bits. L'ID de l'icône provient du numéro du groupe d'icônes, de sorte que lorsque l'utilisateur change de niveau de zoom, il ne modifie que la taille de l'icône et non l'icône elle-même.

Cela peut être facilement compris à l'aide d'un exemple. Dans ce cas, j'utilise Pirate des ressources . Voici une capture d'écran des icônes des fichiers de raccourcis (extensions .LNK) dans Resource Hacker (les icônes peuvent varier) :

Resource_Hacker_Shell32

Et voici les paramètres du registre :

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"=""

Voyez le numéro "16769", faites-le correspondre avec la capture d'écran. Mais comment l'ouvrir dans Pirate des ressources ? Réponse : Téléchargez et exécutez ce logiciel --> Copie shell32.dll (ou tout autre fichier dll/exe) sur votre bureau/répertoire de travail --> faites glisser ce fichier dans la fenêtre de Resource Hacker --> Double-cliquez sur le "Groupe d'icônes" --> Faites défiler jusqu'à ce numéro. Vous voyez qu'il y a beaucoup d'icônes dans un groupe d'icônes par rapport à leurs dimensions 16x16, 20x20 etc. Celles-ci correspondent à différents niveaux de zoom dans l'explorateur de fichiers.

0voto

DavidPostill Points 140654

Il est fastidieux de trouver l'icône correcte lorsque la DLL est composée de centaines d'icônes.

Vous pouvez utiliser le script Powershell suivant .\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();

Exemple de sortie :

> .\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]

enter image description here

Notes :

  • Ce script a été construit en utilisant les sources listées ci-dessous.
  • Merci à Ben N en Accès aux racines pour son aide à déboguer le code.

Sources :

SistemesEz.com

SystemesEZ est une communauté de sysadmins où vous pouvez résoudre vos problèmes et vos doutes. Vous pouvez consulter les questions des autres sysadmins, poser vos propres questions ou résoudre celles des autres.

Powered by:

X