获取.exe的版本信息

有谁知道如何通过Java获取可执行文件的版本信息。 方案是我的本地系统上有一个文件,如果服务器上的版本比较新,那么我的系统上的版本需要从服务器下载文件。

花了几个小时在线和编码后,我找到了一个使用JNA获取文件版本信息的解决方案。

import com.sun.jna.Library; import com.sun.jna.Memory; import com.sun.jna.Native; import com.sun.jna.Pointer; import com.sun.jna.ptr.IntByReference; import com.sun.jna.ptr.PointerByReference; import com.sun.jna.win32.W32APIOptions; import java.io.IOException; public class FileVersionInfo { interface Version extends Library { Version INSTANCE = (Version) Native.loadLibrary("Version", Version.class, W32APIOptions.UNICODE_OPTIONS); public int GetFileVersionInfoSizeW(String lptstrFilename, int dwDummy); public boolean GetFileVersionInfoW(String lptstrFilename, int dwHandle, int dwLen, Pointer lpData); public int VerQueryValueW(Pointer pBlock, String lpSubBlock, PointerByReference lplpBuffer, IntByReference puLen); } static class VS_FIXEDFILEINFO extends com.sun.jna.Structure { public int dwSignature; public int dwStrucVersion; public int dwFileVersionMS; public int dwFileVersionLS; public int dwProductVersionMS; public int dwProductVersionLS; public int dwFileFlagsMask; public int dwFileFlags; public int dwFileOS; public int dwFileType; public int dwFileSubtype; public int dwFileDateMS; public int dwFileDateLS; public VS_FIXEDFILEINFO(com.sun.jna.Pointer p){ super(p); } } public static void main(String[] args) throws IOException { int dwDummy = 0; int versionlength = Version.INSTANCE.GetFileVersionInfoSizeW( "C:\\Test\\chromeinstall.exe", dwDummy); byte[] bufferarray = new byte[versionlength]; Pointer lpData = new Memory(bufferarray.length); PointerByReference lplpBuffer = new PointerByReference(); IntByReference puLen = new IntByReference(); boolean FileInfoResult = Version.INSTANCE.GetFileVersionInfoW( "C:\\Test\\chromeinstall.exe", 0, versionlength, lpData); System.out.println(FileInfoResult); int verQueryVal = Version.INSTANCE.VerQueryValueW(lpData, "\\", lplpBuffer, puLen); VS_FIXEDFILEINFO lplpBufStructure = new VS_FIXEDFILEINFO( lplpBuffer.getValue()); lplpBufStructure.read(); short[] rtnData = new short[4]; rtnData[0] = (short) (lplpBufStructure.dwFileVersionMS >> 16); rtnData[1] = (short) (lplpBufStructure.dwFileVersionMS & 0xffff); rtnData[2] = (short) (lplpBufStructure.dwFileVersionLS >> 16); rtnData[3] = (short) (lplpBufStructure.dwFileVersionLS & 0xffff); for (int i = 0; i < rtnData.length; i++) { System.out.println(rtnData[i]); } } 

供参考,使用com.sun.jna.platform.win32由GEverding和JNA 4修改的代码版本

 package examples; import java.io.IOException; import com.sun.jna.Memory; import com.sun.jna.Pointer; import com.sun.jna.platform.win32.VerRsrc.VS_FIXEDFILEINFO; import com.sun.jna.ptr.IntByReference; import com.sun.jna.ptr.PointerByReference; public class FileVersion { public static void main(String[] args) throws IOException { String filePath = "C:\\Test\\chromeinstall.exe"; IntByReference dwDummy = new IntByReference(); dwDummy.setValue(0); int versionlength = com.sun.jna.platform.win32.Version.INSTANCE.GetFileVersionInfoSize( filePath, dwDummy); byte[] bufferarray = new byte[versionlength]; Pointer lpData = new Memory(bufferarray.length); PointerByReference lplpBuffer = new PointerByReference(); IntByReference puLen = new IntByReference(); boolean fileInfoResult = com.sun.jna.platform.win32.Version.INSTANCE.GetFileVersionInfo( filePath, 0, versionlength, lpData); boolean verQueryVal = com.sun.jna.platform.win32.Version.INSTANCE.VerQueryValue( lpData, "\\", lplpBuffer, puLen); VS_FIXEDFILEINFO lplpBufStructure = new VS_FIXEDFILEINFO(lplpBuffer.getValue()); lplpBufStructure.read(); int v1 = (lplpBufStructure.dwFileVersionMS).intValue() >> 16; int v2 = (lplpBufStructure.dwFileVersionMS).intValue() & 0xffff; int v3 = (lplpBufStructure.dwFileVersionLS).intValue() >> 16; int v4 = (lplpBufStructure.dwFileVersionLS).intValue() & 0xffff; System.out.println( String.valueOf(v1) + "." + String.valueOf(v2) + "." + String.valueOf(v3) + "." + String.valueOf(v4)); } } 

如果您指的是在Windows上的Property-> Details中获得的信息,请记住它依赖于平台! 据说SIGAR有Java绑定和FileVersionInfo类,看起来很接近你需要的。

由于可移植性问题,我认为除非您使用不太便携的方法访问它,否则这种信息在Java中实际上并不可用。

例如,您可以使用JNI和C ++编写包装器,并使用Windows的GetFileVersionInfo API (另请参阅此JavaWorld提示 )从exe获取此类信息。 另一种方法是使用完全外部的应用程序来输出文件的版本,并使用Runtime类来创建进程并与该应用程序进行交互。

其他方法需要访问服务器并从服务器端提供版本检查:

  • 文件包含其名称中的版本号,
  • 保存可供java访问的单独文件,该文件可提供当前版本
  • 在服务器端保存下载日期,并检查当前版本是否比下载最后一个版本的日期更新
  • 检查md5以查看版本是否不同,以防服务器只能包含更新版本或与客户端版本相同的新版本

我修改了Antonis Zafiropoulos的答案并制作了一个方便的课程,你可以放入你的项目。 请注意,fileInfoResult和verQueryVal行必须存在,即使它们似乎没有做任何事情。

 package yourpackage; import com.sun.jna.Memory; import com.sun.jna.Pointer; import com.sun.jna.platform.win32.VerRsrc.VS_FIXEDFILEINFO; import com.sun.jna.ptr.IntByReference; import com.sun.jna.ptr.PointerByReference; public class EXEFileInfo { public static int MAJOR = 0; public static int MINOR = 1; public static int BUILD = 2; public static int REVISION = 3; public static int getMajorVersionOfProgram(String path) { return getVersionInfo(path)[MAJOR]; } public static int getMinorVersionOfProgram(String path) { return getVersionInfo(path)[MINOR]; } public static int getBuildOfProgram(String path) { return getVersionInfo(path)[BUILD]; } public static int getRevisionOfProgram(String path) { return getVersionInfo(path)[REVISION]; } public static int[] getVersionInfo(String path) { IntByReference dwDummy = new IntByReference(); dwDummy.setValue(0); int versionlength = com.sun.jna.platform.win32.Version.INSTANCE.GetFileVersionInfoSize(path, dwDummy); byte[] bufferarray = new byte[versionlength]; Pointer lpData = new Memory(bufferarray.length); PointerByReference lplpBuffer = new PointerByReference(); IntByReference puLen = new IntByReference(); boolean fileInfoResult = com.sun.jna.platform.win32.Version.INSTANCE.GetFileVersionInfo(path, 0, versionlength, lpData); boolean verQueryVal = com.sun.jna.platform.win32.Version.INSTANCE.VerQueryValue(lpData, "\\", lplpBuffer, puLen); VS_FIXEDFILEINFO lplpBufStructure = new VS_FIXEDFILEINFO(lplpBuffer.getValue()); lplpBufStructure.read(); int v1 = (lplpBufStructure.dwFileVersionMS).intValue() >> 16; int v2 = (lplpBufStructure.dwFileVersionMS).intValue() & 0xffff; int v3 = (lplpBufStructure.dwFileVersionLS).intValue() >> 16; int v4 = (lplpBufStructure.dwFileVersionLS).intValue() & 0xffff; System.out.println("Version: " + v1 + "." + v2 + "." + v3 + "." + v4); return new int[] { v1, v2, v3, v4 }; } } 

这里有一个便携式解决方案(这个问题或多或少是重复的)。

基本上,Windows可执行文件使用PE格式(和linux格式的ELF),您可以使用pecoff4j库以便携方式读取此信息。