由問題引入
今天卸載了 VS 2015 ,安裝了 VS 2019。使用 VS 2019 打開之前的項目,不做任何項目升級打開后嘗試編譯,提示沒有 Windows SDK 8.1 而無法編譯。
進一步探索,了解到安裝 VS 2015 時,安裝包已經自動帶上了 Windows SDK 8.1,之前的項目選擇的 Target Platform Version (對應於 Windows SDK Version) 就是選的 8.1

基於我對這個屬性還沒了解過,依着謹慎原則還是到官網下載安裝了 Windows SDK 8.1,安裝完畢后可以成功編譯運行了,不過,編輯器始終還是錯誤地報錯:
提示無法打開 Windows.h 等頭文件

在網上找到了靠譜的解釋和解決辦法是:(來自 StackOverflow 的回答)
This happens when you have customized include/library paths in legacy projects. If you added your own additional paths in project properties, VisualStudio 2017 can't automatically figure out base paths when switching between platforms/toolsets - normally it automatically puts correct paths there, but if you added customizations, VS won't touch them.
This is legitimate problem which I ran into myself recently when migrating old project targeted for Windows XP into VS2017. None of the answers or comments listed/linked here so far are helpful. I have all legacy SDKs in VisualStudio 2017 installer, and none of that fixed VS not finding essential includes such as
<windows.h>. In my case the project was using v120 toolset from VS2013, which is superseded by v140_xp in newer VS.After setting correct platform and toolset understood by VS2017, I did the following to resolve the problem:
Open project properties, go to VC++ Directories, for 'Include Directories' and for 'Library Directories', choose
<Inherit from parent or project defaults>. This will remove your additional paths.Click 'Apply'. This will reset include path to something like
$(VC_IncludePath_x86);$(WindowsSdk_71A_IncludePath_x86)(will vary for SDKs).Re-add your extra paths here, or better yet - under C/C++/General -> Additional Include Directories and Linker/General -> Additional Library Directories.
這種情況發生在你的項目屬性路徑設置中有自定義的路徑的情況,如果你往項目屬性設置中加入了額外的路徑, 當切換平台/工具集 設置時 VS2017(或 VS2019)無法自動去刷新分析引用的路徑——通常 VS 會正確分析默認的路徑,當時如果你加了自定義的路徑, VS 就不會這么做了。 ......
在設置好正確的 VS 能識別的平台和工具集后,我做了如下步驟,解決了我的問題:
- 打開項目 Properties ,進入 VC++ Directories ,對於 “Include Directories” 和 “Library Directories” 這兩項,選擇 <Inherit from parent or project defaults>。這樣就把自己自定義加過的路徑去除掉。
 - 點擊 “Apply” 應用,這樣對應的引用的路徑就變成類似 $(VC_IncludePath);$(WindowsSDK_IncludePath); 的設置(不同的 SDK 其值會有不同)
 - 直接在這里重新添加之前自定義的額外的路徑,或者更好的做法是,換個地方設置——在 C/C++/General -> Additional Include Directories 和 Linker/General -> Additional Library Directories 下設置路徑
 
就這樣,報錯問題就解決了。
只不過,我看到很多解決辦法是,既然使用新的 VS 版本后報錯 SDK 8.1 找不到,就直接把 SDK 換成 SDK 10.0 的, 那么問題是:
切換 Windows SDK 版本后,對編譯的程序會產生什么影響嗎?
根據經驗來看,我們在之前的 Windows 版本如 Win7 編譯的程序,是能夠直接運行在后續的版本比如 Win10 的,那如果我是在 Win10 上編譯的程序,是否能夠在 Win7 上正常運行呢?
在我切換了 Target Platform Version(對應於 Windows SDK 的版本)之后,編譯出來的程序,是否還能夠在 Win7 上正常運行呢?
還有就是,VS 項目屬性頁中,Target Platform Version 和 Platform ToolSet(平台工具集) 這兩個屬性又有什么聯系呢?

