📜 ⬆️ ⬇️

Get the file version (exe, dll) using java

I faced such a problem - how to get the file version (exe and dll) on java. After all, the usual standard means to determine this is impossible, but only you can find out the size, the date of the last modification and some other properties of the file. It is described here .
Having rummaged on the forums and everything was thoroughly googling - I found two such exits - JNI and JNA . I stopped at the second version, since I didn’t really want to write a special dll in C ++, I wanted to solve everything with java and go directly to version.dll (C: \ WINDOWS \ system32).
As a result, the decision is reduced to such a bundle GetFileVersionInfo - GetFileVersionInfoSize - VerQueryValue . I had to deal with the VerQueryValue function for a long time - the difficulty was that the versions of the files depended on the language and it was necessary to get LANGANDCODEPAGE in a tricky way. The result was this class:



package upload;

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.StdCallLibrary;
import java.io.IOException;

/**
*
* @author samozvanka
*/
public class Win32GetFileInformation
{
//+ declare before using
private static byte [] Hexhars = "«0123456789abcdef" .getBytes();

public String FileVersion;
private String LanguageCodePage;
private PointerByReference InfoData;

public interface Win32VersionDLL extends StdCallLibrary
{
Win32VersionDLL INSTANCE = (Win32VersionDLL) Native.loadLibrary(
"Version" , Win32VersionDLL. class );

Integer GetFileVersionInfoSizeA( String FilePath, IntByReference Handle);

Boolean GetFileVersionInfoA( String FilePath, int Handle, int InfoSize,
PointerByReference InfoData);

Boolean VerQueryValueA(PointerByReference InfoData,
String VersionInformation, PointerByReference VersionData,
IntByReference DataSize);
}

public void Win32GetFileInformation( String FilePath) throws IOException
{
IntByReference unusedParam = new IntByReference();

int infoSize = Win32VersionDLL.INSTANCE.GetFileVersionInfoSizeA(FilePath, unusedParam);
if (infoSize == 0)
{
throw new IOException( "File does not exist or has no information." );
}

this .InfoData = new PointerByReference();

Boolean success = Win32VersionDLL.INSTANCE.GetFileVersionInfoA
(
FilePath,
unusedParam.getValue(),
infoSize,
this .InfoData
);

//+ Assert(success, "GetFileVersionInfoA in Win32GetFileInformation is failed")

PointerByReference versionDataByRef = new PointerByReference();
IntByReference dataSize = new IntByReference();
Pointer versionDataPointer = null ;

// Retrieve the language information
success = Win32VersionDLL.INSTANCE.VerQueryValueA
(
this .InfoData,
"\\VarFileInfo\\Translation" ,
versionDataByRef,
dataSize
);

//+ Assert(success, "VerQueryValueA in Win32GetFileInformation is failed")

System. out .println( "DataSize.getValue() = " + dataSize.getValue());

versionDataPointer = versionDataByRef.getValue();
byte [] codePageBytes = versionDataPointer.getByteArray(0, dataSize.getValue());
byte BSwap;
// swap 0<->1 and 2<->3
BSwap = codePageBytes[1];
codePageBytes[1] = codePageBytes[0];
codePageBytes[0] = BSwap;
BSwap = codePageBytes[3];
codePageBytes[3] = codePageBytes[2];
codePageBytes[2] = BSwap;
// got 1,0,3,2

this .LanguageCodePage = decode(codePageBytes).toUpperCase();

//// Retrieve file information
this .FileVersion = QueryValue( "FileVersion" );

System. out .println( "FileVersion = " + this .FileVersion);

}

private String QueryValue( String ValueName)
{
IntByReference dataSize = new IntByReference();
PointerByReference versionDataByRef = new PointerByReference();
Pointer versionDataPointer = null ;
Boolean success = Win32VersionDLL.INSTANCE.VerQueryValueA
(
this .InfoData,
"\\StringFileInfo\\" + this.LanguageCodePage + " \\ " + ValueName, //"
versionDataByRef,
dataSize
);

//+ Assert(success, "VerQueryValueA in Win32GetFileInformation is failed")

versionDataPointer = versionDataByRef.getValue();
if (versionDataPointer == null )
{
return "" ;
}
else
{
versionDataPointer = versionDataByRef.getValue();
return versionDataPointer.getString();
}
}

private static String decode( byte [] encodedString)
{
StringBuilder result = new StringBuilder (2 * encodedString.length);

for ( int i = 0; i < encodedString.length; i++)
{
int v = encodedString[i] & 0xff;

result.append(( char ) Hexhars[v >> 4]);
result.append(( char ) Hexhars[v & 0xf]);
}

return result.toString();
}
}

* This source code was highlighted with Source Code Highlighter .

')
Suddenly someone come in handy. And if there are any other simple implementations of this, I would like to know them.

Source: https://habr.com/ru/post/93028/


All Articles