转储Windows DLL版本的命令行工具?

我需要一个命令行工具来转储标准的Windows DLL版本信息,所以我可以通过bash脚本(Cygwin)来处理它。

作为一名Java开发人员,我不太习惯于Microsoft开发工具(尽pipe我对Microsoft Visual C ++ 4.0和Microsoft Visual Basic 6.0有一点点经验)。

正如SO上所述,合适的工具似乎是mt.exe 。 但是,我发现获得这个小应用程序的唯一机会是下载Windows Server 2008和.NET Framework的Windows SDK 1.29 GB ISO。 我不能相信这是做到这一点的唯一方法。

我还在互联网上find了一个名叫PEView的应用程序,但是它显示的信息太多了(而且在我的情况下是无用的)信息,它不是一个命令行应用程序。

Cygwin中捆绑的标准objdump也可以转储有关DLL文件的一些信息,但是我看不到转储DLL版本的选项。 请注意,MajorImageVersion,MinorImageVersion和这个工具(使用-p选项)转储的其他字段与自己的DLL版本无关。

有什么办法可以做什么? 也许我错过了一些重要的objdump选项? mt.exe是我唯一的select吗? 如果是这种情况,是否可以从Windows SDK中单独获取?

您也可以查看filever.exe,它可以作为Windows XP SP2支持工具软件包的一部分下载 – 只有4.7MB的下载(或直接从这里下载)。

你可以使用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 KB。

您可以编写一个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 

或者你可以自己创build一个。 打开VS,创build一个新的控制台应用程序。 创build一个没有ATL或MFC支持的简单项目,保持stdafx选项不被检查,但不检查“空项目”并将其称为VersionInfo。

你会得到一个简单的项目与2个文件:VersionInfo.cpp和VersionInfo.h

打开cpp文件并粘贴下面的内容,然后编译。 你可以运行它,第一个参数是完整的文件名,它会根据Version资源块打印出“Product:5.6.7.8 File:1.2.3.4” 。 如果没有版本资源,它将返回-1,否则返回0。

使用dll CRT编译为8k二进制文件,每个静态链接的一切都在60k(在C ++选项中设置,将“代码生成页面,运行时选项”更改为“/ MT”)

HTH。

PS。 如果你不想使用Visual Studio,它仍然可以使用任何C ++编译器(交叉手指)进行编译,但是你几乎可以肯定必须改变#pragma – 只需在链接器设置中指定这个lib,而编译指示器只是简单的自动链接到该库。


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

Systernals的listdlls工具可以完成这项工作: http ://technet.microsoft.com/en-us/sysinternals/bb896656.aspx

 listdlls -v -d mylib.dll 

这个函数返回任何使用Cygwin bash(实际r-click-properties-info)的文件的ntfs Windows文件详细信息

将文件path传递给finfo(),可以是unixpath,dospath,相对或绝对path。 该文件被转换成一个绝对的nixpath,然后检查它是否实际上是一个常规/现有的文件。 然后转换成绝对的窗口path,并发送到“wmic”。 然后魔术,你有在terminal窗口文件的细节。 用途: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 $1"=""\033[1m"$2"\033[0m" }' } 

在CodeProject上有一个名为“ShowVer”的命令行应用程序:

ShowVer.exe命令行VERSIONINFO显示程序

像往常一样,应用程序附带一个exe和源代码(VisualC ++ 6)。

输出所有可用的元数据:

在德国的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 

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

示例输出(它有一个string版本,这是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.application和混合批处理\ 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(); 

用于反对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