exe文件版本一般用于版本管理和客户版本更新,对exe右键->属性,选择版本就能看见。如下图
如果需要再windows上使用java读取exe文件版本,推荐使用jna.jar。本jar包可以调用本地c/c++类库,非常方便就能获取到exe文件版本。但如果是在其他系统上,那就没法用了,因为本地根本就没有此类库。
跨系统读取exe文件版本其实想法很简单,版本号就在文件里,去读文件不就行了。但由于一般人都不会了解exe文件结构,所以需要去学习文件结构,再开始学代码。最后贴上我的代码:
public class TstThree {
public static void main(String[] args) {
getVersion();
}
public static boolean getVersion() {
String filePath = "F:\\Test\\test.exe";
File file = new File(filePath);
RandomAccessFile raf = null;
byte[] buffer;
String str;
try {
raf = new RandomAccessFile(file, "r");
buffer = new byte[64];
raf.read(buffer);
str = "" + (char)buffer[0] + (char)buffer[1];
if(!"MZ".equals(str)) {
return false;
}
int peOffset = unpack(new byte[]{buffer[60], buffer[61], buffer[62], buffer[63]});
if(peOffset < 64) {
return false;
}
raf.seek(peOffset);
buffer = new byte[24];
raf.read(buffer);
str = "" + (char)buffer[0] + (char)buffer[1];
if(!"PE".equals(str)) {
return false;
}
int machine = unpack(new byte[]{buffer[4], buffer[5]});
if(machine != 332) {
return false;
}
int noSections = unpack(new byte[]{buffer[6], buffer[7]});
int optHdrSize = unpack(new byte[]{buffer[20], buffer[21]});
raf.seek(raf.getFilePointer() + optHdrSize);
boolean resFound = false;
for(int i=0; i < noSections; i++) {
buffer = new byte[40];
raf.read(buffer);
str = "" + (char)buffer[0] + (char)buffer[1] +
(char)buffer[2] + (char)buffer[3] + (char)buffer[4];
if(".rsrc".equals(str)) {
resFound = true;
break;
}
}
if(!resFound) {
return false;
}
int infoVirt = unpack(new byte[]{buffer[12], buffer[13], buffer[14], buffer[15]});
int infoSize = unpack(new byte[]{buffer[16], buffer[17], buffer[18], buffer[19]});
int infoOff = unpack(new byte[]{buffer[20], buffer[21], buffer[22], buffer[23]});
raf.seek(infoOff);
buffer = new byte[infoSize];
raf.read(buffer);
int nameEntries = unpack(new byte[]{buffer[12], buffer[13]});
int idEntries = unpack(new byte[]{buffer[14], buffer[15]});
boolean infoFound = false;
int subOff = 0;
for(int i=0; i < (nameEntries+idEntries); i++) {
int type = unpack(new byte[]{buffer[i*8+16], buffer[i*8+17], buffer[i*8+18], buffer[i*8+19]});
if(type == 16) { //FILEINFO resource
infoFound = true;
subOff = unpack(new byte[]{buffer[i*8+20], buffer[i*8+21], buffer[i*8+22], buffer[i*8+23]});
break;
}
}
if(!infoFound) {
return false;
}
subOff = subOff&0x7fffffff;
infoOff = unpack(new byte[]{buffer[subOff+20], buffer[subOff+21], buffer[subOff+22], buffer[subOff+23]}); //offset of first FILEINFO
infoOff = infoOff&0x7fffffff;
infoOff = unpack(new byte[]{buffer[infoOff+20], buffer[infoOff+21], buffer[infoOff+22], buffer[infoOff+23]}); //offset to data
int dataOff = unpack(new byte[]{buffer[infoOff], buffer[infoOff+1], buffer[infoOff+2], buffer[infoOff+3]});
dataOff = dataOff - infoVirt;
int version1 = unpack(new byte[]{buffer[dataOff+48], buffer[dataOff+48+1]});
int version2 = unpack(new byte[]{buffer[dataOff+48+2], buffer[dataOff+48+3]});
int version3 = unpack(new byte[]{buffer[dataOff+48+4], buffer[dataOff+48+5]});
int version4 = unpack(new byte[]{buffer[dataOff+48+6], buffer[dataOff+48+7]});
System.out.println(version2 + "." + version1 + "." + version4 + "." + version3);
return true;
} catch (FileNotFoundException e) {
return false;
} catch (IOException e) {
return false;
} finally {
if(raf != null) {
try {
raf.close();
} catch (IOException e) {
}
}
}
}
public static int unpack(byte[] b) {
int num = 0;
for(int i=0; i < b.length; i++) {
num = 256 * num + (b[b.length - 1 - i]&0xff);
}
return num;
}
}