获取 .exe 的版本信息

发布于 2024-11-27 08:23:05 字数 87 浏览 1 评论 0原文

有谁知道如何通过 Java 获取可执行文件/文件的版本信息。情况是,我的本地系统上有一个文件,如果服务器上的版本比我系统上的版本更新,我需要从服务器下载该文件。

Does anybody know how got get the version info for a executable/file via Java. The scenario is that I have a file on my local system and if the version on the server is newer then the one on my system I need to download the file from the server.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(7

末蓝 2024-12-04 08:23:05

经过几个小时的在线编码后,我找到了一个使用 JNA 获取文件版本信息的解决方案。

import com.sun.jna.Library;
import com.sun.jna.Memory;
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.W32APIOptions;
import java.io.IOException;


public class FileVersionInfo
{
    interface Version extends Library {

        Version INSTANCE = (Version) Native.loadLibrary("Version", Version.class, W32APIOptions.UNICODE_OPTIONS);

        public int GetFileVersionInfoSizeW(String lptstrFilename, int dwDummy);

        public boolean GetFileVersionInfoW(String lptstrFilename, int dwHandle,
            int dwLen, Pointer lpData);

        public int VerQueryValueW(Pointer pBlock, String lpSubBlock,
            PointerByReference lplpBuffer, IntByReference puLen);

    }

    static class VS_FIXEDFILEINFO extends com.sun.jna.Structure {
        public int dwSignature;
        public int dwStrucVersion;
        public int dwFileVersionMS;
        public int dwFileVersionLS;
        public int dwProductVersionMS;
        public int dwProductVersionLS;
        public int dwFileFlagsMask;
        public int dwFileFlags;
        public int dwFileOS;
        public int dwFileType;
        public int dwFileSubtype;
        public int dwFileDateMS;
        public int dwFileDateLS;

           public VS_FIXEDFILEINFO(com.sun.jna.Pointer p){
                super(p);
           }
    }
    public static void main(String[] args) throws IOException {

        int dwDummy = 0;
        int versionlength = Version.INSTANCE.GetFileVersionInfoSizeW(
                "C:\\Test\\chromeinstall.exe", dwDummy);

        byte[] bufferarray = new byte[versionlength];
        Pointer lpData = new Memory(bufferarray.length);    

        PointerByReference lplpBuffer = new PointerByReference();
        IntByReference puLen = new IntByReference();
        boolean FileInfoResult = Version.INSTANCE.GetFileVersionInfoW(
                "C:\\Test\\chromeinstall.exe",
                0, versionlength, lpData);
        System.out.println(FileInfoResult);
        int verQueryVal = Version.INSTANCE.VerQueryValueW(lpData,
                "\\", lplpBuffer,
                puLen);

        VS_FIXEDFILEINFO lplpBufStructure = new VS_FIXEDFILEINFO(
                lplpBuffer.getValue());
        lplpBufStructure.read();

        short[] rtnData = new short[4];
        rtnData[0] = (short) (lplpBufStructure.dwFileVersionMS >> 16);
        rtnData[1] = (short) (lplpBufStructure.dwFileVersionMS & 0xffff);
        rtnData[2] = (short) (lplpBufStructure.dwFileVersionLS >> 16);
        rtnData[3] = (short) (lplpBufStructure.dwFileVersionLS & 0xffff);

        for (int i = 0; i < rtnData.length; i++) {
            System.out.println(rtnData[i]);
        }

} 

After spending hours online and coding I found a solution using JNA to get the Version Information for a file.

import com.sun.jna.Library;
import com.sun.jna.Memory;
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.W32APIOptions;
import java.io.IOException;


public class FileVersionInfo
{
    interface Version extends Library {

        Version INSTANCE = (Version) Native.loadLibrary("Version", Version.class, W32APIOptions.UNICODE_OPTIONS);

        public int GetFileVersionInfoSizeW(String lptstrFilename, int dwDummy);

        public boolean GetFileVersionInfoW(String lptstrFilename, int dwHandle,
            int dwLen, Pointer lpData);

        public int VerQueryValueW(Pointer pBlock, String lpSubBlock,
            PointerByReference lplpBuffer, IntByReference puLen);

    }

    static class VS_FIXEDFILEINFO extends com.sun.jna.Structure {
        public int dwSignature;
        public int dwStrucVersion;
        public int dwFileVersionMS;
        public int dwFileVersionLS;
        public int dwProductVersionMS;
        public int dwProductVersionLS;
        public int dwFileFlagsMask;
        public int dwFileFlags;
        public int dwFileOS;
        public int dwFileType;
        public int dwFileSubtype;
        public int dwFileDateMS;
        public int dwFileDateLS;

           public VS_FIXEDFILEINFO(com.sun.jna.Pointer p){
                super(p);
           }
    }
    public static void main(String[] args) throws IOException {

        int dwDummy = 0;
        int versionlength = Version.INSTANCE.GetFileVersionInfoSizeW(
                "C:\\Test\\chromeinstall.exe", dwDummy);

        byte[] bufferarray = new byte[versionlength];
        Pointer lpData = new Memory(bufferarray.length);    

        PointerByReference lplpBuffer = new PointerByReference();
        IntByReference puLen = new IntByReference();
        boolean FileInfoResult = Version.INSTANCE.GetFileVersionInfoW(
                "C:\\Test\\chromeinstall.exe",
                0, versionlength, lpData);
        System.out.println(FileInfoResult);
        int verQueryVal = Version.INSTANCE.VerQueryValueW(lpData,
                "\\", lplpBuffer,
                puLen);

        VS_FIXEDFILEINFO lplpBufStructure = new VS_FIXEDFILEINFO(
                lplpBuffer.getValue());
        lplpBufStructure.read();

        short[] rtnData = new short[4];
        rtnData[0] = (short) (lplpBufStructure.dwFileVersionMS >> 16);
        rtnData[1] = (short) (lplpBufStructure.dwFileVersionMS & 0xffff);
        rtnData[2] = (short) (lplpBufStructure.dwFileVersionLS >> 16);
        rtnData[3] = (short) (lplpBufStructure.dwFileVersionLS & 0xffff);

        for (int i = 0; i < rtnData.length; i++) {
            System.out.println(rtnData[i]);
        }

} 
淡莣 2024-12-04 08:23:05

作为参考,GEverding 的代码修改版本,带有 JNA 4,使用 com.sun.jna.platform.win32

package examples;

import java.io.IOException;

import com.sun.jna.Memory;
import com.sun.jna.Pointer;
import com.sun.jna.platform.win32.VerRsrc.VS_FIXEDFILEINFO;
import com.sun.jna.ptr.IntByReference;
import com.sun.jna.ptr.PointerByReference;

public class FileVersion {

    public static void main(String[] args) throws IOException {

        String filePath = "C:\\Test\\chromeinstall.exe";

        IntByReference dwDummy = new IntByReference();
        dwDummy.setValue(0);

        int versionlength =
                com.sun.jna.platform.win32.Version.INSTANCE.GetFileVersionInfoSize(
                        filePath, dwDummy);

        byte[] bufferarray = new byte[versionlength];
        Pointer lpData = new Memory(bufferarray.length);
        PointerByReference lplpBuffer = new PointerByReference();
        IntByReference puLen = new IntByReference();

        boolean fileInfoResult =
                com.sun.jna.platform.win32.Version.INSTANCE.GetFileVersionInfo(
                        filePath, 0, versionlength, lpData);

        boolean verQueryVal =
                com.sun.jna.platform.win32.Version.INSTANCE.VerQueryValue(
                        lpData, "\\", lplpBuffer, puLen);

        VS_FIXEDFILEINFO lplpBufStructure = new VS_FIXEDFILEINFO(lplpBuffer.getValue());
        lplpBufStructure.read();

        int v1 = (lplpBufStructure.dwFileVersionMS).intValue() >> 16;
        int v2 = (lplpBufStructure.dwFileVersionMS).intValue() & 0xffff;
        int v3 = (lplpBufStructure.dwFileVersionLS).intValue() >> 16;
        int v4 = (lplpBufStructure.dwFileVersionLS).intValue() & 0xffff;

        System.out.println(
                String.valueOf(v1) + "." +
                        String.valueOf(v2) + "." +
                        String.valueOf(v3) + "." +
                        String.valueOf(v4));
    }
}

For reference, a modified version of the code by GEverding, with JNA 4, using com.sun.jna.platform.win32

package examples;

import java.io.IOException;

import com.sun.jna.Memory;
import com.sun.jna.Pointer;
import com.sun.jna.platform.win32.VerRsrc.VS_FIXEDFILEINFO;
import com.sun.jna.ptr.IntByReference;
import com.sun.jna.ptr.PointerByReference;

public class FileVersion {

    public static void main(String[] args) throws IOException {

        String filePath = "C:\\Test\\chromeinstall.exe";

        IntByReference dwDummy = new IntByReference();
        dwDummy.setValue(0);

        int versionlength =
                com.sun.jna.platform.win32.Version.INSTANCE.GetFileVersionInfoSize(
                        filePath, dwDummy);

        byte[] bufferarray = new byte[versionlength];
        Pointer lpData = new Memory(bufferarray.length);
        PointerByReference lplpBuffer = new PointerByReference();
        IntByReference puLen = new IntByReference();

        boolean fileInfoResult =
                com.sun.jna.platform.win32.Version.INSTANCE.GetFileVersionInfo(
                        filePath, 0, versionlength, lpData);

        boolean verQueryVal =
                com.sun.jna.platform.win32.Version.INSTANCE.VerQueryValue(
                        lpData, "\\", lplpBuffer, puLen);

        VS_FIXEDFILEINFO lplpBufStructure = new VS_FIXEDFILEINFO(lplpBuffer.getValue());
        lplpBufStructure.read();

        int v1 = (lplpBufStructure.dwFileVersionMS).intValue() >> 16;
        int v2 = (lplpBufStructure.dwFileVersionMS).intValue() & 0xffff;
        int v3 = (lplpBufStructure.dwFileVersionLS).intValue() >> 16;
        int v4 = (lplpBufStructure.dwFileVersionLS).intValue() & 0xffff;

        System.out.println(
                String.valueOf(v1) + "." +
                        String.valueOf(v2) + "." +
                        String.valueOf(v3) + "." +
                        String.valueOf(v4));
    }
}
枉心 2024-12-04 08:23:05

由于可移植性问题,我相信此类信息在 java 中实际上不可用,除非您使用不太可移植的方法访问它。

例如,您可以使用 JNI 和 C++ 编写包装器,并使用 GetFileVersionInfo API(另请参阅这个 JavaWorld 提示) 可以从 Windows 的 exe 中获取此类信息。另一种方法是使用完全外部的应用程序来输出文件的版本,并使用 Runtime 类创建进程并与该应用程序交互。

其他方法需要访问服务器并从服务器端提供版本检查:

  • 文件名称中包含版本号,
  • 保存一个可由 java 访问的单独文件,该文件可以提供当前版本,
  • 保存服务器端的下载日期并检查如果当前版本比上次下载的日期新,
  • 请检查 md5 以查看版本是否不同,以防服务器只能包含更新版本或与客户端版本相同的版本

Due to portability issues I believe this kind of information is not actually available in java unless you access it using a less portable approach.

For example you could write a wrapper using JNI and C++ and use the GetFileVersionInfo API (see also this JavaWorld tip) of Windows to get that kind of information from the exe. Another approach would be to use a totally external application that outputs the version of the file and use the Runtime class to create a process and interact with that application.

Other approaches would require having access to the server and providing version checking from server side:

  • files contain the version number in their name,
  • save a separate file accessible to java that can provide the current version
  • save the date of the download on server side and checking if the current version is newer than the date when the last one was downloaded
  • check the md5 to see if the version is different, in case the server can contain only versions newer or equally as new as the client one
甜中书 2024-12-04 08:23:05

如果您指的是 Windows 上的“属性”->“详细信息”中获得的信息,请记住它依赖于平台!话虽如此,SIGAR 具有 Java 绑定和 FileVersionInfo 类看起来很接近您的需要。

If you mean the information you get in Property->Details on Windows, bear in mind that it's platform dependent! That being said SIGAR has Java bindings and a FileVersionInfo class that seems close to what you need.

舞袖。长 2024-12-04 08:23:05

我修改了 Antonis Zafiropoulos 的答案,并制作了一个方便的课程,您可以将其放入您的项目中。请注意,fileInfoResult 和 verQueryVal 行必须存在,即使它们似乎没有执行任何操作。

package yourpackage;

import com.sun.jna.Memory;
import com.sun.jna.Pointer;
import com.sun.jna.platform.win32.VerRsrc.VS_FIXEDFILEINFO;
import com.sun.jna.ptr.IntByReference;
import com.sun.jna.ptr.PointerByReference;

public class EXEFileInfo {
    public static int MAJOR = 0;
    public static int MINOR = 1;
    public static int BUILD = 2;
    public static int REVISION = 3;

    public static int getMajorVersionOfProgram(String path) {
        return getVersionInfo(path)[MAJOR];
    }

    public static int getMinorVersionOfProgram(String path) {
        return getVersionInfo(path)[MINOR];
    }

    public static int getBuildOfProgram(String path) {
        return getVersionInfo(path)[BUILD];
    }

    public static int getRevisionOfProgram(String path) {
        return getVersionInfo(path)[REVISION];
    }

    public static int[] getVersionInfo(String path) {
        IntByReference dwDummy = new IntByReference();
        dwDummy.setValue(0);

        int versionlength = com.sun.jna.platform.win32.Version.INSTANCE.GetFileVersionInfoSize(path, dwDummy);

        byte[] bufferarray = new byte[versionlength];
        Pointer lpData = new Memory(bufferarray.length);
        PointerByReference lplpBuffer = new PointerByReference();
        IntByReference puLen = new IntByReference();
        boolean fileInfoResult = com.sun.jna.platform.win32.Version.INSTANCE.GetFileVersionInfo(path, 0, versionlength, lpData);
        boolean verQueryVal = com.sun.jna.platform.win32.Version.INSTANCE.VerQueryValue(lpData, "\\", lplpBuffer, puLen);

        VS_FIXEDFILEINFO lplpBufStructure = new VS_FIXEDFILEINFO(lplpBuffer.getValue());
        lplpBufStructure.read();

        int v1 = (lplpBufStructure.dwFileVersionMS).intValue() >> 16;
        int v2 = (lplpBufStructure.dwFileVersionMS).intValue() & 0xffff;
        int v3 = (lplpBufStructure.dwFileVersionLS).intValue() >> 16;
        int v4 = (lplpBufStructure.dwFileVersionLS).intValue() & 0xffff;
        System.out.println("Version: " + v1 + "." + v2 + "." + v3 + "." + v4);
        return new int[] { v1, v2, v3, v4 };
    }
}

I modified Antonis Zafiropoulos's answer and made a handy class you can just drop into your project. Note that the fileInfoResult and verQueryVal lines must exist even though they don't appear to do anything.

package yourpackage;

import com.sun.jna.Memory;
import com.sun.jna.Pointer;
import com.sun.jna.platform.win32.VerRsrc.VS_FIXEDFILEINFO;
import com.sun.jna.ptr.IntByReference;
import com.sun.jna.ptr.PointerByReference;

public class EXEFileInfo {
    public static int MAJOR = 0;
    public static int MINOR = 1;
    public static int BUILD = 2;
    public static int REVISION = 3;

    public static int getMajorVersionOfProgram(String path) {
        return getVersionInfo(path)[MAJOR];
    }

    public static int getMinorVersionOfProgram(String path) {
        return getVersionInfo(path)[MINOR];
    }

    public static int getBuildOfProgram(String path) {
        return getVersionInfo(path)[BUILD];
    }

    public static int getRevisionOfProgram(String path) {
        return getVersionInfo(path)[REVISION];
    }

    public static int[] getVersionInfo(String path) {
        IntByReference dwDummy = new IntByReference();
        dwDummy.setValue(0);

        int versionlength = com.sun.jna.platform.win32.Version.INSTANCE.GetFileVersionInfoSize(path, dwDummy);

        byte[] bufferarray = new byte[versionlength];
        Pointer lpData = new Memory(bufferarray.length);
        PointerByReference lplpBuffer = new PointerByReference();
        IntByReference puLen = new IntByReference();
        boolean fileInfoResult = com.sun.jna.platform.win32.Version.INSTANCE.GetFileVersionInfo(path, 0, versionlength, lpData);
        boolean verQueryVal = com.sun.jna.platform.win32.Version.INSTANCE.VerQueryValue(lpData, "\\", lplpBuffer, puLen);

        VS_FIXEDFILEINFO lplpBufStructure = new VS_FIXEDFILEINFO(lplpBuffer.getValue());
        lplpBufStructure.read();

        int v1 = (lplpBufStructure.dwFileVersionMS).intValue() >> 16;
        int v2 = (lplpBufStructure.dwFileVersionMS).intValue() & 0xffff;
        int v3 = (lplpBufStructure.dwFileVersionLS).intValue() >> 16;
        int v4 = (lplpBufStructure.dwFileVersionLS).intValue() & 0xffff;
        System.out.println("Version: " + v1 + "." + v2 + "." + v3 + "." + v4);
        return new int[] { v1, v2, v3, v4 };
    }
}
机场等船 2024-12-04 08:23:05

有一个便携式解决方案此处解释(这个问题或多或少是重复的)。

基本上,Windows 可执行文件使用 PE 格式(以及 Linux 的 ELF),您可以使用 pecoff4j 库 来以便携式方式阅读此信息。

There is a portable solution explained here (and this question is more or less a duplicate).

Basically, windows executable use the PE format (and linux ones ELF) and you can use the pecoff4j library to read this information in a portable way.

寄离 2024-12-04 08:23:05

如果是 Windows 程序,请使用 powershell。
该位获取文件版本。
一并完成:

$fileVersion = [System.Diagnostics.FileVersionInfo]::GetVersionInfo($FilePath).FileVersion

Shell out to powershell if it's a windows program.
This bit gets the file version.
One and done:

$fileVersion = [System.Diagnostics.FileVersionInfo]::GetVersionInfo($FilePath).FileVersion
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文