Search code examples
c++cwindowswinapi

How to get the Windows SDK version number a program is compiling with at compile time


I'd like to get the Windows SDK version number, a program is being compiled with at compile time, like 10.0.22621.0.

The closest I was able to achieve is something like that:

#include <iostream>
#include <sstream>
#include <windows.h>

std::string NTDDIToFriendlyVersion(DWORD ntddiVersion) {
  DWORD major = (ntddiVersion & 0xFF000000) >> 24;
  DWORD minor = (ntddiVersion & 0x00FF0000) >> 16;
  DWORD build = (ntddiVersion & 0x0000FFFF);

  std::ostringstream oss;
  oss << major << "." << minor << "." << build;
  return oss.str();
}

int main() {
  std::cout << "WDK_NTDDI_VERSION is: " << std::hex << WDK_NTDDI_VERSION <<
            " (" << NTDDIToFriendlyVersion(WDK_NTDDI_VERSION) << ")\n";
}

which basically just dissects the WDK_NTDDI_VERSION constant defined in C:\Program Files (x86)\Windows Kits\10\Include\10.0.22621.0\shared\sdkddkver.h.

Output I get:

NTDDI_VERSION is: a00000c (10.0.12)

I'd rather get the 10.0.22621.0 instead of 10.0.12


I tagged both C and C++ because I don't really care.


Solution

  • If you're running on MsBuild and/or VisualStudio you can add something like this to your .vcxproj:

    <Project>
        ...
        <PropertyGroup>
          <BuildDependsOn>
            CreateSDKInfo;$(BuildDependsOn)
          </BuildDependsOn>
        </PropertyGroup>
        
        <Target Name="CreateSDKInfo">
          <PropertyGroup>
            <SDKInfo>
      #define COMPILATION_INCLUDEPATH "$(IncludePath.Replace('\', '\\'))"
      #define W10_SDK_INSTALLATION_FOLDER "$([System.String]::new($(registry:HKEY_LOCAL_MACHINE\SOFTWARE\WOW6432Node\Microsoft\Microsoft SDKs\Windows\v10.0@InstallationFolder)).Replace('\', '\\'))"
      #define W10_SDK_PRODUCT_NAME "$(registry:HKEY_LOCAL_MACHINE\SOFTWARE\WOW6432Node\Microsoft\Microsoft SDKs\Windows\v10.0@ProductName)"
      #define W10_SDK_PRODUCT_VERSION "$(registry:HKEY_LOCAL_MACHINE\SOFTWARE\WOW6432Node\Microsoft\Microsoft SDKs\Windows\v10.0@ProductVersion)"
            </SDKInfo>
          </PropertyGroup>
          <WriteLinesToFile File="$(ProjectDir)SDKInfo.h" Overwrite="true" Lines="$(SDKInfo)" />
        </Target>
       ...
    </Project>
        
    

    This will create a SDKInfo.h file in your project (before compilation targets) that will define the COMPILATION_INCLUDEPATH identifier and its value will be a concatenated list of included paths at project compile time.

    This contains exact SDK paths. You could post parse it at runtime or define a more complex task (this can be done inline with C# code) to include only what you need at compilation time. Here is what this file looks like for me:

    #define COMPILATION_INCLUDEPATH "C:\\Program Files\\Microsoft Visual Studio\\2022\\Professional\\VC\\Tools\\MSVC\\14.43.34808\\include;;C:\\Program Files\\Microsoft Visual Studio\\2022\\Professional\\VC\\Tools\\MSVC\\14.43.34808\\atlmfc\\include;;C:\\Program Files\\Microsoft Visual Studio\\2022\\Professional\\VC\\Auxiliary\\VS\\include;;C:\\Program Files (x86)\\Windows Kits\\10\\Include\\10.0.26100.0\\ucrt;;;C:\\Program Files (x86)\\Windows Kits\\10\\Include\\10.0.26100.0\\um;C:\\Program Files (x86)\\Windows Kits\\10\\Include\\10.0.26100.0\\shared;C:\\Program Files (x86)\\Windows Kits\\10\\Include\\10.0.26100.0\\winrt;PreventSdkUapPropsAssignment;C:\\Program Files (x86)\\Windows Kits\\NETFXSDK\\4.8.1\\Include\\um;"
    #define W10_SDK_INSTALLATION_FOLDER "C:\\Program Files (x86)\\Windows Kits\\10\\"
    #define W10_SDK_PRODUCT_NAME "Microsoft Windows SDK for Windows 10.0.26100"
    #define W10_SDK_PRODUCT_VERSION "10.0.26100"
    

    As a bonus, I've also added the latest installed SDK installed path and version (it can be different from what your project uses) from the registry.