Инструмент командной строки для сброса версии DLL Windows?

Мне нужен инструмент командной строки для сброса стандартной информации о версии DLL Windows, чтобы я мог обработать ее с помощью скрипта bash (Cygwin).

Как разработчик Java я не очень привык к инструментам разработки Microsoft (хотя у меня есть немного опыта работы с Microsoft Visual Embedded C++ 4.0 и Microsoft Visual Basic 6.0).

соответствующий инструмент, кажется,mt.exe, as указано на SO. Однако единственный шанс узнать это небольшое приложение для загрузки 1.29 GB ISO из Windows SDK для Windows Server 2008 и .NET Framework. Я не могу поверить, что это единственный способ сделать это.

Я также нашел небольшое приложение в интернете под названием PEView, но он отображает слишком много (и бесполезно в моем случае) информации, и это не приложение командной строки.

стандартный objdump в комплекте внутри Cygwin также может сбросить некоторую информацию о DLL-файлы, но я не вижу возможности сбросить версию DLL. Обратите внимание, что MajorImageVersion, MinorImageVersion и другие поля, сбрасываемые этим инструментом (с опцией-p), не связаны с собственной версией DLL.

любые альтернативы, что делать? Может быть, я пропустил какой-то важный вариант objdump? Является mt.exe мой единственный выбор? Если это так, можно ли получить его отдельно от Windows SDK?

11 ответов


вы также можете посмотреть на filever.exe, который можно загрузить как часть средства поддержки Windows XP SP2 пакет-только 4,7 МБ загрузки.


Вы можете использовать PowerShell для получения нужной информации.

(Get-Item C:\Path\To\MyFile.dll).VersionInfo

по умолчанию это будет отображать ProductVersion и FileVersion Но полный VERSIONINFO доступно. Т. е. чтобы вернуть комментарии

(Get-Item C:\Path\To\MyFile.dll).VersionInfo.Comments

использовать Microsoft Sysinternals Sigcheck. Этот пример выводит только версию:

sigcheck -q -n foo.dll

распаковывается sigcheck.exe-это только 228 КБ.


вы можете написать сценарий VBScript, чтобы получить информацию о версии файла:

VersionInfo.vbs

set args = WScript.Arguments
Set fso = CreateObject("Scripting.FileSystemObject")
WScript.Echo fso.GetFileVersion(args(0))
Wscript.Quit

вы можете вызвать это из командной строки следующим образом:

cscript //nologo VersionInfo.vbs C:\Path\To\MyFile.dll

или вы можете построить его самостоятельно. Откройте VS, создайте новое консольное приложение. Создайте простой проект без поддержки ATL или MFC, оставьте опцию stdafx, но не проверяйте "пустой проект" и не называйте его VersionInfo.

вы получите простой проект с 2 файлами: VersionInfo.cpp и VersionInfo.h

откройте файл cpp и вставьте в него следующее, затем скомпилируйте. Вы сможете запустить его, первый аргумент-полное имя файла, он распечатает "товара: Файл 5.6.7.8: 1.2.3.4" на основе блока ресурсов версии. Если нет ресурса версии, он вернет -1, в противном случае 0.

компилируется в двоичный файл 8k с помощью dll CRT, 60k со всем, что связано статически (установите в параметрах C++, измените "страницу генерации кода, параметры выполнения" на "/MT")

HTH.

PS. Если вы не хотите использовать Visual Studio, он все равно будет компилироваться с помощью любого компилятора c++ (скрещенные пальцы), но вам почти наверняка придется изменить # pragma-просто укажите, что lib в настройках компоновщика вместо этого, pragma - это просто стенография для автоматической связи с этой библиотекой.


// VersionInfo.cpp : Defines the entry point for the console application.
//

#include "stdafx.h"
#include <windows.h>

#pragma comment(lib, "version.lib")

