The version of the Windows SDK used doesn't actually matter that much. All that matters is that anything required to be used in any application is available in the SDK. Since there was never any mention of the circumstances that the SDK will be used under, I will provide a C/C++ view on this.
If Windows 10 is the target, then there isn't anything wrong with using the latest Windows 11 SDK. For C/C++ development, Microsoft are pretty good at using the preprocessor to limit what function definitions are available:
//Extracted from Appmodel.h
#if NTDDI_VERSION >= NTDDI_WIN10_19H1
typedef enum PackagePathType
{
PackagePathType_Install = 0,
PackagePathType_Mutable = 1,
PackagePathType_Effective = 2,
#if NTDDI_VERSION >= NTDDI_WIN10_VB
PackagePathType_MachineExternal = 3,
PackagePathType_UserExternal = 4,
PackagePathType_EffectiveExternal = 5
#endif // NTDDI_VERSION >= NTDDI_WIN10_VB
} PackagePathType;
WINBASEAPI
_Success_(return == ERROR_SUCCESS)
LONG
WINAPI
GetPackagePathByFullName2(
_In_ PCWSTR packageFullName,
_In_ PackagePathType packagePathType,
_Inout_ UINT32* pathLength,
_Out_writes_opt_(*pathLength) PWSTR path
);
WINBASEAPI
_Success_(return == ERROR_SUCCESS)
LONG
WINAPI
GetStagedPackagePathByFullName2(
_In_ PCWSTR packageFullName,
_In_ PackagePathType packagePathType,
_Inout_ UINT32* pathLength,
_Out_writes_opt_(*pathLength) PWSTR path
);
WINBASEAPI
_Success_(return == ERROR_SUCCESS)
LONG
WINAPI
GetCurrentPackageInfo2(
_In_ const UINT32 flags,
_In_ PackagePathType packagePathType,
_Inout_ UINT32* bufferLength,
_Out_writes_bytes_opt_(*bufferLength) BYTE* buffer,
_Out_opt_ UINT32* count
);
WINBASEAPI
_Success_(return == ERROR_SUCCESS)
LONG
WINAPI
GetCurrentPackagePath2(
_In_ PackagePathType packagePathType,
_Inout_ UINT32* pathLength,
_Out_writes_opt_(*pathLength) PWSTR path
);
#endif // NTDDI_VERSION >= NTDDI_WIN10_19H1
It requires a little bit of understanding what the various NTDDI version codes mean, but if NTDDI_VERSION is defined to be a lower version, then this will restrict function definitions to only those available on the versions of Windows that you wish to target.
The libraries only cause a dependency if a function is used and the linker links the import library for it. However, with care and techniques such as delay loading or runtime dynamic linking then it is also possible to use a newer SDK to target an older version of Windows, and make newer functionality available when it is detected.
For the tooling, using the newest possible is often the best option. This is why some projects use the Windows SDK Build Tools NuGet package. This decouples some tools from the SDK.
To give a small example of what I mean. I have an application with the project properties set as:
This signifies that the project is using the latest version of the SDK. On my system, this is the Windows 11 24H2 SDK (10.0.26100.1742). However, this project targets Windows 10 1809 (10.0.17763.0) as the baseline. It does use Windows 11 behaviour though, and this actually requires that I build it with the Windows 11 SDK.
bool init_dd()
{
s_appmodel_lib = LoadLibraryExW(apiset_name_w, nullptr, LOAD_LIBRARY_SEARCH_SYSTEM32);
if (s_appmodel_lib == nullptr)
{
return false;
}
ptrTryCreatePackageDependency = reinterpret_cast<TryCreatePackageDependency_ptr_t>(GetProcAddress(s_appmodel_lib, "TryCreatePackageDependency"));
ptrAddPackageDependency = reinterpret_cast<AddPackageDependency_ptr_t>(GetProcAddress(s_appmodel_lib, "AddPackageDependency"));
ptrRemovePackageDependency = reinterpret_cast<RemovePackageDependency_ptr_t>(GetProcAddress(s_appmodel_lib, "RemovePackageDependency"));
ptrDeletePackageDependency = reinterpret_cast<DeletePackageDependency_ptr_t>(GetProcAddress(s_appmodel_lib, "DeletePackageDependency"));
return true;
}
This is an example of how I reference the Dynamic Dependencies API. Essentially, if the LoadLibraryEx fails then this indicates that the Windows 11 Dynamic Dependencies API is unavailable, so I fall back, otherwise I use runtime dynamic linking to set function pointers to point at the functions and then use these function pointers when I wish to use them.
Visual Studio itself is in on this knowledge, this is why it defaults to installing the latest non preview* SDK by default.
The advice normally is, unless there is a specific bug that causes problems, just use the latest SDK. There are some specific instances where it is obvious that a specific version of the SDK must be used, but these are should be rarer.*There can be quirks related to when packages are updated. Currently, Windows 11 24H2's SDK isn't default, Windows 11 22H2's is. This should become default either when Visual Studio 17.12 is released, or when the successor is released.