Pregunta

Necesito una herramienta de línea de comandos para volcar la información de la versión estándar de Windows DLL para poder procesarla mediante un script de bash (Cygwin).

Como desarrollador de Java no estoy muy acostumbrado a las herramientas de desarrollo de Microsoft (aunque tengo un poco de experiencia con Microsoft Visual Embedded C ++ 4.0 y Microsoft Visual Basic 6.0).

La herramienta adecuada parece ser mt.exe , como < a href = "https://stackoverflow.com/questions/420852/reading-an-applications-manifest-file"> indicado en SO . Sin embargo, la única oportunidad que he encontrado para obtener esta pequeña aplicación es descargar un ISO de 1.29 GB de Windows SDK para Windows Server 2008 y .NET Framework . No puedo creer que esta sea la única manera de hacerlo.

También encontré una pequeña aplicación en Internet llamada PEView , pero se muestra demasiado (e inútil en mi caso) información y no es una aplicación de línea de comandos.

Estándar objdump incluido en Cygwin también puede volcar información sobre los archivos DLL, pero puedo No veo la opción de volcar la versión DLL. Tenga en cuenta que MajorImageVersion, MinorImageVersion y otros campos volcados por esta herramienta (con la opción -p) no están relacionados con la versión de DLL propia.

¿Alguna alternativa sobre qué hacer? Tal vez me perdí alguna opción importante objdump? ¿Es mt.exe mi única opción? Si este es el caso, ¿es posible obtenerlo por separado desde el SDK de Windows?

¿Fue útil?

Solución

También puede consultar filever.exe, que se puede descargar como parte de Paquete de herramientas de soporte de Windows XP SP2 : solo 4.7MB de descarga.

Otros consejos

Puede usar PowerShell para obtener la información que desee.

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

Por defecto, esto mostrará ProductVersion y FileVersion Pero el VERSIONINFO está disponible. Es decir. para devolver comentarios

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

Utilice Microsoft Sysinternals Sigcheck . Este ejemplo muestra solo la versión:

sigcheck -q -n foo.dll

Sigcheck.exe desempaquetado solo tiene 228 KB.

Puede escribir un script VBScript para obtener la información de la versión del archivo:

VersionInfo.vbs

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

Puedes llamar a esto desde la línea de comando de esta manera:

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

o puedes construir uno tú mismo. Abre VS, crea una nueva aplicación de consola. Cree un proyecto simple sin soporte de ATL o MFC, deje la opción stdafx marcada pero no marque 'proyecto vacío' y llámelo VersionInfo.

Obtendrás un proyecto simple con 2 archivos: VersionInfo.cpp y VersionInfo.h

Abra el archivo cpp y pegue lo siguiente en él, luego compile. Podrá ejecutarlo, el primer argumento es el nombre completo del archivo, se imprimirá " Producto: 5.6.7.8 Archivo: 1.2.3.4 " en función del bloque de recursos de la Versión. Si no hay un recurso de versión, devolverá -1, en caso contrario, 0.

Compila en un binario de 8k usando el CRT de dll, 60k con todo lo vinculado de forma estática (establecido en las opciones de C ++, cambiar la página de generación de código, opciones de tiempo de ejecución a "/ MT")

HTH.

PS. Si no quieres usar Visual Studio, aún así se compilará con cualquier compilador de c ++ (con los dedos cruzados), pero es casi seguro que tendrás que cambiar el #pragma. solo una taquigrafía para enlazar automáticamente con esa 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

Las herramientas listdlls de Systernals podrían hacer el trabajo: http: // technet. microsoft.com/en-us/sysinternals/bb896656.aspx

listdlls -v -d mylib.dll

Esta función devuelve los detalles del archivo ntfs de Windows para cualquier archivo que use Cygwin bash (real r-click-properties-info) al término

Pase la ruta de los archivos a finfo (), puede ser la ruta de Unix, la ruta de dos, relativa o absoluta. El archivo se convierte en una ruta de acceso nix absoluta, y luego se verifica para ver si en realidad es un archivo regular / existente. Luego se convirtió en una ruta de Windows absoluta y se envió a " wmic " ;. Entonces magia, tienes los detalles del archivo de Windows justo en el terminal. Usos: cygwin, cygpath, sed y awk. Necesita Windows WMI " wmic.exe " para ser operacional La salida se corrige 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 es posible obtener solo la cadena de la versión, es decir, 2.3.4 de cualquier dll o exe con el siguiente comando

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

Probado en Windows 10

Hay una aplicación de línea de comandos llamada " ShowVer " en CodeProject:

Programa de visualización VERSIONINFO de la línea de comandos ShowVer.exe

Como de costumbre, la aplicación viene con un exe y el código fuente (VisualC ++ 6).

Sale todos los metadatos disponibles:

En un sistema Win7 alemán, la salida para user32.dll es así:

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

y una forma con 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*"

salida de ejemplo (tiene una versión de cadena que es una pequeña adición al 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

y uno más utilizando shell.application y batch híbrido \ jscript.Aquí está 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();

utilizado 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 bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top