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

在Linux上获取java中.exe的文件版本,java,linux,docker,Java,Linux,Docker,问题-在Linux上为一些奇怪的客户端获取java中的.exe文件版本 溶液- 我使用JNA库使用Java读取文件版本。下面给出的代码在windows平台上运行良好,但在Linux docker映像上抛出以下错误 “无法加载库“版本”:加载共享库libversion时出错。so:没有此类文件或目录加载共享库libversion时出错。so:在资源路径中找不到此类文件或目录本机库(linux-x86-64/libversion.so)。” 我将首先回答你提出的问题,尽管我怀疑这是你真正需要知道的

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

溶液-

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

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


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

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

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

  • 按照上面Wikipedia链接中描述的格式,编写一些代码来读取前几个字节并解码文件头信息
  • 找到一个现有的Java库来实现这一点,并找出如何实现这一点。(谷歌搜索“java文件魔法库”,看看你能找到什么。)
  • 阅读Linux
    file
    命令,编写一些Java代码在每个库上运行
    file
    ,并解析输出

  • 我认为你实际上需要做的是有点不同:

  • 找到Java正在查找的文件系统中的一个或多个文件:显然
    libversion.so
    linux-x86-64/libversion.so
    。(该文件很可能是一个符号链接。请遵循它。)
  • 对每个文件运行
    文件
    ,检查它是否是正确的库类型。它们需要是32位或64位,对应于您正在运行的JVM,以及平台的正确ABI和ISA
  • 检查文件是否位于JVM希望找到它们的位置。JVM在“java.library.path”系统属性中列出的目录中搜索库。您可以(如有必要)使用
    -Djava.library.path=…
    JVM选项设置路径
  • 有关库加载的详细信息,请参阅


    (绝对没有必要在Java中执行步骤2“从”或“在”中)。

    我想我终于弄明白了你在做什么

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

    如果我没有弄错的话,您实际上需要为Linux平台编译和构建Windows COM本机库来完成您要做的事情

    哎呀,那是不可能的

    那你怎么能做到这一点呢?基本上,您需要执行以下操作之一:

    • 查找现有的纯Java库,用于从Windows“.exe”文件提取版本信息。我认为你不大可能找到一个

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

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



    我在另一个答案中提到的“libversion”文件与此无关。这是另外一回事。这是一个令人费解的问题。

    “…没有这样的文件或目录…”向我表示文件路径不正确,或者容器中不存在目标文件。从Win到*nix文件路径可能是一种痛苦。仔细检查资源的位置。嘿@DavidJEddy,我不是Java/linux专家。你能帮我解决这个问题吗?这个“版本”类来自JNA库,我无法控制它。遗憾的是,我对JNA不熟悉。尽管您似乎遇到的问题是文件路径/文件是否存在。应用程序正在查找一个文件,但该文件在给定位置不存在。@DavidEddy,请删除否决票好吗?我花了几个小时才把问题贴出来。你对这个问题做了什么研究?您是否有针对Linux编译的本机代码版本?它是否安装在您的Linux机器上?在Linux机器上查找
    exe
    文件的用例是什么?这是什么项目的一部分?你的问题缺少很多信息。嗨,谢谢你的时间。我需要访问.exe的文件版本,而不是内容类型。如果这些修复程序能帮助我在Linux上运行JNA,我将在第二部分中探讨第一步和第三步。对于作为JNA库一部分的“Version”类来说,这是一个例外。请让我知道,如果你知道一些替代方法。你说的文件版本是什么意思?你是说版本号吗?比如libvorbis.so.0->libvorbis.so.0.4.8?AFAIK,仅通过文件名和符号链接名提供。是的,我需要读取版本号。如果您有其他/更好的方法,请建议我。您可能需要下载libversion源代码,并在Linux机器上构建和安装它。我无法识别任何包含它的Linux包。但我不相信这能解决你的问题。下载libversion不会有帮助。这是一个错误的答案,请看我的另一个答案。我同意你的观点,并且给出的代码在Linux上永远不会工作。linux上的
    文件
    包没有提供
    文件版本
    。我试图在linux上使用
    exiftool
    包来读取
    文件版本
    ,但它的依赖性让我头疼。
    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);
        }
    }