Pergunta

Eu preciso de uma ferramenta de linha de comando para despejar padrão do Windows DLL informação de versão para que eu possa processá-lo por meio de um script bash (Cygwin).

Como um desenvolvedor Java que eu não sou muito usado para ferramentas de desenvolvimento da Microsoft (embora eu tenho um pouco de experiência com Microsoft Visual C ++ incorporado 4.0 e Microsoft Visual Basic 6.0).

A ferramenta apropriada parece ser Mt.exe , como < a href = "https://stackoverflow.com/questions/420852/reading-an-applications-manifest-file"> declarado no SO . No entanto, a única chance que eu encontrei para obter este pequeno aplicativo é baixar um 1,29 GB ISO do Windows SDK para Windows Server 2008 e .NET Framework . Eu não posso acreditar que esta é a única maneira de fazê-lo.

Eu também encontrei um pequeno aplicativo na internet chamado PEView , mas mostra muito (e inútil no meu caso) informações e não é um aplicativo de linha de comando.

objdump empacotado dentro Cygwin também pode despejar algumas informações sobre os arquivos DLL, mas eu posso não vir a opção para despejar versão DLL. Note-se que MajorImageVersion, MinorImageVersion e outros campos despejado por esta ferramenta (com opção -p) não estão relacionados com a própria versão DLL.

Qualquer alternativas sobre o que fazer? Talvez eu tenha perdido alguma opção objdump importante? É Mt.exe minha única opção? Se este for o caso, é possível obtê-lo separadamente do Windows SDK?

Foi útil?

Solução

Você também pode olhar para Filever.exe, que pode ser baixado como parte do ferramentas de suporte do Windows XP SP2 pacote -. única 4.7MB de download

Outras dicas

Você pode usar o PowerShell para obter as informações desejadas.

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

Por padrão isto irá mostrar ProductVersion e FileVersion Mas a completa VERSIONINFO está disponível. Ou seja, para retornar Comentários

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

Use Microsoft Sysinternals SigCheck . Esta saídas de amostra apenas a versão:

sigcheck -q -n foo.dll

sigcheck.exe desembalado apenas 228 KB.

Você pode escrever um script VBScript para obter a informação de versão de arquivo:

VersionInfo.vbs

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

Você pode chamar isso na linha de comando como este:

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

ou você pode construir um você mesmo. Abrir VS, crie um novo aplicativo de console. Crie um projeto simples, sem ATL ou suporte MFC, deixe a opção stdafx marcada, mas não marque 'projeto vazio' e chamá-lo VersionInfo.

Você vai ter um projeto simples com 2 arquivos: VersionInfo.cpp e VersionInfo.h

Abra o arquivo cpp e cole o seguinte para ele, em seguida, compilar. Você vai ser capaz de executá-lo, o primeiro argumento é o nome do arquivo completo, ele vai imprimir "produto: 5.6.7.8 do arquivo: 1.2.3.4" baseado no bloco de recursos Version. Se não houver recurso versão que vai retornar -1, caso contrário 0.

compila para um 8k binário usando o CRT dll, 60k com tudo incluído estaticamente (definido no C ++ opções, altere "Geração de código página, as opções de tempo de execução" para "/ MT")

HTH.

PS. Se você não quiser usar Visual Studio, ele ainda vai compilar usando qualquer compilador c ++ (dedos cruzados), mas você quase certamente tem que mudar a #pragma - apenas especificar que lib nas configurações do vinculador em vez disso, é a Pragma apenas um atalho para automaticamente ligar com essa biblioteca.


// 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

As ferramentas ListDLLs de Systernals pode fazer o trabalho: http: // TechNet. microsoft.com/en-us/sysinternals/bb896656.aspx

listdlls -v -d mylib.dll

Esta função retorna os detalhes do arquivo NTFS do Windows para qualquer arquivo usando Cygwin bash (real r-click-propriedades-Info) para o termo

Passe o caminho arquivos para finfo (), pode ser caminho UNIX, DOS caminho, relativo ou absoluto. O arquivo é convertido em um caminho nix absoluta, então verificado para ver se ele é em verdade a / arquivo regular existente. Então convertido em um caminho de janelas absolutos e enviado para "wmic". Então a mágica, você tem detalhes do arquivo janelas direita no terminal. Usos: cygwin, cygpath, sed e awk. Precisa do Windows WMI "Wmic.exe" para ser operacional. A saída é corrigida para fácil ...

$ 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 $1"=""\033[1m"$2"\033[0m" }'
}

Usando PowerShell é possível obter apenas a cadeia de versão, ou seja, 2.3.4 a partir de qualquer dll ou exe com o seguinte comando

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

Testado em Windows 10

Existe um aplicativo de linha de comando chamado "ShowVer" no CodeProject:

ShowVer.exe de linha de comando programa de exibição VERSIONINFO

Como de costume a aplicação vem com um exe eo código fonte (VisualC ++ 6).

Fora saídas de todos os metadados disponíveis:

Em um sistema alemão Win7 a saída para user32.dll é assim:

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

e uma maneira com 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*"

exemplo de saída (tem uma versão corda que é um pequeno acréscimo ao método 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

e mais uma Usando Shell.Application e híbridos lote \ de jscript.Here tooptipInfo.bat :

@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();

usado contra 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
Licenciado em: CC-BY-SA com atribuição
Não afiliado a StackOverflow
scroll top