Como posso exibir diretamente um ícone com um ID de DLL conhecido?

1

Alguém sabe como exibir diretamente um ícone no formato "Registro"? Por exemplo. "% SystemRoot% \ system32 \ shell32.dll, 112", ou seja, C: \ Windows \ System32 \ shell32.dll, 112, é normalmente o ID de um ícone como encontrado nos Dados do Registro para o valor "IconPath". O caminho é real, o código do ícone "112" é apenas um número aleatório.

O ponto é que é complicado encontrar o ícone correto quando a dll consiste em centenas de ícones, mesmo quando se usa uma ferramenta como o Icon Extractor , que exibe informações de ícone quando o cursor passa sobre o ícone ícones. Todas essas ferramentas só parecem funcionar ao contrário: é preciso carregar a dll, a próxima esperança é localizar o ícone com o código correspondente.

    
por WinMike 22.07.2018 / 15:22

2 respostas

1

Os ícones para tipos de arquivo são recursos (ou seja, qualquer tipo de imagem, mídia etc.) incorporados em DLLs conhecidas. Esse número de ícone (ou índice de grupo de ícones) não é aleatório. Arquivos DLL têm uma seção para armazenar esses recursos. Cada ícone é armazenado com números exclusivos. Um tipo de ícone pode consistir em vários tamanhos de ícones, dimensões e profundidade de bits. Esse ID de ícone vem do número do grupo de ícones para que quando o usuário alterar o nível de zoom, ele altere apenas o tamanho do ícone e não o próprio ícone.

Isso pode ser facilmente entendido com um exemplo. Para este caso, eu uso Resource Hacker . Aqui está a captura de tela dos ícones dos arquivos de atalho (extensões .LNK) no Resource Hacker (os ícones podem variar):

Eaquiestãoasconfiguraçõesdoregistro:

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

Veja o número "16769", combine-o com a captura de tela. Mas como abri-lo em Resource Hacker ? Resposta: Faça o download e execute esse software - > Copie shell32.dll (ou qualquer arquivo dll / exe) em sua área de trabalho / pasta de trabalho - > arraste esse arquivo na janela Resource Hacker - > Dê um duplo clique no "Grupo de Ícones" - > Vá até esse número. Veja que há muitos ícones em um grupo de ícones com relação às suas dimensões 16x16, 20x20 etc. Esses são para diferentes níveis de zoom no File Explorer.

por 22.07.2018 / 17:29
0

É complicado encontrar o ícone correto quando a dll consiste em centenas de ícones

Você pode usar o seguinte script 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();

Exemplo de saída:

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

Notas:

  • Estescriptfoicriadousandoasfonteslistadasabaixo.
  • Graçasa Ben N em Acesso Root para sua ajuda na depuração do código.

Fontes:

por 22.07.2018 / 17:43