如何从 Windows 命令提示符下的 .exe 文件中获取所有 VersionInfo 字符串

Jos*_*hua 1 windows powershell version

在 Windows 10 之前,可以VersionInfo通过右键单击文件并执行属性来获取所有字符串。那已经行不通了。这就像有人只决定展示几十年来获得标准含义的那些。但是 GUI 并不重要,只是注意到它不起作用,因此对属性页的 COM 调用将无济于事。无论如何,我们想知道如何从命令行。

尝试:

PS> get-childitem .\execautablename | FormatList VersionInfo
PS> (get-item .\execautablename | format-list -force)
PS> get-childitem .\execautablename | ? {$_.VersionInfo.Xyz}
cmd> wmic datafile where Name="C:\\Full\\Path\\to\\executablename.exe" list full
Run Code Online (Sandbox Code Playgroud)

第三个命令只能获取一些版本字符串,但不能获取我知道的其他版本字符串。

就像现在所有的方法都知道一个“标准”列表(有两个或三个关于标准列表的想法),并且它们都不知道如何枚举所有 VersionInfo 字符串。我有一个带有字符串“ProductHash”的二进制文件,它是用于编译它的相应源代码的 git commit hash。

我不断收到建议涉及的答案{$_.VersionInfo}。该路径永远不会起作用,因为VersionInfo相信要检索的 versioninfo 属性的固定列表。该rc编译器和VERSIONINFOPE结构不同的信。wmic 有一个不同的固定列表,它检索。

应用 VersInfoEx 后的 versioninfo

这是物业。它仅在应用由postanote链接的Fish 的VersInfoEx shell 扩展后才出现

源代码片段(windows 资源):

#include <windows.h>

1 VERSIONINFO
FILEVERSION 10, 0, 0, 0
PRODUCTVERSION 10, 0, 0, 0
FILEFLAGSMASK 0
FILEFLAGS 0
FILEOS VOS_NT_WINDOWS32
FILETYPE VFT_APP
BEGIN
BLOCK "StringFileInfo"
BEGIN
BLOCK "040904E4"
BEGIN
VALUE "FileDescription", "Hello RC"
VALUE "FileVersion", "10.0.0.0"
VALUE "LegalCopyright", "Copyright (C) Cedaron Medical, Inc. 2018"
VALUE "InternalName", "hellorc"
VALUE "ProductHash", "Hello_World_abcdefgh" /* this is the value I'm after */
VALUE "ProductName", "Hello RC"
VALUE "ProductVersion", "10.0.0.0"
END
END
BLOCK "VarFileInfo"
BEGIN
VALUE "Translation", 0x409, 1252
END
END
Run Code Online (Sandbox Code Playgroud)

我设法得到了一个真正可怕且令人不满意的答案,它对 VERSIONINFO 一无所知,并且读取了兆字节的文件,并且依赖于安装的方式太多。

cmd> c:\cygwin64\bin\tr -d \0 < filename.exe | c:\cygwin64\bin\strings | c:\cygwin64\bin\grep ^^ProductHash. | c:\cygwin64\bin\sed s/ProductHash//
Run Code Online (Sandbox Code Playgroud)

如果正在搜索的 VERSIONINFO 字符串名称不在二进制文件中的其他位置,则此方法有效。我希望一个糟糕的答案足以更好地解释这个问题。

尝试按照 Pimp Juice IT 的建议使用 powershell 做同样的事情并没有完全奏效:

PS> Get-Content ".\executablename.exe" | % { if($_ -match "ProductHash") { write-host $_}}
PS>
Run Code Online (Sandbox Code Playgroud)

它非常接近一个可行的想法,我能够确定为什么它没有产生任何输出。我将 cygwintr重新插入管道,命令运行时间太长,我以为它挂了,但我最终得到了一些输出。

PS> Get-Content ".\executablename.exe" | c:\cygwin64\bin\tr.exe -d \0 | % { if($_ -match "ProductHash") { write-host $_}}
InternalNameexecutablenameh$ProductNameMyProductPProductVersion10.0.591.927r)ProductHash50acd7cedb99dddab69c5de9b2f021ef72d64ca0DVarFileInfo$Translation       ????<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
PS>
Run Code Online (Sandbox Code Playgroud)

我制作了一个最小的二进制hello.zip(1313 字节,解压到 4096 字节)。versioninfo 键“ProductHash”的值为“Hello_World_abcdefgh”。

不要被欺骗。ProductHash 不是二进制的哈希。它是源代码存储库中的哈希键,用于查找编译二进制文件的源代码。这个想法是,如果有人最终得到了一些奇怪的版本,我们可以追踪它并确切地确定他们拥有什么代码。与其让客户给我们发送一个大文件,我们宁愿向他们发送一个小命令来从中获取价值。

