You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

从Windows资源文件提取版本信息结果异常的技术求助

从RC资源提取版本信息输出异常的问题分析与修复

环境

Win10、C++20、MSVS Community 17.8.3

问题描述

我尝试从Visual Studio资源编辑器创建并编译生成的.res文件(由.rc文件编译而来,版本资源创建路径:解决方案资源管理器>资源文件>添加>资源>版本)中提取文件版本信息。.rc文件里FILEVERSION和PRODUCTVERSION均设为1, 0, 0, 1,但自己编写的代码运行后输出结果完全不符合预期,编译链接无错误警告。

原代码

#include <iostream>
#include <format>
#include "resource.h"

using std::cout;
using std::cerr;
using std::endl;
using std::format;

int main() {
    struct VersionInfo {
        DWORD dwFileVersionMS;
        DWORD dwFileVersionLS;
        DWORD dwProductVersionMS;
        DWORD dwProductVersionLS;
    };

    HRSRC hVersionResource = FindResource(NULL, MAKEINTRESOURCE(1), RT_VERSION);

    if (!hVersionResource) {
        cerr << "Error: Could not find version resource." << endl;
        return -1;
    }

    HGLOBAL hVersionData = LoadResource(NULL, hVersionResource);

    if (!hVersionData) {
        cerr << "Error: Could not load version resource." << endl;
        return -1;
    }

    LPVOID pVersionData = LockResource(hVersionData);

    if (!pVersionData) {
        cerr << "Error: Could not lock version resource." << endl;
        return -1;
    }

    VersionInfo* versionInfo = (VersionInfo*)pVersionData;

    cout << format("File version: {}.{}.{}.{}\n",
        HIWORD(versionInfo->dwFileVersionMS),
        LOWORD(versionInfo->dwFileVersionMS),
        HIWORD(versionInfo->dwFileVersionLS),
        LOWORD(versionInfo->dwFileVersionLS));

    cout << format("Product version: {}.{}.{}.{}\n",
        HIWORD(versionInfo->dwProductVersionMS),
        LOWORD(versionInfo->dwProductVersionMS),
        HIWORD(versionInfo->dwProductVersionLS),
        LOWORD(versionInfo->dwProductVersionLS));

    FreeResource(hVersionData);
    return 0;
}

实际输出

File version: 52.792.86.0
Product version: 95.83.69.86

问题原因

你忽略了RT_VERSION资源的实际结构:

  • RT_VERSION资源的起始部分并不是你自定义的VersionInfo结构体,而是系统定义的VS_VERSION_INFO结构,其中包含了VS_FIXEDFILEINFO和其他可选的字符串信息块。直接强制转换会读取到错误的内存数据,导致输出异常。
  • 必须通过VerQueryValue函数来定位到VS_FIXEDFILEINFO的正确位置,而不是直接强转资源指针。

修复后的代码

#include <iostream>
#include <format>
#include <windows.h>
#include "resource.h"

using std::cout;
using std::cerr;
using std::endl;
using std::format;

int main() {
    // 查找版本资源
    HRSRC hVersionResource = FindResource(NULL, MAKEINTRESOURCE(1), RT_VERSION);
    if (!hVersionResource) {
        cerr << "错误:无法找到版本资源。" << endl;
        return -1;
    }

    // 加载资源
    HGLOBAL hVersionData = LoadResource(NULL, hVersionResource);
    if (!hVersionData) {
        cerr << "错误:无法加载版本资源。" << endl;
        return -1;
    }

    LPVOID pVersionData = LockResource(hVersionData);
    if (!pVersionData) {
        cerr << "错误:无法锁定版本资源。" << endl;
        return -1;
    }

    // 定位VS_FIXEDFILEINFO结构
    VS_FIXEDFILEINFO* pFixedFileInfo = nullptr;
    UINT infoSize = 0;
    if (!VerQueryValue(pVersionData, L"\\", reinterpret_cast<LPVOID*>(&pFixedFileInfo), &infoSize)) {
        cerr << "错误:无法查询版本信息。" << endl;
        return -1;
    }

    // 提取并格式化版本号
    cout << format("文件版本: {}.{}.{}.{}\n",
        HIWORD(pFixedFileInfo->dwFileVersionMS),
        LOWORD(pFixedFileInfo->dwFileVersionMS),
        HIWORD(pFixedFileInfo->dwFileVersionLS),
        LOWORD(pFixedFileInfo->dwFileVersionLS));

    cout << format("产品版本: {}.{}.{}.{}\n",
        HIWORD(pFixedFileInfo->dwProductVersionMS),
        LOWORD(pFixedFileInfo->dwProductVersionMS),
        HIWORD(pFixedFileInfo->dwProductVersionLS),
        LOWORD(pFixedFileInfo->dwProductVersionLS));

    // 现代Win32系统中无需手动调用FreeResource,系统会自动管理资源
    return 0;
}

说明

  • 修复后的代码使用VerQueryValue定位根节点\对应的VS_FIXEDFILEINFO结构,这是系统定义的标准版本信息结构,能正确读取到资源中设置的版本号。
  • 全程无需手动分配/释放内存,完全基于已加载的资源数据操作,符合你避免原生new[]/delete[]的需求。
  • 注意:在现代Win32环境下,FreeResource函数已经不需要手动调用,系统会自动处理资源释放。

内容的提问来源于stack exchange,提问作者SimpleCoder

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.03 11:18:12