在运行时获取Win32 UCRT版本?

问题描述 投票:0回答:1

如何在运行时从 ISO C 代码获取 UCRT 版本?我需要 ucrt 版本(不是 Windows 版本)来警告用户某些功能无法与某些有问题的 ucrt 版本一起使用。

winapi crt
1个回答
0
投票

框架挑战:只需静态链接 UCRT。

或者,您可以结合

GetModuleHandle
GetModuleFileName
版本查询功能来查询已加载的UCRT模块的版本。

自包含的 C++ 示例代码,具有最少的错误检查:


#include <array>
#include <expected>
#include <print>
#include <string>
#include <vector>

#define UNICODE
#include <Windows.h>

#pragma comment(lib, "version.lib")

struct UCRTVersion
{
    std::array<std::uint16_t, 4> FileVersion;
    std::array<std::uint16_t, 4> ProductVersion;
};

std::expected<UCRTVersion, HRESULT> GetUCRTVersion()
{
#ifdef _DEBUG
    static constexpr auto DllName = L"ucrtbased.dll";
#else
    static constexpr auto DllName = L"ucrtbase.dll";
#endif

    const HMODULE ucrt{GetModuleHandle(DllName)};
    if (!ucrt)
        return std::unexpected(HRESULT_FROM_WIN32(GetLastError()));

    std::wstring path;
    path.resize_and_overwrite(_MAX_PATH, [ucrt](wchar_t *ptr, const std::size_t size)
    {
        return GetModuleFileName(ucrt, ptr, size);
    });

    const DWORD versionInfoSize{GetFileVersionInfoSize(path.c_str(), nullptr)};
    if (!versionInfoSize)
        return std::unexpected(HRESULT_FROM_WIN32(GetLastError()));

    std::vector<std::byte> versionInfo(versionInfoSize);

    if (!GetFileVersionInfo(path.c_str(), 0, versionInfo.size(), versionInfo.data()))
        return std::unexpected(HRESULT_FROM_WIN32(GetLastError()));

    VS_FIXEDFILEINFO *fixedFileInfo;
    if (!VerQueryValue(versionInfo.data(), L"\\", reinterpret_cast<void **>(&fixedFileInfo), nullptr))
        return std::unexpected(HRESULT_FROM_WIN32(GetLastError()));

    return UCRTVersion{
        {HIWORD(fixedFileInfo->dwFileVersionMS), LOWORD(fixedFileInfo->dwFileVersionMS),
         HIWORD(fixedFileInfo->dwFileVersionLS), LOWORD(fixedFileInfo->dwFileVersionLS)},
        {HIWORD(fixedFileInfo->dwProductVersionMS), LOWORD(fixedFileInfo->dwProductVersionMS),
         HIWORD(fixedFileInfo->dwProductVersionLS), LOWORD(fixedFileInfo->dwProductVersionLS)}
         };
}

int main()
{
    const auto version = GetUCRTVersion();

    if (!version)
    {
        std::println("Failed to get UCRT version: {:8X}", version.error());
        return 1;
    }

    std::println("UCRT version: File = {}.{}.{}.{}, Product = {}.{}.{}.{}",
        version->FileVersion[0],
        version->FileVersion[1],
        version->FileVersion[2],
        version->FileVersion[3],

        version->ProductVersion[0],
        version->ProductVersion[1],
        version->ProductVersion[2],
        version->ProductVersion[3]
        );
    return 0;
}
UCRT version: File = 10.0.22621.2428, Product = 10.0.22621.2428
© www.soinside.com 2019 - 2024. All rights reserved.