programming first create application app c++ windows winapi

c++ - first - Detectando la versión de Windows 10



windows desktop (3)

La forma más directa de recuperar la verdadera versión del sistema operativo es llamar a RtlGetVersion . Es lo que GetVersionEx y VerifyVersionInfo , pero no emplea las cuñas de compatibilidad.

Puede usar el DDK (#incluyendo <ntddk.h> y vincular contra NtosKrnl.lib desde el modo kernel, o ntdll.lib desde el modo de usuario), o usar el enlace dinámico en tiempo de ejecución como en el siguiente fragmento:

typedef LONG NTSTATUS, *PNTSTATUS; #define STATUS_SUCCESS (0x00000000) typedef NTSTATUS (WINAPI* RtlGetVersionPtr)(PRTL_OSVERSIONINFOW); RTL_OSVERSIONINFOW GetRealOSVersion() { HMODULE hMod = ::GetModuleHandleW(L"ntdll.dll"); if (hMod) { RtlGetVersionPtr fxPtr = (RtlGetVersionPtr)::GetProcAddress(hMod, "RtlGetVersion"); if (fxPtr != nullptr) { RTL_OSVERSIONINFOW rovi = { 0 }; rovi.dwOSVersionInfoSize = sizeof(rovi); if ( STATUS_SUCCESS == fxPtr(&rovi) ) { return rovi; } } } RTL_OSVERSIONINFOW rovi = { 0 }; return rovi; }

En caso de que necesite información adicional, puede pasar una estructura RTL_OSVERSIONINFOEXW en lugar de la estructura RTL_OSVERSIONINFOW (asignando correctamente el miembro dwOSVersionInfoSize ).

Esto devuelve el resultado esperado en Windows 10, incluso cuando no hay un manifiesto adjunto.

Por otro lado, se acepta comúnmente como una mejor solución para proporcionar diferentes implementaciones basadas en las características disponibles en lugar de las versiones del sistema operativo.

Mi objetivo es detectar Windows 10 en mi código, que tiene que funcionar multiplataforma, así como en diferentes versiones de Windows (al menos 7 y superiores). Windows proporciona IsWindows10OrGreater() para abordar este problema, pero hay otro problema, esta función no está presente en versiones anteriores de Windows.

Encontrará innumerables blogs y preguntas SO con respecto a esto, así como la locura manifiesta donde funciones como esta y getversion y otros devuelven alguna versión diferente en lugar de la correcta.

Por ejemplo, en mi máquina: el método IsWindows10OrGreater() no se compila (tendría que instalar Win10 SDK), e IsWindowsVersionOrGreater() informa 6 como versión principal.

Entonces, ¿hay alguna forma sensata de múltiples versiones que pueda resolver este problema?


Puede leer el número de compilación real del registro y luego deducir la versión de Windows de él. Su aplicación no necesita tener un manifiesto para este trabajo: en mi máquina, detecta correctamente el número de compilación del sistema operativo como 10586. Por ejemplo:

#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, &currentVersion) != 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; }


IsWindows10OrGreater() de VersionHelpers.h

Consulte las notas en las funciones de Version Helper en MSDN

File VersionHelpers.h se entrega con Windows 10 SDK, pero también funcionará en versiones anteriores. Simplemente cópielo en su entorno de desarrollo.

Es solo una pequeña VerSetConditionMask definida solo con encabezado, que usa las funciones VerSetConditionMask y VerifyVersionInfoW , ambas disponibles en WinAPI desde Windows 2000.

Upd Si no puede incluir el archivo de manifiesto con su código fuente, puede usar un hack simple: simplemente obtenga una versión de cualquier dll del sistema, por ejemplo, kernel32.dll usando la función GetFileVersionInfo .