假设我正在写一个多用途的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
为什么发生这种情况? 我可以解决这个问题,而无需向可执行文件添加清单?
我不能控制将使用我的库的应用程序,但我仍然要正确检索操作系统版本。
在清单中指定公钥标记
我如何创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] 举报,一经查实,本站将立刻删除。