如何从 shell32.dll 中获取图标?

发布于 2024-07-05 02:20:36 字数 79 浏览 11 评论 0原文

我想获得树图标用于本土应用程序。 有谁知道如何将图像提取为 .icon 文件? 我想要 16x16 和 32x32,或者我只是进行屏幕截图。

I'd like to get the Tree icon to use for a homegrown app. Does anyone know how to extract the images out as .icon files? I'd like both the 16x16 and 32x32, or I'd just do a screen capture.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(13

柳絮泡泡 2024-07-12 02:20:36

以下内容与 Mr. 类似。 恼火的答案,它使用 < code>ExtractIconEx 函数 从库中提取图标。 主要区别在于,此 cmdlet 应与 Windows PowerShell 5.1 和 PowerShell 7+ 兼容,并且默认情况下还会从给定索引中提取大图标和小图标-InconIndex)。

该 cmdlet 输出 2 个 FileInfo 实例,指向 -DestinationFolder 中给出的创建的图标。 如果未提供目标文件夹,图标将被提取到 PowerShell 当前目录 ($pwd)。

答案是使用Add-Type编译代码,然后通过Import-Module -Assembly导入程序集。 Add-Type 还提供将程序集存储在磁盘上以供以后导入而无需预编译,即:-OutputAssembly path\to\ExtractIconEx.dll

Cmdlet 使用

# Extracts to PWD
Invoke-ExtractIconEx -InconIndex 1

# Targeting a different library
Invoke-ExtractIconEx -SourceLibrary user32.dll -InconIndex 1

# Using a different target folder
Invoke-ExtractIconEx path\to\my\folder -InconIndex 1

来源

Add-Type -AssemblyName System.Drawing

$refAssemblies = @(
    [Drawing.Icon].Assembly.Location

    if ($IsCoreCLR) {
        $pwshRefAssemblyPattern = [IO.Path]::Combine($PSHOME, 'ref', '*.dll')
        Convert-Path $pwshRefAssemblyPattern
    }
)

Add-Type @'
using System;
using System.ComponentModel;
using System.Runtime.InteropServices;
using System.Drawing;
using System.IO;
using System.Management.Automation;

namespace ExtractIconEx
{
    [Cmdlet(VerbsLifecycle.Invoke, "ExtractIconEx")]
    [OutputType(typeof(FileInfo))]
    public sealed class InvokeExtractIconEx : PSCmdlet
    {
        private string _defaultSource = "shell32.dll";

        [Parameter]
        [ValidateNotNullOrEmpty]
        public string SourceLibrary
        {
            get
            {
                return _defaultSource;
            }
            set
            {
                _defaultSource = value;
            }
        }

        [Parameter(Position = 0)]
        [ValidateNotNullOrEmpty]
        public string DestinationFolder { get; set; }

        [Parameter(Position = 1)]
        public int IconIndex { get; set; }

        protected override void EndProcessing()
        {
            if (string.IsNullOrEmpty(DestinationFolder))
            {
                DestinationFolder = SessionState.Path.CurrentFileSystemLocation.Path;
            }

            try
            {
                FileInfo[] fileInfos = ShellApi.ExtractIcon(
                    SourceLibrary,
                    GetUnresolvedProviderPathFromPSPath(DestinationFolder),
                    IconIndex);

                WriteObject(fileInfos, enumerateCollection: true);
            }
            catch (Exception e)
            {
                WriteError(new ErrorRecord(
                    e, "IconExtractError", ErrorCategory.NotSpecified, null));
            }
        }
    }

    internal sealed class SafeIconHandle : SafeHandle
    {
        [DllImport("user32.dll")]
        private static extern bool DestroyIcon(IntPtr hIcon);

        internal SafeIconHandle() : base(IntPtr.Zero, true)
        {

        }

        public override bool IsInvalid
        {
            get
            {
                return handle == IntPtr.Zero;
            }
        }
        protected override bool ReleaseHandle()
        {
            return DestroyIcon(handle);
        }
    }

