有谁知道如何通过Java获取可执行文件的版本信息。方案是我的本地系统上有一个文件,如果服务器上的版本比较新,那么我的系统上的版本需要从服务器下载文件。
答案 0 :(得分:9)
在网上和编码上花了数小时后,我找到了一个使用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]);
}
}
答案 1 :(得分:5)
供参考,使用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));
}
}
答案 2 :(得分:2)
由于可移植性问题,我认为除非您使用不太便携的方法访问它,否则这种信息在Java中实际上不可用。
例如,您可以使用JNI和C ++编写包装器,并使用Windows的GetFileVersionInfo API(另请参阅this JavaWorld tip)从exe获取此类信息。另一种方法是使用完全外部的应用程序输出文件的版本,并使用Runtime类创建进程并与该应用程序进行交互。
其他方法需要访问服务器并从服务器端提供版本检查:
答案 3 :(得分:2)
如果您指的是在Windows上的Property-&gt;详细信息中获得的信息,请记住它依赖于平台!据说SIGAR有Java绑定和FileVersionInfo类似乎接近你需要的类。
答案 4 :(得分:2)
我修改了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 };
}
}
答案 5 :(得分:0)
有一个可移植的解决方案explained here(这个问题或多或少是重复的)。
基本上,Windows可执行文件使用PE格式(和linux格式的ELF),您可以使用the pecoff4j library以便携方式读取此信息。