私の目的は、クロスプラットフォームだけでなく、Windowsのさまざまなバージョン(少なくとも7以降)で動作する必要があるコードでWindows 10を検出することです。 Windowsはこの問題に取り組むためにIsWindows10OrGreater()
を提供していますが、これには別の問題があり、この関数は以前のバージョンのWindowsには存在しません。
無数のブログとSOこれに関する質問だけでなく、このような関数やgetversionなどの関数が正しいバージョンではなく別のバージョンを返すマニフェストの狂気を見つけるでしょう。
たとえば、私のマシンでは、メソッドIsWindows10OrGreater()
はコンパイルできません(Win10 SDKをインストールする必要があります)。また、IsWindowsVersionOrGreater()
は、メジャーバージョンとして6
を報告します。
それで、この問題を解決できる健全なマルチバージョンの方法はありますか?
IsWindows10OrGreater()
VersionHelpers.h
から
MSDNの Version Helper functionsでメモを確認してください
ファイルVersionHelpers.h
はWindows 10 SDKに付属していますが、以前のバージョンでも機能します。開発環境にコピーするだけです。
これは、ヘッダーのみが定義された小さなlibであり、VerSetConditionMask
およびVerifyVersionInfoW
関数を使用します。どちらもWindows 2000以降のWinAPIで使用できます。
Updソースコードにマニフェストファイルを含めることができない場合は、単純なハックを使用できます。たとえば、kernel32.dll
などのシステムDLLのバージョンを取得するだけですGetFileVersionInfo
関数を使用します。
レジストリから実際のビルド番号を読み取り、それからWindowsバージョンを推測できます。アプリケーションは、この作業のためにマニフェストを持つ必要はありません。私のマシンでは、OSビルド番号を10586として正しく検出します。次に例を示します。
#include <Windows.h>
#include <sstream>
struct HKeyHolder
{
private:
HKEY m_Key;
public:
HKeyHolder() :
m_Key(nullptr)
{
}
HKeyHolder(const HKeyHolder&) = delete;
HKeyHolder& operator=(const HKeyHolder&) = delete;
~HKeyHolder()
{
if (m_Key != nullptr)
RegCloseKey(m_Key);
}
operator HKEY() const
{
return m_Key;
}
HKEY* operator&()
{
return &m_Key;
}
};
bool IsRunningOnWindows10()
{
HKeyHolder currentVersion;
if (RegOpenKeyExW(HKEY_LOCAL_MACHINE, LR"(SOFTWARE\Microsoft\Windows NT\CurrentVersion)", 0, KEY_QUERY_VALUE, ¤tVersion) != ERROR_SUCCESS)
return false;
DWORD valueType;
BYTE buffer[256];
DWORD bufferSize = 256;
if (RegQueryValueExW(currentVersion, L"CurrentBuild", nullptr, &valueType, buffer, &bufferSize) != ERROR_SUCCESS)
return false;
if (valueType != REG_SZ)
return false;
int version;
std::wistringstream versionStream(reinterpret_cast<wchar_t*>(buffer));
versionStream >> version;
return version > 9800;
}