    internal static class ShellApi
    {
        [DllImport(
            "shell32.dll",
            CharSet = CharSet.Unicode,
            SetLastError = true)]
        private static extern uint ExtractIconExW(
            string szFileName,
            int nIconIndex,
            out SafeIconHandle phiconLarge,
            out SafeIconHandle phiconSmall,
            uint nIcons);

        private static void ExtractIconEx(
            string fileName,
            int iconIndex,
            out SafeIconHandle iconLarge,
            out SafeIconHandle iconSmall)
        {
            if (ExtractIconExW(fileName, iconIndex, out iconLarge, out iconSmall, 1) == uint.MaxValue)
            {
                throw new Win32Exception();
            }
        }

        internal static FileInfo[] ExtractIcon(
            string source,
            string destinationFolder,
            int iconIndex)
        {
            SafeIconHandle largeIconHandle;
            SafeIconHandle smallIconHandle;
            ExtractIconEx(source, iconIndex, out largeIconHandle, out smallIconHandle);
            FileInfo[] outFiles;

            using (largeIconHandle)
            using (smallIconHandle)
            using (Icon largeIcon = Icon.FromHandle(largeIconHandle.DangerousGetHandle()))
            using (Icon smallIcon = Icon.FromHandle(smallIconHandle.DangerousGetHandle()))
            {
                outFiles = new[]
                {
                    new FileInfo(GetPath(source, destinationFolder, "largeIcon", iconIndex)),
                    new FileInfo(GetPath(source, destinationFolder, "smallIcon", iconIndex))
                };

                largeIcon.ToBitmap().Save(outFiles[0].FullName);
                smallIcon.ToBitmap().Save(outFiles[1].FullName);
            }

            return outFiles;
        }

        private static string GetPath(
            string source,
            string destinationFolder,
            string name,
            int iconIndex)
        {
            return Path.Combine(
                destinationFolder,
                string.Format("{0}-{1}-{2}.bmp", source, name, iconIndex));
        }
    }
}
'@ -PassThru -ReferencedAssemblies $refAssemblies | Import-Module -Assembly { $_.Assembly }

The following is a similar take to Mr. Annoyed's answer, it uses ExtractIconEx function to extract icons from libraries. Main difference is, this cmdlet should be compatible with both, Windows PowerShell 5.1 and PowerShell 7+ and will also extract both icons by default, large and small, from a given index (-InconIndex).

The cmdlet outputs 2 FileInfo instances pointing to the created icons given in -DestinationFolder. If no destination folder is provided, the icons will be extracted to the PowerShell current directory ($pwd).

The answer uses Add-Type to compile the code and then import the assembly via Import-Module -Assembly. Add-Type also offers to store the assembly on disk for later imports without need to precompile, i.e.: -OutputAssembly path\to\ExtractIconEx.dll.

Cmdlet Usage

# Extracts to PWD
Invoke-ExtractIconEx -InconIndex 1

# Targeting a different library
Invoke-ExtractIconEx -SourceLibrary user32.dll -InconIndex 1

# Using a different target folder
Invoke-ExtractIconEx path\to\my\folder -InconIndex 1

Source

Add-Type -AssemblyName System.Drawing

$refAssemblies = @(
    [Drawing.Icon].Assembly.Location

    if ($IsCoreCLR) {
        $pwshRefAssemblyPattern = [IO.Path]::Combine($PSHOME, 'ref', '*.dll')
        Convert-Path $pwshRefAssemblyPattern
    }
)

Add-Type @'
using System;
using System.ComponentModel;
using System.Runtime.InteropServices;
using System.Drawing;
using System.IO;
using System.Management.Automation;

namespace ExtractIconEx
{
    [Cmdlet(VerbsLifecycle.Invoke, "ExtractIconEx")]
    [OutputType(typeof(FileInfo))]
    public sealed class InvokeExtractIconEx : PSCmdlet
    {
        private string _defaultSource = "shell32.dll";