要理清楚這些問題,就不得不搞清楚,這些設置,到底都是用來決定什么的。
一些基本的概念
先看看 官方文檔 中的解釋:
什么是 Target Platform Version 屬性?
Target Platform Version
Specifies the version of the Windows SDK used to build the project. This property appears only if the project type supports it. You can select 10.0 to specify the latest version of the Windows SDK. If your app can take advantage of features in this Windows SDK version, but can still run on earlier versions without those features, perhaps with some loss of functionality, then the value of this property and the Target Platform Min. Version property might be different. If so, your code should check the version of the platform it's running against at runtime and disable features that aren't available in older platform versions.
這個解釋里只是提到這個屬性指定了 “用於構建項目的 Windows SDK 的版本號”,還說什么如果指定了新的Windows版本的SDK,而程序運行在更早的Windows版本,程序運行時要檢測一下當前運行的 Windows 版本,把舊版本 Windows 不支持的一些功能禁用掉。
按字面上理解,就是肯定了這樣的實踐——如果我指定使用 Windows 10 的 SDK 10,運行在 Windows 7 系統上的話,要注意不去調用 Windows 10 支持而 Windows 7 不支持的接口
也就是說,我指定了 SDK10 的程序,還是可以在 Windows 7 上運行的。(有人確實也已經長期這么干也沒出現過什么問題,來源:msdn 論壇討論)
什么是 Windows SDK 的版本號 ?
Windows SDK Version
For the Windows target platform, this property specifies the version of the Windows SDK that your project requires. When the Visual Studio Installer installs a C++ Workload, it also installs the required parts of the Windows SDK. If you have other Windows SDK versions on your computer, each version installed appears in the dropdown.
To target Windows 7 or Windows Vista, use the value 8.1, since Windows SDK 8.1 is backward compatible to those platforms. When you target an earlier version, define the appropriate value for
_WIN32_WINNTintargetver.h. For Windows 7, that's 0x0601. For more information, see ModifyingWINVERand_WIN32_WINNT.You can install the Windows XP platform toolset included as an optional component in Visual Studio Installer to build Windows XP and Windows 2003 Server projects. For information on how to obtain and use this platform toolset, see Configuring programs for Windows XP. For more information on changing the platform toolset, see How to: Modify the target framework and platform toolset.
Windows SDK (Software Development Kit)包含了開發 Windows 應用程序需要的頭文件和庫文件 (dll 和 lib), 比如 windows.h 頭文件等
當你安裝某個版本的 Visual Studio 時,VS 會自動安裝這個 VS 默認對應的 SDK,比如 VS2015 默認會安裝 SDK 8.1, VS2019 則會默認安裝 SDK 10
新版本的 SDK 一般會有新的 API 或 新的功能特性表現,比如某個版本會有 CreateFile2 接口,而更早的版本可能沒有;
從開發者的編碼的角度看,選擇更新的 Windows SDK 版本號,意味着可能使用到舊版本無法使用的 Windows 接口,這種情況下編譯的程序,自然是在舊的系統版本上運行會出錯。不過並不是說,選擇了新的 SDK 版本(比如 Win10 對應的 SDK 10)開發出的程序就不能在舊的 Windows 版本(比如 Win7)上運行,可能只是失去一些特性。這個說法對應於文檔中的解釋: “You can select 10.0 to specify the latest version of the Windows SDK. If your app can take advantage of features in this Windows SDK version, but can still run on earlier versions without those features”
什么是 Platform ToolSet 的版本號 ?
Platform Toolset
Specifies the toolset used for building the current configuration. This property allows the project to target a different version of the Visual C++ libraries and compiler. By default, Visual Studio C++ projects target the latest toolset installed by Visual Studio. You can choose one of the toolsets installed by several previous versions of Visual Studio instead. Some older toolsets can create executables that run on Windows XP or Vista. For more information on how to change the platform toolset, see How to: Modify the target framework and platform toolset.
這個屬性指定了用來構建程序的編譯器和相關C++庫的版本號的。默認地,構建的 C++ 項目指向 VS 自行安裝的最新的 ToolSet 版本號(比如 VS2015 對應 v140, VS2019 對應 v142)
區別
先使用 StackOverflow 相關的問題 Visual studio platform toolset vs Windows SDK 下的一個說法來總結:
Basically, the toolset is what you build with (compiler, linker, C/C++ libraries), while the SDK is what you build for (target Windows version).
本質上來說,Platform ToolSet(平台工具集)是用來構建程序的,而 Target Platform Version(這里等同於 Windows SDK)是用來面向你要運行的 Windows 版本的
聯系
Target Platform Version 和 Platform ToolSet 這兩個屬性,共同決定了編譯出來的程序能夠運行的目標的 Windows 版本
實際上,決定最終能夠在哪個版本的 Windows 上正常運行的,除了上面兩個屬性,還有在代碼頭文件 targetver.h 中定義的一些宏:_WIN32_WINNT, WINVER,  和 TDDI_VERSION
如在官網解釋如何配置出能夠運行在 Windows XP 上運行的程序的文章所說
Configuring Programs for Windows XP
The toolset supplied in Visual Studio 2019 and later doesn't include support for creating code for Windows XP. Support for Windows XP development is available by using the Visual Studio 2017 v141_xp toolset. You can install the v141_xp toolset as an individual component option in the Visual Studio Installer.
你可以使用 VS2017 編譯出來的 v141_xp 工具集,也可以使用 VS2015 編譯出倆的 v140_xp 工具集
參考鏈接
What does the `Target Platform Version` mean for a VS C++ project?
What version of the SDK should I use in VS2017?
Can I target Windows 7 while using SDK 10.0.15063.0?
Which SDK do I need to ensure Windows 7 compatibility in Visual Studio C++ 2017
Visual studio platform toolset vs Windows SDK
toolSet 特性:
Microsoft C/C++ language conformance by Visual Studio version
Is C++11 available in Visual Studio 2017?
SDK 8.1 下載鏈接: Free: Download the Windows 8.1 SDK
