Domanda

Ho bisogno di uno strumento da riga di comando per scaricare le informazioni sulla versione standard della DLL di Windows in modo da poterlo elaborare tramite uno script bash (Cygwin).

Come sviluppatore Java non sono molto abituato agli strumenti di sviluppo Microsoft (anche se ho un po 'di esperienza con Microsoft Visual Embedded C ++ 4.0 e Microsoft Visual Basic 6.0).

Lo strumento appropriato sembra essere mt.exe , come < a href = "https://stackoverflow.com/questions/420852/reading-an-applications-manifest-file"> indicato su SO . Tuttavia, l'unica possibilità che ho trovato per ottenere questa piccola applicazione è quella di scaricare un ISO da 1,29 GB di Windows SDK per Windows Server 2008 e .NET Framework . Non posso credere che questo sia l'unico modo per farlo.

Ho anche trovato una piccola applicazione su Internet chiamata PEView , ma mostra troppo (e inutili nel mio caso) informazioni e non si tratta di un'applicazione a riga di comando.

Standard objdump in bundle all'interno di Cygwin può anche scaricare alcune informazioni sui file DLL, ma posso non vedere l'opzione per scaricare la versione DLL. Notare che MajorImageVersion, MinorImageVersion e altri campi scaricati da questo strumento (con l'opzione -p) non sono correlati alla propria versione della DLL.

Qualche alternativa su cosa fare? Forse ho perso qualche importante opzione objdump? Mt.exe è la mia unica scelta? In questo caso, è possibile ottenerlo separatamente da Windows SDK?

È stato utile?

Soluzione

Puoi anche guardare filever.exe, che può essere scaricato come parte di pacchetto Strumenti di supporto di Windows XP SP2 - solo 4,7 MB di download.

Altri suggerimenti

È possibile utilizzare PowerShell per ottenere le informazioni desiderate.

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

Per impostazione predefinita, verranno visualizzati ProductVersion e FileVersion Ma l'intero VERSIONINFO è disponibile. Cioè per restituire commenti

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

Usa Microsoft Sysinternals Sigcheck . Questo esempio mostra solo la versione:

sigcheck -q -n foo.dll

sigcheck.exe decompresso è solo 228 KB.

Puoi scrivere uno script VBScript per ottenere le informazioni sulla versione del file:

VersionInfo.vbs

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

Puoi chiamarlo dalla riga di comando in questo modo:

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

oppure puoi costruirne uno tu stesso. Apri VS, crea una nuova applicazione console. Crea un progetto semplice senza supporto ATL o MFC, lascia selezionata l'opzione stdafx ma non selezionare "progetto vuoto" e chiamarlo VersionInfo.

Otterrai un semplice progetto con 2 file: VersionInfo.cpp e VersionInfo.h

Apri il file cpp e incolla quanto segue, quindi compila. Sarai in grado di eseguirlo, il primo argomento è il nome file completo, verrà stampato " Prodotto: 5.6.7.8 File: 1.2.3.4 " in base al blocco di risorse Versione. Se non è presente alcuna risorsa versione, verrà restituito -1, altrimenti 0.

Compila un binario 8k usando la dll CRT, 60k con tutto ciò che è collegato staticamente (impostato nelle opzioni C ++, modifica " Pagina di generazione del codice, Opzioni di runtime " in " / MT ")

HTH.

PS. Se non vuoi usare Visual Studio, verrà comunque compilato usando qualsiasi compilatore c ++ (dita incrociate), ma quasi sicuramente dovrai cambiare #pragma - specifica invece quella lib nelle impostazioni del linker, il pragma's solo una scorciatoia per collegarsi automaticamente a quella libreria.


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

Gli strumenti listdlls di Systernals potrebbero fare il lavoro: http: // technet. microsoft.com/en-us/sysinternals/bb896656.aspx

listdlls -v -d mylib.dll

Questa funzione restituisce i dettagli del file Windows NTFS per qualsiasi file che utilizza Cygwin bash (informazioni reali r-clic-proprietà) al termine

Passa il percorso dei file a finfo (), può essere unix path, dos path, relativo o assoluto. Il file viene convertito in un percorso nix assoluto, quindi controllato per vedere se si tratta effettivamente di un file normale / esistente. Quindi convertito in un percorso assoluto di Windows e inviato a " wmic " ;. Quindi magia, hai i dettagli del file di Windows proprio nel terminale. Usi: cygwin, cygpath, sed e awk. Richiede Windows WMI "wmic.exe" essere operativo. L'output viene corretto per semplificare ...

$ 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 è possibile ottenere solo la stringa Version, ovvero 2.3.4 da qualsiasi dll o exe con il seguente comando

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

Testato su Windows 10

Esiste un'applicazione da riga di comando chiamata " ShowVer " su CodeProject:

Programma di visualizzazione VERSIONINFO della riga di comando ShowVer.exe

Come al solito, l'applicazione include un exe e il codice sorgente (VisualC ++ 6).

Out genera tutti i metadati disponibili:

Su un sistema Win7 tedesco l'output per user32.dll è così:

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 un modo 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*"

esempio di output (ha una versione stringa che è una piccola aggiunta al metodo 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 un altro ancora usando shell.application e il batch ibrido \ jscript. Qui 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();

utilizzato contro 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
Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top