        [Parameter]
        [ValidateNotNullOrEmpty]
        public string SourceLibrary
        {
            get
            {
                return _defaultSource;
            }
            set
            {
                _defaultSource = value;
            }
        }

        [Parameter(Position = 0)]
        [ValidateNotNullOrEmpty]
        public string DestinationFolder { get; set; }

        [Parameter(Position = 1)]
        public int IconIndex { get; set; }

        protected override void EndProcessing()
        {
            if (string.IsNullOrEmpty(DestinationFolder))
            {
                DestinationFolder = SessionState.Path.CurrentFileSystemLocation.Path;
            }

            try
            {
                FileInfo[] fileInfos = ShellApi.ExtractIcon(
                    SourceLibrary,
                    GetUnresolvedProviderPathFromPSPath(DestinationFolder),
                    IconIndex);

                WriteObject(fileInfos, enumerateCollection: true);
            }
            catch (Exception e)
            {
                WriteError(new ErrorRecord(
                    e, "IconExtractError", ErrorCategory.NotSpecified, null));
            }
        }
    }

    internal sealed class SafeIconHandle : SafeHandle
    {
        [DllImport("user32.dll")]
        private static extern bool DestroyIcon(IntPtr hIcon);

        internal SafeIconHandle() : base(IntPtr.Zero, true)
        {

        }

        public override bool IsInvalid
        {
            get
            {
                return handle == IntPtr.Zero;
            }
        }
        protected override bool ReleaseHandle()
        {
            return DestroyIcon(handle);
        }
    }

    internal static class ShellApi
    {
        [DllImport(
            "shell32.dll",
            CharSet = CharSet.Unicode,
            SetLastError = true)]
        private static extern uint ExtractIconExW(
            string szFileName,
            int nIconIndex,
            out SafeIconHandle phiconLarge,
            out SafeIconHandle phiconSmall,
            uint nIcons);

        private static void ExtractIconEx(
            string fileName,
            int iconIndex,
            out SafeIconHandle iconLarge,
            out SafeIconHandle iconSmall)
        {
            if (ExtractIconExW(fileName, iconIndex, out iconLarge, out iconSmall, 1) == uint.MaxValue)
            {
                throw new Win32Exception();
            }
        }

        internal static FileInfo[] ExtractIcon(
            string source,
            string destinationFolder,
            int iconIndex)
        {
            SafeIconHandle largeIconHandle;
            SafeIconHandle smallIconHandle;
            ExtractIconEx(source, iconIndex, out largeIconHandle, out smallIconHandle);
            FileInfo[] outFiles;

            using (largeIconHandle)
            using (smallIconHandle)
            using (Icon largeIcon = Icon.FromHandle(largeIconHandle.DangerousGetHandle()))
            using (Icon smallIcon = Icon.FromHandle(smallIconHandle.DangerousGetHandle()))
            {
                outFiles = new[]
                {
                    new FileInfo(GetPath(source, destinationFolder, "largeIcon", iconIndex)),
                    new FileInfo(GetPath(source, destinationFolder, "smallIcon", iconIndex))
                };

                largeIcon.ToBitmap().Save(outFiles[0].FullName);
                smallIcon.ToBitmap().Save(outFiles[1].FullName);
            }

            return outFiles;
        }

        private static string GetPath(
            string source,
            string destinationFolder,
            string name,
            int iconIndex)
        {
            return Path.Combine(
                destinationFolder,
                string.Format("{0}-{1}-{2}.bmp", source, name, iconIndex));
        }
    }
}
'@ -PassThru -ReferencedAssemblies $refAssemblies | Import-Module -Assembly { $_.Assembly }
拿命拼未来 2024-07-12 02:20:36

