【问题标题】:Get File Version of .exe in java on Linux在 Linux 上的 java 中获取 .exe 的文件版本
【发布时间】:2019-07-10 11:58:57
【问题描述】:

问题 - 在 Linux 上为一些奇怪的客户端获取 .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);
    }
}

【问题讨论】:

  • "...没有这样的文件或目录..." 向我表明该文件的路径不正确或容器内不存在目标文件。从 Win 转到 *nix 文件路径可能会很痛苦。仔细检查资源的位置。
  • 嘿@DavidJEddy,我不是Java/Linux 专家。你能帮我解决这个问题吗?这个“版本”类来自 JNA 库,我无法控制。
  • 遗憾的是我不熟悉 JNA。尽管您似乎遇到的问题是文件路径/文件存在之一。应用程序正在查找文件,但该文件在给定位置不存在。
  • @DavidJEddy,你能删除否决票吗?我花了几个小时后发布了这个问题。
  • 你对这个问题做了哪些研究?您是否有针对 Linux 编译的本机代码版本?它安装在你的 Linux 机器上吗?在 Linux 机器上查找 exe 文件的用例是什么?这是什么程序的一部分?您的问题缺少很多信息。

标签: java linux docker


【解决方案1】:

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

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

所以有很多方法可以找出 Java 中的可执行文件类型:

  1. 按照上面维基百科链接中描述的格式编写一些代码,读取前几个字节并解码文件头信息。
  2. 查找执行此操作的现有 Java 库并确定如何执行此操作。 (谷歌搜索“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 中执行第 2 步。)

【讨论】:

  • 您好,感谢您的宝贵时间。我需要访问 .exe 的文件版本而不是内容类型。如果这些修复可以帮助我在 Linux 上运行 JNA,我将在第 2 部分中探索第 1 步和第 3 步。此例外适用于作为 JNA 库一部分的“版本”类。如果您知道其他方法,请告诉我。
  • 文件版本是什么意思?您是指版本编号吗?喜欢 libvorbis.so.0 -> libvorbis.so.0.4.8 吗?仅可通过文件和符号链接名称获得的 AFAIK。
  • 是的,我需要阅读版本号。如果您有其他/更好的方法,请建议我。
  • 您可能需要下载 libversion 源代码并在您的 Linux 机器上构建和安装它。我无法识别任何包含它的 Linux 软件包。但我不相信这会解决你的问题。
  • 下载该 libversion 无济于事。这是错误的,请参阅我的另一个答案。
【解决方案2】:

我想我终于知道你在做什么了。

您使用的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”文件不相关。这是另外一回事。这是一条红鲱鱼。

【讨论】:

  • 我同意你的观点,给定的代码永远不会在 Linux 上运行。 linux 上的File 包没有给出FileVersion。我正在尝试使用Linux 上的exiftool 包来读取FileVersion,但它的依赖关系让我很头疼。
猜你喜欢
  • 2013-04-02
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2015-08-04
  • 1970-01-01
  • 2012-09-05
  • 1970-01-01
相关资源
最近更新 更多