Vom*_*yle 6

最终工作解决方案逻辑

该脚本考虑了 versioninfo 结构的实际布局,并使用一个额外的参数(靠近末尾的 1 或 2)来处理输入字符串的奇偶校验。

$versioninfostate = 0
(Get-Content "hello.exe" -Encoding Unicode) -split {$_ -lt " "} | % { if ($versioninfostate -eq 1) { write-host $_ } if ($versioninfostate -gt 0) { $versioninfostate = $versioninfostate - 1} if ($_ -match "ProductHash$") { $versioninfostate = 2 }}
Run Code Online (Sandbox Code Playgroud)

最终解决方案路径的开发

  1. “最后一个命令只能获取一些版本字符串,但不能获取我知道的其他版本字符串”
    • 使用Select *获得额外的属性不只是显示Format-List

  2. “从 .exe 文件中获取所有 VersionInfo 字符串”
    • 将 exe 传递% {$_.VersionInfo}给使用,Foreach-Object而不是将Where-Object$_.VersionInfo 归零在一个列表/记录集中的属性

  3. “无法解析任意属性名称”
    • 实际上使用上面列出的 #1 & #2 你可以(见下文) 在此处输入图片说明

  4. “根据您的最新更新,您在评论中安装了某人向您推荐的第三方实用程序;该软件似乎来自 2010 年,专为 Windows 7 设计。无论如何,它似乎添加了一个名为ProductHashper您的最新更新屏幕截图。”
    • 使用Get-FileHash 然后以这种方式显式获取 exe 的哈希值


下面是一些 PowerShell 逻辑。. .

  • 使用%而不是?通过Foreach-Object放置可执行文件而不是Where-Object
  • 使用Select *而不是Format-List确保变量对象是System.Object BaseType而不是System.Arrayas Format-Listcreated
  • 使用您从VersionInfo列表中指定的显式属性值设置变量
  • 使用Get-FileHash获取 exe 哈希值

电源外壳

$t = get-childitem ".\executablename" | % {$_.VersionInfo} | Select *
$Hash = (Get-FileHash $Exe).Hash
$t.<Property>, $Hash
Run Code Online (Sandbox Code Playgroud)

输出示例

Coolest - www.CoolTool.com
30E14E358DD76EC712CCC6B5FD1E79DDEAA653E682E968DA0229BE13BED2B991
Run Code Online (Sandbox Code Playgroud)

版本信息列表对象

PS C:\WINDOWS\system32> get-childitem ".\executablename" | % {$_.VersionInfo} | Select *


FileVersionRaw     : 1.80.0.0
ProductVersionRaw  : 1.80.0.0
Comments           : 
CompanyName        : Coolest - www.CoolTool.com
FileBuildPart      : 0
FileDescription    : Program - Cool memory analyzer
FileMajorPart      : 1
FileMinorPart      : 80
FileName           : C:\Users\User\Desktop\Coolio.exe
FilePrivatePart    : 0
FileVersion        : 1.80
InternalName       : TooCool
IsDebug            : False
IsPatched          : False
IsPrivateBuild     : False
IsPreRelease       : False
IsSpecialBuild     : False
Language           : English (United States)
LegalCopyright     : Copyright © 1985-2099 Michael Jordan
LegalTrademarks    : 
OriginalFilename   : Coolio
PrivateBuild       : 
ProductBuildPart   : 0
ProductMajorPart   : 1
ProductMinorPart   : 80
ProductName        : TooCool
ProductPrivatePart : 0
ProductVersion     : 1.80
SpecialBuild       : 
Run Code Online (Sandbox Code Playgroud)

搜索二进制字符串内容

注意: 就像cygwincli stringgrep和其他命令搜索文件的二进制文件以匹配 string 一样"ProductHash",您也可以从类似的 PowerShell 命令中读取它。

$Match = (Get-Content ".\executablename") -replace "`0", "" | % {if($_ -match "(ProductHash)") {$Matches[0]}}
$Line  = (Get-Content ".\executablename") -replace "`0", "" | % {if($_ -match "(ProductHash)") {$_}} | % {if($_ -match "(ProductHash).*$") {$Matches[0]}} 
$Line  = $Line -replace "[\W]", "`r`n" | % {if($_ -match "(ProductHash).*\s") {$Matches[0]}}
$MisMatch = $Line.Replace($Match, "")
Write-Output "$Match`: $MisMatch"
Run Code Online (Sandbox Code Playgroud)

示例输出

ProductHash: Hello_World_abcdefgh2
Run Code Online (Sandbox Code Playgroud)

更多资源