现在,GetVersion会被报告成“过期函数”了。也许还能用,但(据MSDN说)起码在Win10上是别指望得到预期的结果了。道理也很简单,Win10都搞定期升级了,版本号规则肯定也和之前不一样了,你还指望这么老的函数能兼容么?
别痴心妄想了,GetVersionEx也一样过期。那么,眼下有什么好办法吗?
一般来说,拿Windows版本号可能有两种用途:
- 我想看看你Windows版本达到我要求没。
- 我就是想知道你Windows版本号是多少。
对于前者,微软现在在MSDN上是这样推荐的:它做了一组Version Helper functions,你如果想知道当前Windows的版本是不是某个特定的发行版,调这组函数就可以。我们来看看这组函数中三个典型:
- IsWindowsXPOrGreater
- IsWindowsXPSP3OrGreater
- IsWindowsServer
不需要更多说明,我们从名字中就可以看出,这组函数可以用于判断Windows的大版本,Service Pack的版本(结合大版本),以及能知道是不是服务器版操作系统。通常情况下,这些函数大概是够了。
但是,有的时候我们并不关心版本号高低,我们只是想要一个版本号(例如记录日志时)而已。微软对此的建议是:用GetFileVersionInfo去获取一个系统DLL(例如Kernel32.dll)的文件版本号(原文看这里)。
相关的代码虽然能找到,MSDN上也有官方例子(有点小Bug),但比起一行GetVersion来代码量实在是不能算很少。由此可见,处理“过期函数”真的没有想象中那么容易。最后我还是提供一下我从项目代码中挖出来的一个实现吧。别照抄,如果你不想引入STL的话:
wstring GetOSVersion(const wstring& strWinSysDir) const { wstring strWinSysFilePath = strWinSysDir + L"\\Kernel32.dll"; DWORD dwVerInfoSize = GetFileVersionInfoSize(strWinSysFilePath.c_str(), nullptr); if (dwVerInfoSize) { vector<byte> vecVerData; vecVerData.resize(dwVerInfoSize); if (GetFileVersionInfo(strWinSysFilePath.c_str(), NULL, dwVerInfoSize, &vecVerData[0])) { LPCVOID pBlock = &vecVerData[0]; UINT cbTranslate; TCHAR SubBlock[50]; struct LANGANDCODEPAGE { WORD wLanguage; WORD wCodePage; } *lpTranslate; // Read the list of languages and code pages. VerQueryValue(pBlock, TEXT("\\VarFileInfo\\Translation"), (LPVOID*)&lpTranslate, &cbTranslate); // Read the file version for first language and code page. for (size_t i = 0; i < (cbTranslate / sizeof(struct LANGANDCODEPAGE)); ++i) { StringCchPrintf(SubBlock, sizeof(SubBlock) / sizeof(TCHAR), L"\\StringFileInfo\\%04x%04x\\ProductVersion", lpTranslate[i].wLanguage, lpTranslate[i].wCodePage); LPVOID lpBuffer = nullptr; UINT dwBytes; if (VerQueryValue(pBlock, SubBlock, &lpBuffer, &dwBytes) && lpBuffer) { wstring strOSVersion(reinterpret_cast<tchar>(lpBuffer)); return strOSVersion; } } } } return L""; }
最近迷之高产。
回复删除每天中午除了进餐剩下来的时间从加班改为写Blog,并且前段时间的加班积累了一些素材。
删除