int _tmain(int argc, _TCHAR* argv[])
{
    DWORD handle = 0;
    DWORD size = GetFileVersionInfoSize(argv[1], &handle);
    BYTE* versionInfo = new BYTE[size];
    if (!GetFileVersionInfo(argv[1], handle, size, versionInfo))
    {
        delete[] versionInfo;
        return -1;
    }
    // we have version information
    UINT    len = 0;
    VS_FIXEDFILEINFO*   vsfi = NULL;
    VerQueryValue(versionInfo, L"\", (void**)&vsfi, &len);

    WORD fVersion[4], pVersion[4];
    fVersion[0] = HIWORD(vsfi->dwFileVersionMS);
    fVersion[1] = LOWORD(vsfi->dwFileVersionMS);
    fVersion[2] = HIWORD(vsfi->dwFileVersionLS);
    fVersion[3] = LOWORD(vsfi->dwFileVersionLS);
    pVersion[0] = HIWORD(vsfi->dwProductVersionMS);
    pVersion[1] = LOWORD(vsfi->dwProductVersionMS);
    pVersion[2] = HIWORD(vsfi->dwProductVersionLS);
    pVersion[3] = LOWORD(vsfi->dwProductVersionLS);

    printf("Product: %d.%d.%d.%d File: %d.%d.%d.%d\n", 
        pVersion[0], pVersion[1], 
        pVersion[2], pVersion[3], 
        fVersion[0], fVersion[1], 
        fVersion[2], fVersion[3]);
    delete[] versionInfo;

    return 0;
}

C:\>wmic datafile where name="C:\Windows\System32\kernel32.dll" get version
Version
6.1.7601.18229

инструменты listdlls из Systernals могут выполнить эту работу:http://technet.microsoft.com/en-us/sysinternals/bb896656.aspx

listdlls -v -d mylib.dll

эта функция возвращает сведения о файле ntfs Windows для любого файла с помощью Cygwin bash (фактический r-click-properties-info) В термин

передайте путь к файлам finfo (), может быть путь unix, путь dos, относительный или абсолютный. Файл преобразуется в абсолютный путь nix, затем проверяется, является ли он на самом деле обычным/существующим файлом. Затем преобразуется в абсолютный путь windows и отправляется в "wmic". Затем magic, у вас есть сведения о файле windows прямо в терминале. Использование: cygwin, cygpath, sed и awk. Требуется Windows WMI " wmic.exe " для работы. Выход исправлен для легкого...

$ finfo notepad.exe
$ finfo "C:\windows\system32\notepad.exe" 
$ finfo /cygdrive/c/Windows/System32/notepad.exe 
$ finfo "/cygdrive/c/Program Files/notepad.exe"
$ finfo ../notepad.exe

finfo() {
    [[ -e "$(cygpath -wa "$@")" ]] || { echo "bad-file"; return 1; }
    echo "$(wmic datafile where name=\""$(echo "$(cygpath -wa "$@")" | sed 's/\/\\/g')"\" get /value)" |\
    sed 's/\r//g;s/^M$//;/^$/d' | awk -F"=" '{print "=""3[1m""3[0m" }'
}

в CodeProject есть приложение командной строки под названием "ShowVer":

ShowVer.exe программа отображения командной строки VERSIONINFO

как обычно приложение поставляется с exe и исходным кодом (VisualC++ 6).

Out выводит все доступные метаданные:

на немецкой системе Win7 вывод для user32.dll выглядит так:

VERSIONINFO for file "C:\Windows\system32\user32.dll":  (type:0)
  Signature:       feef04bd
  StrucVersion:    1.0
  FileVersion:     6.1.7601.17514
  ProductVersion:  6.1.7601.17514
  FileFlagsMask:   0x3f
  FileFlags:       0
  FileOS:          VOS_NT_WINDOWS32
  FileType:        VFT_DLL
  FileDate:        0.0
 LangID: 040704B0
  CompanyName       : Microsoft Corporation
  FileDescription   : Multi-User Windows USER API Client DLL
  FileVersion       : 6.1.7601.17514 (win7sp1_rtm.101119-1850)
  InternalName      : user32
  LegalCopyright    : ® Microsoft Corporation. Alle Rechte vorbehalten.
  OriginalFilename  : user32
  ProductName       : Betriebssystem Microsoft« Windows«
  ProductVersion    : 6.1.7601.17514
 Translation: 040704b0

С помощью Powershell можно получить только строку версии, т. е. 2.3.4 из любой dll или exe со следующей командой

(Get-Item "C:\program files\OpenVPN\bin\openvpn.exe").VersionInfo.ProductVersion

протестировано в Windows 10


и с makecab:

; @echo off
;;goto :end_help
;;setlocal DsiableDelayedExpansion
;;;
;;;
;;; fileinf /l list of full file paths separated with ;
;;; fileinf /f text file with a list of files to be processed ( one on each line )
;;; fileinf /? prints the help
;;;
;;:end_help

; REM Creating a Newline variable (the two blank lines are required!)
; set NLM=^


; set NL=^^^%NLM%%NLM%^%NLM%%NLM%
; if "%~1" equ "/?" type "%~f0" | find ";;;" | find /v "find" && exit /b 0
; if "%~2" equ "" type "%~f0" | find ";;;" | find /v "find" && exit /b 0
; setlocal enableDelayedExpansion
; if "%~1" equ "/l" (
;  set "_files=%~2"
;  echo !_files:;=%NL%!>"%TEMP%\file.paths"
;  set _process_file="%TEMP%\file.paths"
;  goto :get_info
; )

; if "%~1" equ "/f" if exist "%~2" (
;  set _process_file="%~2"
;  goto :get_info
; )

; echo incorect parameters & exit /b 1
; :get_info
; set "file_info="

; makecab /d InfFileName=%TEMP%\file.inf /d "DiskDirectory1=%TEMP%" /f "%~f0"  /f %_process_file% /v0>nul

; for /f "usebackq skip=4 delims=" %%f in ("%TEMP%\file.inf") do (
;  set "file_info=%%f"
;  echo !file_info:,=%nl%!
; )

; endlocal
;endlocal
; del /q /f %TEMP%\file.inf 2>nul
; del /q /f %TEMP%\file.path 2>nul
; exit /b 0

.set DoNotCopyFiles=on
.set DestinationDir=;
.set RptFileName=nul
.set InfFooter=;
.set InfHeader=;
.Set ChecksumWidth=8
.Set InfDiskLineFormat=;
.Set Cabinet=off
.Set Compress=off
.Set GenerateInf=ON
.Set InfDiskHeader=;
.Set InfFileHeader=;
.set InfCabinetHeader=;
.Set InfFileLineFormat=",file:*file*,date:*date*,size:*size*,csum:*csum*,time:*time*,vern:*ver*,vers:*vers*,lang:*lang*"

пример вывода (он имеет строковую версию, которая является небольшим дополнением к методу wmic:)):