如果您使用的是 Linux,则可以使用 gExtractWinIcons 从 Windows DLL 中提取图标。
它在 Ubuntu 和 Debian 中的 gextractwinicons 软件包中可用。

这篇博客文章有一个 屏幕截图和简要说明

If you're on Linux, you can extract icons from a Windows DLL with gExtractWinIcons.
It's available in Ubuntu and Debian in the gextractwinicons package.

This blog article has a screenshot and brief explanation.

撞了怀 2024-07-12 02:20:36

这个问题已经在这里有了答案,但是对于任何想知道如何执行此操作的新人,我使用 7Zip 并导航到 %SystemRoot%\system32\SHELL32.dll\.rsrc\ICON,然后复制所有文件到所需位置。

如果您想要预解压的目录,可以在此处下载 ZIP< /a>.

注意:我在 Windows 8.1 安装上提取了这些文件,因此它们可能与其他版本的 Windows 上的文件有所不同。

This question already has answers here, but for anybody new wondering how to do this, I used 7Zip and navigated to %SystemRoot%\system32\SHELL32.dll\.rsrc\ICON, then copied all the files to a desired location.

If you'd like a pre-extracted directory, you can download the ZIP here.

Note: I extracted the files on a Windows 8.1 installation, so they may vary from the ones on other versions of Windows.

失退 2024-07-12 02:20:36

还有一个可用的资源,即 Visual Studio 图像库,它“可用于创建在视觉上与 Microsoft 软件一致的应用程序”,大概需要获得底部给出的许可。
https://www.microsoft.com/en-ca/下载/details.aspx?id=35825

There is also this resource available, the Visual Studio Image Library, which "can be used to create applications that look visually consistent with Microsoft software", presumably subject to the licensing given at the bottom.
https://www.microsoft.com/en-ca/download/details.aspx?id=35825

娇柔作态 2024-07-12 02:20:36

您可以下载免费软件Resource Hacker,然后按照以下说明操作:

  1. 打开您希望从中查找图标的任何 dll 文件。
  2. 浏览文件夹以查找特定图标。
  3. 从菜单栏中选择“操作”,然后选择“保存”。
  4. 选择 .ico 文件的目标位置。

参考:http://techsultan.com/how-to-extract-图标-来自-windows-7/

You can download freeware Resource Hacker and then follow below instructions :

  1. Open any dll file you wish to find icons from.
  2. Browse folders to find specific icons.
  3. From menu bar, select 'action' and then 'save'.
  4. Select destination for .ico file.

Reference : http://techsultan.com/how-to-extract-icons-from-windows-7/

荒人说梦 2024-07-12 02:20:36

这是上述解决方案的更新版本。
我添加了一个隐藏在链接中的缺失程序集。
新手不会明白这一点。
这是示例,无需修改即可运行。

    <#
.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
)

#https://social.technet.microsoft.com/Forums/windowsserver/en-US/16444c7a-ad61-44a7-8c6f-b8d619381a27/using-icons-in-powershell-scripts?forum=winserverpowershell
$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
        $form = New-Object System.Windows.Forms.Form
        $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]"

Here is an updated version of a solution above.
I added a missing assembly that was buried in a link.
Novices will not understand that.
This is sample will run without modifications.

    <#
.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
)

#https://social.technet.microsoft.com/Forums/windowsserver/en-US/16444c7a-ad61-44a7-8c6f-b8d619381a27/using-icons-in-powershell-scripts?forum=winserverpowershell
$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
        $form = New-Object System.Windows.Forms.Form
        $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]"
聊慰 2024-07-12 02:20:36

Resources Extract 是另一个工具,可以递归地从大量图标中查找图标DLL,在我看来非常方便。

Resources Extract is another tool that will recursively find icons from a lot of DLLs, very handy IMO.

魂ガ小子 2024-07-12 02:20:36

只需使用 IrfanView 打开 DLL 并将结果保存为 .gif 或 .jpg。

