在Linux上的Java中获取.exe的文件版本

时间:2019-07-10 11:58:57

标签: java linux docker

问题-在Linux上的Java中为某些奇怪的客户端获取.exe的文件版本。

解决方案-

我使用JNA库使用Java读取文件版本。鉴于以下给出的代码在Windows平台上运行良好,但在Linux docker映像上却抛出了以下错误。

“无法加载库'version':加载共享库libversion.so时出错:没有此类文件或目录加载共享库libversion.so时出错:没有此类文件或目录本机库(linux-x86-64 / libversion.so )在资源路径中找不到。..

private String GetFileVersion(String filePath) {

    File fileToCheck = new File(filePath);
    short[] rtnData = new short[4];


    int infoSize = Version.INSTANCE.GetFileVersionInfoSize(fileToCheck.getAbsolutePath(), null);
    Pointer buffer = Kernel32.INSTANCE.LocalAlloc(WinBase.LMEM_ZEROINIT, infoSize);

    try {

        Version.INSTANCE.GetFileVersionInfo(fileToCheck.getAbsolutePath(), 0, infoSize, buffer);
        IntByReference outputSize = new IntByReference();
        PointerByReference pointer = new PointerByReference();
        Version.INSTANCE.VerQueryValue(buffer, "\\", pointer, outputSize);
        VerRsrc.VS_FIXEDFILEINFO fileInfoStructure = new VerRsrc.VS_FIXEDFILEINFO(pointer.getValue());

        rtnData[0] = (short) (fileInfoStructure.dwFileVersionMS.longValue() >> 16);
        rtnData[1] = (short) (fileInfoStructure.dwFileVersionMS.longValue() & 0xffff);
        rtnData[2] = (short) (fileInfoStructure.dwFileVersionLS.longValue() >> 16);
        rtnData[3] = (short) (fileInfoStructure.dwFileVersionLS.longValue() & 0xffff);

        return String.format("%s.%s.%s.%s", rtnData[0], rtnData[1], rtnData[2], rtnData[3]);

    } catch (Exception exception) {

        return null;

    } finally {
        Kernel32.INSTANCE.GlobalFree(buffer);
    }
}

2 个答案:

答案 0 :(得分:0)

尽管我怀疑这是您实际上需要知道的,但我将首先回答您提出的问题。

不同的可执行文件格式的类型编码在文件的前几个字节中。例如,this Wikipedia页面中描述了ELF文件(可执行文件,共享库)。

因此,有多种方法可以找出Java中哪种可执行文件:

  1. 按照上面的Wikipedia链接中所述的格式,编写一些读取前几个字节并解码文件头信息的代码。
  2. 找到一个可以执行此操作的现有Java库,并确定如何执行此操作。 (Google提供了“ java文件魔术库”,请看您能找到什么。)
  3. 了解Linux file命令并编写一些Java代码以在每个库上运行file并解析输出。

我认为您实际上需要做的事情有所不同:

  1. 在Java正在查找的文件系统中找到一个或多个文件:显然是libversion.solinux-x86-64/libversion.so。 (该文件很可能是符号链接。请遵循它。)
  2. 在每个文件上运行file,以检查它是否是正确的库。它们必须为32或64位对应于您正在运行的JVM ,以及用于平台的正确ABI和ISA。
  3. 检查文件是否是JVM期望在其中找到的文件。 JVM在“ java.library.path”系统属性中列出的目录中搜索库。您可以(如有必要)使用-Djava.library.path=... JVM选项设置路径。

有关库加载的更多信息,请参见"java.library.path – What is it and how to use"

(绝对不需要“从Java中”或“在Java中”执行步骤2。)

答案 1 :(得分:0)

我想我终于弄清楚了你在做什么。

您使用的Version实际上来自软件包com.sun.jna.platform.win32。它不是JNA库(jna.jar)的一部分。我认为它实际上是jna-platform.jar的一部分。如果我理解正确,那就是Windows COM dll生成的JNA适配器库。

如果我没错,实际上您将需要为Linux平台编译和构建的Windows COM本机库来执行您想做的事情。

AFAIK,那是不可能的。

那你怎么做这项工作?基本上,您需要执行以下操作之一:

  • 寻找现有的纯Java 库,以从Windows“ .exe”文件中提取版本信息。我认为您不太可能会找到一个。

  • 找到Windows“ .exe”文件格式的规范,并编写自己的Java代码以提取版本信息。我没有寻找规范来查看它会做多少工作。

然后重写添加问题的代码以使用替代API。


我在其他答案中提到的“ libversion”文件不相关。这是另一回事。这是一条红鲱鱼。