c:> fileinfo.bat /l C:\install.exe
    file:install.exe
    date:11/07/07
    size:562688
    csum:380ef239
    time:07:03:18a
    vern:9.0.21022.8
    vers:9.0.21022.8 built by: RTM
    lang:1033

и с помощью shell.применение и гибридный пакет\jscript.Вот!--10-->tooptipInfo.летучая мышь!--13--> :

@if (@X)==(@Y) @end /* JScript comment
    @echo off

    rem :: the first argument is the script name as it will be used for proper help message
    cscript //E:JScript //nologo "%~f0" %*

    exit /b %errorlevel%

@if (@X)==(@Y) @end JScript comment */

////// 
FSOObj = new ActiveXObject("Scripting.FileSystemObject");
var ARGS = WScript.Arguments;
if (ARGS.Length < 1 ) {
 WScript.Echo("No file passed");
 WScript.Quit(1);
}
var filename=ARGS.Item(0);
var objShell=new ActiveXObject("Shell.Application");
/////


//fso
ExistsItem = function (path) {
    return FSOObj.FolderExists(path)||FSOObj.FileExists(path);
}

getFullPath = function (path) {
    return FSOObj.GetAbsolutePathName(path);
}
//

//paths
getParent = function(path){
    var splitted=path.split("\");
    var result="";
    for (var s=0;s<splitted.length-1;s++){
        if (s==0) {
            result=splitted[s];
        } else {
            result=result+"\"+splitted[s];
        }
    }
    return result;
}


getName = function(path){
    var splitted=path.split("\");
    return splitted[splitted.length-1];
}
//

function main(){
    if (!ExistsItem(filename)) {
        WScript.Echo(filename + " does not exist");
        WScript.Quit(2);
    }
    var fullFilename=getFullPath(filename);
    var namespace=getParent(fullFilename);
    var name=getName(fullFilename);
    var objFolder=objShell.NameSpace(namespace);
    var objItem=objFolder.ParseName(name);
    //https://msdn.microsoft.com/en-us/library/windows/desktop/bb787870(v=vs.85).aspx
    WScript.Echo(fullFilename + " : ");
    WScript.Echo(objFolder.GetDetailsOf(objItem,-1));

}

main();

используется против cmd.exe:

C:\Windows\System32\cmd.exe :
File description: Windows Command Processor
Company: Microsoft Corporation
File version: 6.3.9600.16384
Date created: ?22-?Aug-?13 ??13:03
Size: 347 KB