我知道这个问题很旧,但这是“从 dll 中提取图标”的第二次谷歌点击,我想避免在我的工作站上安装任何东西,我记得我使用 IrfanView。

Just open the DLL with IrfanView and save the result as a .gif or .jpg.

I know this question is old, but it's the second google hit from "extract icon from dll", I wanted to avoid installing anything on my workstation and I remembered I use IrfanView.

贵在坚持 2024-07-12 02:20:36

我需要从 shell32.dll 中提取图标 #238,并且不想下载 Visual Studio 或 Resourcehacker,因此我从 Technet 找到了几个 PowerShell 脚本(感谢 John Grenfell 和 #https://social.technet.microsoft。 com/Forums/windowsserver/en-US/16444c7a-ad61-44a7-8c6f-b8d619381a27/using-icons-in-powershell-scripts?forum=winserverpowershell)做了类似的事情并创建了一个新脚本(如下)以满足我的需要。

我输入的参数是(源 DLL 路径、目标图标文件名和 DLL 文件内的图标索引):

C:\Windows\System32\shell32.dll

C:\Temp\Restart.ico

238

我发现了图标索引通过临时创建一个新的快捷方式,我需要的是#238,通过反复试验(右键单击桌面并选择新建 --> 快捷方式并输入 calc 并按 Enter 两次)。 然后右键单击新快捷方式并选择“属性”,然后单击“快捷方式”选项卡中的“更改图标”按钮。 粘贴到路径 C:\Windows\System32\shell32.dll 中,然后单击“确定”。 找到您想要使用的图标并计算出其索引。 注意:索引#2 位于#1 下方,而不是在其右侧。 图标索引 #5 位于我的 Windows 7 x64 计算机上第二列的顶部。

如果有人有更好的方法,其工作原理类似但获得更高质量的图标,那么我有兴趣听到它。 谢谢,肖恩。

#Windows PowerShell Code###########################################################################
# http://gallery.technet.microsoft.com/scriptcenter/Icon-Exporter-e372fe70
#
# AUTHOR: John Grenfell
#
###########################################################################

<#
.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
   No error checking I'm afraid so make sure your source and destination locations exist!
.EXAMPLE
    .\Icon_Exporter.ps1
.Notes
        Version HISTORY:
        1.1 2012.03.8
#>
Param ( [parameter(Mandatory = $true)][string] $SourceEXEFilePath,
        [parameter(Mandatory = $true)][string] $TargetIconFilePath
)
CLS
#"shell32.dll" 238
If ($SourceEXEFilePath.ToLower().Contains(".dll")) {
    $IconIndexNo = Read-Host "Enter the icon index: "
    $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())
}
$stream = [System.IO.File]::OpenWrite("$($TargetIconFilePath)")
$icon.save($stream)
$stream.close()
Write-Host "Icon file can be found at $TargetIconFilePath"

I needed to extract icon #238 from shell32.dll and didn't want to download Visual Studio or Resourcehacker, so I found a couple of PowerShell scripts from Technet (thanks John Grenfell and to #https://social.technet.microsoft.com/Forums/windowsserver/en-US/16444c7a-ad61-44a7-8c6f-b8d619381a27/using-icons-in-powershell-scripts?forum=winserverpowershell) that did something similar and created a new script (below) to suit my needs.

The parameters I entered were (the source DLL path, target icon file name and the icon index within the DLL file):

C:\Windows\System32\shell32.dll

C:\Temp\Restart.ico

238

I discovered the icon index that I needed was #238 by trial and error by temporarily creating a new shortcut (right-click on your desktop and select New --> Shortcut and type in calc and press Enter twice). Then right-click the new shortcut and select Properties then click 'Change Icon' button in the Shortcut tab. Paste in path C:\Windows\System32\shell32.dll and click OK. Find the icon you wish to use and work out its index. NB: Index #2 is beneath #1 and not to its right. Icon index #5 was at the top of column two on my Windows 7 x64 machine.

