До 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

Третья команда может получить только некоторые строки версии, но не те, которые, как я знаю, есть.

Это похоже на то, как теперь все способы знают "стандартный" список (есть два или три представления о том, что такое стандартный список), и никто из них не знает, как перечислить все строки VersionInfo. У меня есть двоичный файл со строкой "ProductHash", которая является хешем git commit соответствующего исходного кода, используемого для его компиляции.

Я продолжаю получать ответы, предложенные с участием {$_.VersionInfo} . Этот путь никогда не сработает, потому что VersionInfo верит в фиксированный список свойств versioninfo для извлечения. Компилятор rc и структура PE VERSIONINFO верят по-разному. И wmic имеет другой фиксированный список, который он получает.

versioninfo после применения VersInfoEx

Это собственность. Он появился только после применения расширения оболочки VersInfoEx от Fish, связанного с помощью postanote.

Фрагмент исходного кода (ресурс 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

Мне удалось получить по-настоящему ужасный и неудовлетворительный ответ, который ничего не знает о 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//

Это работает при условии, что искомое имя строки VERSIONINFO не находится где-то еще в двоичном файле. Я надеюсь, что плохого ответа достаточно, чтобы лучше объяснить вопрос.

Попытка сделать то же самое с PowerShell, как это было предложено Pimp Juice IT, не сработала:

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

Это было достаточно близко к рабочей идее, и я смог определить, почему она не дала результатов. Я вставил tr cygwin обратно в конвейер, и выполнение команды заняло так много времени, что я подумал, что оно зависло, но в итоге я получил какой-то вывод.

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>

Я сделал минимальный двоичный файл hello.zip (1313 байт, распаковывает до 4096 байт). Ключ информации о версии "ProductHash" имеет значение "Hello_World_abcdefgh".

Не обманывайтесь. ProductHash не является хешем двоичного файла. Это хэш-ключ в хранилище исходного кода, чтобы найти исходный код, из которого был скомпилирован бинарный файл. Идея в том, что если кто-то получит какую-то странную версию, мы можем отследить ее и точно определить, какой код у них есть. Вместо того чтобы заказчик отправлял нам большой файл, мы бы отправили ему небольшую команду, чтобы извлечь из него значение.

2 ответа2

3

Конечная рабочая логика решения

Этот сценарий учитывает фактическое расположение структуры 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 }}

Разработка пути окончательного решения

  1. «Последняя команда может получить только некоторые строки версии, но не те, которые я знаю, там есть»
    • Используйте Select * чтобы получить дополнительные свойства, которые не отображаются только с Format-List

  2. «Получить все строки VersionInfo из файла .exe»
    • Передайте исполняемый файл % {$_.VersionInfo} для использования Foreach-Object вместо Where-Object с $_.VersionInfo только на свои свойства в одном наборе списков / записей

  3. "Не удается разрешить произвольные имена свойств"
    • На самом деле, используя # 1 & # 2, как указано выше, вы можете (см. Ниже)

  4. «Согласно вашему последнему обновлению, вы установили стороннюю утилиту, рекомендованную кем-то в комментарии; это программное обеспечение относится к 2010 году и разработано специально для Windows 7. В любом случае, кажется, что добавлено дополнительное свойство с именем ProductHash в соответствии с вашим последним снимком экрана обновления. "
    • Используйте Get-FileHash а затем явно получите значение хеша exe таким образом


Ниже приведена некоторая логика PowerShell. , ,

  • Использует % вместо ? поместить исполняемый файл через Foreach-Object, а не Where-Object
  • Использует Select * вместо Format-List чтобы гарантировать, что переменный объект принадлежит System.Object BaseType, а не System.Array при Format-List
  • Задает переменную с явным значением свойства, указанным в списке VersionInfo
  • Использует Get-FileHash, чтобы получить значение хеша exe

PowerShell

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

Пример вывода

Coolest - www.CoolTool.com
30E14E358DD76EC712CCC6B5FD1E79DDEAA653E682E968DA0229BE13BED2B991

VersionInfo List Object

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       : 

Поиск двоичного содержимого строки

Примечание. Подобно тому, как cygwin string cli, grep и другие команды выполняют поиск в двоичном файле, чтобы найти строку "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"

Пример вывода

ProductHash: Hello_World_abcdefgh2

Дополнительные ресурсы

1

Я только что сделал это на исполняемом файле, и я вижу информацию о версии на вкладке сведений. Итак, я немного расстроен тем, что вы имеете в виду под этим.

Этот подход PS также задокументирован здесь:

https://blogs.technet.microsoft.com/askpfeplat/2014/12/07/how-to-correctly-check-file-versions-with-powershell

На моем клиенте Win10

 (Get-CimInstance -CimInstance Win32_OperatingSystem).Caption
Microsoft Windows 10 Pro

 $PSVersionTable

Name                           Value                                                                                                                                       
----                           -----                                                                                                                                       
PSVersion                      5.1.17134.228                                                                                                                               
PSEdition                      Desktop                                                                                                                                     
PSCompatibleVersions           {1.0, 2.0, 3.0, 4.0, 5.0, 5.1.17134.228}                                                                                                    
BuildVersion                   10.0.17134.228                                                                                                                              
CLRVersion                     4.0.30319.42000                                                                                                                             
WSManStackVersion              3.0                                                                                                                                         
PSRemotingProtocolVersion      2.3                                                                                                                                         
SerializationVersion           1.1.0.1                                                                                                                                     



 (Get-Item -Path 'F:\Downloads\WindowsAzureADRightsManagementAdministration_x64.exe').VersionInfo | Format-List -Force 


OriginalFilename  : setup.exe
FileDescription   : Software Installer
ProductName       : Windows Azure AD Rights Management Administration
Comments          : 
CompanyName       : Microsoft Corporation
FileName          : F:\Downloads\WindowsAzureADRightsManagementAdministration_x64.exe
FileVersion       : 1.0.594.1
ProductVersion    : 1.0.594.1
IsDebug           : False
IsPatched         : False
IsPreRelease      : False
IsPrivateBuild    : False
IsSpecialBuild    : False
Language          : English (United States)
LegalCopyright    : Copyright (c) Microsoft Corporation. All rights reserved.
LegalTrademarks   : Microsoft and Windows are either registered trademarks or trademarks of Microsoft Corporation in the U.S. and/or other countries.
PrivateBuild      : **************************************
SpecialBuild      : 
FileVersionRaw    : 1.0.594.1
ProductVersionRaw : 1.0.594.1

Всё ещё ищете ответ? Посмотрите другие вопросы с метками .