如何在运行时通过ISO C代码获取Win32 UCRT版本?
如何在运行时通过ISO C代码获取UCRT版本?
要在运行时获取UCRT(Universal C Runtime)的版本,核心思路是读取UCRT核心库文件的版本信息——UCRT的版本与其对应的DLL文件版本完全一致。以下是基于ISO C标准编写的实现代码,无需依赖Windows特定的头文件:
实现代码
#include <stdio.h> #include <stdlib.h> #include <string.h> // 标准C兼容的Windows API声明(仅使用标准C类型) extern void* LoadLibraryA(const char* lpLibFileName); extern void* GetProcAddress(void* hModule, const char* lpProcName); extern void* GetModuleHandleA(const char* lpModuleName); extern unsigned long GetFileVersionInfoSizeA(const char* lptstrFilename, unsigned long* lpdwHandle); extern int GetFileVersionInfoA(const char* lptstrFilename, unsigned long dwHandle, unsigned long dwLen, unsigned char* lpData); extern int VerQueryValueA(const unsigned char* pBlock, const char* lpSubBlock, void** lplpBuffer, unsigned int* puLen); extern unsigned long GetModuleFileNameA(void* hModule, char* lpFilename, unsigned long nSize); extern void FreeLibrary(void* hModule); // 存储文件版本信息的结构体(标准C兼容) typedef struct { unsigned long dwSignature; unsigned long dwStrucVersion; unsigned long dwFileVersionMS; unsigned long dwFileVersionLS; unsigned long dwProductVersionMS; unsigned long dwProductVersionLS; unsigned long dwFileFlagsMask; unsigned long dwFileFlags; unsigned long dwFileOS; unsigned long dwFileType; unsigned long dwFileSubtype; unsigned long dwFileDateMS; unsigned long dwFileDateLS; } VS_FIXEDFILEINFO; #define MAX_PATH 260 int get_ucrt_version(unsigned int* major, unsigned int* minor, unsigned int* build, unsigned int* revision) { // 初始化输出参数 if (major) *major = 0; if (minor) *minor = 0; if (build) *build = 0; if (revision) *revision = 0; // 获取UCRT核心模块句柄(优先Windows 10+的ucrtbase.dll,兼容旧系统的备用模块) void* ucrt_module = GetModuleHandleA("ucrtbase.dll"); if (!ucrt_module) { ucrt_module = GetModuleHandleA("api-ms-win-crt-runtime-l1-1-0.dll"); if (!ucrt_module) return -1; } // 获取模块文件路径 char path[MAX_PATH]; if (GetModuleFileNameA(ucrt_module, path, sizeof(path)) == 0) { return -2; } // 获取文件版本信息所需的内存大小 unsigned long dummy; unsigned long version_size = GetFileVersionInfoSizeA(path, &dummy); if (version_size == 0) { return -3; } // 分配内存存储版本信息 unsigned char* version_data = (unsigned char*)malloc(version_size); if (!version_data) { return -4; } // 读取文件版本信息 if (!GetFileVersionInfoA(path, 0, version_size, version_data)) { free(version_data); return -5; } // 查询固定版本信息结构 VS_FIXEDFILEINFO* fixed_info; unsigned int info_size; if (!VerQueryValueA(version_data, "\\", (void**)&fixed_info, &info_size)) { free(version_data); return -6; } // 拆分版本号:主版本、次版本、构建号、修订号 if (major) *major = (fixed_info->dwFileVersionMS >> 16) & 0xFFFF; if (minor) *minor = fixed_info->dwFileVersionMS & 0xFFFF; if (build) *build = (fixed_info->dwFileVersionLS >> 16) & 0xFFFF; if (revision) *revision = fixed_info->dwFileVersionLS & 0xFFFF; // 清理资源 free(version_data); return 0; } // 使用示例 int main() { unsigned int major, minor, build, revision; int result = get_ucrt_version(&major, &minor, &build, &revision); if (result == 0) { printf("UCRT Version: %u.%u.%u.%u\n", major, minor, build, revision); // 示例:检查版本是否低于存在缺陷的版本(如10.0.17134.0) if (major < 10 || (major == 10 && minor < 0) || (major == 10 && minor == 0 && build < 17134)) { printf("Warning: Some features may not work correctly with this UCRT version.\n"); } } else { printf("Failed to retrieve UCRT version. Error code: %d\n", result); } return 0; }
关键说明
- ISO C兼容性:代码仅使用标准C语法和类型,通过
extern声明Windows API,避免依赖非标准头文件或扩展。 - UCRT模块适配:优先尝试
ucrtbase.dll(Windows 10+的主UCRT库),若失败则兼容旧系统的api-ms-win-crt-runtime-l1-1-0.dll。 - 版本号解读:UCRT版本采用
主版本.次版本.构建号.修订号格式,例如10.0.22621.3527,需以DLL文件版本为准,而非Windows系统版本。 - 错误处理:返回的错误码可用于定位问题(如模块未找到、路径获取失败等)。
内容的提问来源于stack exchange,提问作者Roland Mainz
相关产品推荐
相关产品推荐