If anyone has a better method that works similarly but obtains higher quality icons then I'd be interested to hear about it. Thanks, Shaun.

#Windows PowerShell Code###########################################################################
# http://gallery.technet.microsoft.com/scriptcenter/Icon-Exporter-e372fe70
#
# AUTHOR: John Grenfell
#
###########################################################################

<#
.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
   No error checking I'm afraid so make sure your source and destination locations exist!
.EXAMPLE
    .\Icon_Exporter.ps1
.Notes
        Version HISTORY:
        1.1 2012.03.8
#>
Param ( [parameter(Mandatory = $true)][string] $SourceEXEFilePath,
        [parameter(Mandatory = $true)][string] $TargetIconFilePath
)
CLS
#"shell32.dll" 238
If ($SourceEXEFilePath.ToLower().Contains(".dll")) {
    $IconIndexNo = Read-Host "Enter the icon index: "
    $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())
}
$stream = [System.IO.File]::OpenWrite("$($TargetIconFilePath)")
$icon.save($stream)
$stream.close()
Write-Host "Icon file can be found at $TargetIconFilePath"
じ违心 2024-07-12 02:20:36

另一种选择是使用 ResourceHacker 等工具。 它处理的不仅仅是图标。 干杯!

Another option is to use a tool such as ResourceHacker. It handles way more than just icons as well. Cheers!

爱格式化 2024-07-12 02:20:36

如果有人正在寻找简单的方法,只需使用 7zip 解压缩 shell32.dll 并查找文件夹 .src/ICON/

If anyone is seeking an easy way, just use 7zip to unzip the shell32.dll and look for the folder .src/ICON/

回梦 2024-07-12 02:20:36

在 Visual Studio 中,选择“文件打开...”,然后选择“文件...”。 然后选择Shell32.dll。 应打开文件夹树,您将在“图标”文件夹中找到图标。

要保存图标,您可以右键单击文件夹树中的图标并选择“导出”。

In Visual Studio, choose "File Open..." then "File...". Then pick the Shell32.dll. A folder tree should be opened, and you will find the icons in the "Icon" folder.

To save an Icon, you can right-click on the icon in the folder tree and choose "Export".

〗斷ホ乔殘χμё〖 2024-07-12 02:20:36

不确定我是否 100% 正确,但根据我的测试,上述使用 7Zip 或 VS 的选项不适用于 Windows 10 / 11 版本的 imageres.dll 或 shell32.dll。
这是我看到的内容:

[shell32.dll]
.rsrc\MANIFEST\124
.rsrc\MUI\1
.rsrc\TYPELIB\1
.rsrc\version.txt
.data
.didat
.pdata
.rdata
.reloc
.text
CERTIFICATE

更新:我想我找到了原因。 链接到我找到的一篇文章。 (抱歉不在域内)。
您可以在以下位置的文件中找到资源:

"C:\Windows\SystemResources\shell32.dll.mun"
"C:\Windows\SystemResources\imageres.dll.mun"

Windows 10 1903 中的 imageres.dll 中不再有图标 - 4kb 文件 (superuser.com)

Not sure if I am 100% correct, but from my testing, the above options for using 7Zip or VS don't work on Windows 10 / 11 versions of imageres.dll or shell32.dll.
This is the content I see:

[shell32.dll]
.rsrc\MANIFEST\124
.rsrc\MUI\1
.rsrc\TYPELIB\1
.rsrc\version.txt
.data
.didat
.pdata
.rdata
.reloc
.text
CERTIFICATE

Update: And I think I found why. Link to an article I found. (Sorry for being off-domain).
You can find the resources in files in these locations:

"C:\Windows\SystemResources\shell32.dll.mun"
"C:\Windows\SystemResources\imageres.dll.mun"

Icons no longer in imageres.dll in Windows 10 1903 - 4kb file (superuser.com)

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文