微信公众号搜"智元新知"关注
微信扫一扫可直接关注哦!

从dll函数调用正确获取Windows版本?

假设我正在写一个多用途的dll,其中包含一个获取操作系统版本的函数

void get_os_version(DWORD *major,DWORD *minor) { OsveRSIONINFOEX osvi; ZeroMemory(&osvi,sizeof(OsveRSIONINFOEX)); osvi.dwOsversionInfoSize = sizeof(OsveRSIONINFOEX); // deprecated but easier to use for this example's sake GetVersionEx((OsveRSIONINFO*)&osvi); *major = osvi.dwMajorVersion; *minor = osvi.dwMinorVersion; }

对于Windows版本高于Windows 8的版本,需要embedded一个指定受支持平台的清单(请参阅此处的详细信息)。

所以我在编译时使用/MANIFEST:NO标志禁用自动生成我的dll文件/MANIFEST:NO ,而是添加下面的清单:

<?xml version="1.0" encoding="UTF-8" standalone="yes"?> <assembly xmlns="urn:schemas-microsoft-com:asm.v1" manifestVersion="1.0"> <trustInfo xmlns="urn:schemas-microsoft-com:asm.v3"> <security> <requestedPrivileges> <requestedExecutionLevel level="asInvoker" uiAccess="false"></requestedExecutionLevel> </requestedPrivileges> </security> </trustInfo> <compatibility xmlns="urn:schemas-microsoft-com:compatibility.v1"> <application> <!-- Windows 10 --> <supportedOS Id="{8e0f7a12-bfb3-4fe8-b9a5-48fd50a15a9a}"/> <!-- Windows 8.1 --> <supportedOS Id="{1f676c76-80e1-4239-95bb-83d0f6d0da78}"/> <!-- Windows Vista --> <supportedOS Id="{e2011457-1546-43c5-a5fe-008deee3d3f0}"/> <!-- Windows 7 --> <supportedOS Id="{35138b9a-5d96-4fbd-8e2d-a2440225f93a}"/> <!-- Windows 8 --> <supportedOS Id="{4a2f28e3-53b9-4441-ba9c-d69d4a4a6e38}"/> </application> </compatibility> </assembly>

,使用mt工具:

可以编辑InstallShield setup.exe的清单文件吗?

Win32:build议显式应用程序的testing与部署

阅读应用程序的清单文件

“以pipe理员身份运行”和带有requireAdministrator的清单之间有什么区别?

强制Windows加载DLL的地方,以便内存最小碎片

mt -manifest Getosversion.dll.manifest -outputresource:Getosversion.dll;#2

一切顺利,没有错误。 现在要使用DLL,我创build一个简单的App.exe加载DLL并调用它的function:

int _tmain(int argc,_TCHAR* argv[]) { DWORD major,minor; get_os_version(&major,&minor); printf("%d.%dn",major,minor); return 0; }

但是在Windows 10上运行App.exe时,出乎意料的是,输出结果是:

6.2

,这是Windows 8的版本。如果我也将清单应用到App.exe:

mt -manifest Getosversion.dll.manifest -outputresource:App.exe;#1

,产出是预期的:

10.0

为什么发生这种情况? 我可以解决这个问题,而无需向可执行文件添加清单?

我不能控制将使用我的库的应用程序,但我仍然要正确检索操作系统版本。

将清单embedded到exe文件失败,参数无效

在清单中指定公钥标记

我如何创build一个清单文件指向我的可执行文件/插件到我的特定版本的Qt.dll?

在同一个进程中加载​​一组DLL的多个副本

应用程序签名/validation

确定实际操作系统版本的另一种方法记录在MSDN页面获取系统版本”上 :

若要获取操作系统的完整版本号,请在其中一个系统DLL(如coreel32.dll)上调用GetFiLeversionInfo函数,然后调用VerQueryValue以获取\StringFileInfo\<lang><codepage>\ProductVersion子块文件版本信息。

这将从DLL工作,而不管应用程序是否具有清单。

(当然,GetVersionInfo和朋友不会返回实际的操作系统版本是有原因的:程序员有一个恶意的滥用这个信息的倾向,你应该认真考虑在你的DLL中提供这样一个函数是否真的是一个好的理念。)

应用程序(可执行)清单MSDN页面相当明确地描述了这个问题:

Windows中引入的应用程序(可执行)清单的兼容性部分可帮助操作系统确定应用程序旨在针对的Windows版本。

如果清单不是可执行清单,则兼容性(以及其他应用程序设置,如DPI知晓)将被完全忽略。 这是有道理的,因为否则在不同dll的清单之间会出现明显的冲突。

作为接受答案的补充,以下是任何想要实现它的人的一些起始代码

#pragma comment(lib,"version") static void print_version() { DWORD buffer_size = GetFiLeversionInfoSize(_T("kernel32.dll"),NULL); if (buffer_size == 0) { // get error from GetLastError() return; } VOID *buffer = malloc(buffer_size); if (buffer == NULL) { // out of memory return; } if (!GetFiLeversionInfo(_T("kernel32.dll"),buffer_size,buffer)) { goto error; } VS_FIXEDFILEINFO *version = NULL; UINT version_len = 0; if (!VerQueryValue(buffer,_T("\"),(LPVOID*)&version,&version_len)) { goto error; } _tprintf(_T("Version is: %u.%un"),HIWORD(version->dwProductVersionMS),LOWORD(version->dwProductVersionMS)); error: free(buffer); }

而Windows 10的输出是:

Version is 10.0

清单中的大多数节点都适用于整个过程,只能从主.exe模块读取:

Windows中引入的应用程序(可执行)清单的兼容性部分可帮助操作系统确定应用程序旨在针对的Windows版本。

您应该使用GetProcAddress和CoCreateInstance来检查您需要的功能是否存在,而不是Windows版本。

通过一些小小的工作, GetProcAddress也可以用来确定你真正需要的信息。 查看MSDN上各种kernel32和user32函数的最低操作系统版本…

版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 [email protected] 举报,一经查实,本站将立刻删除。

相关推荐