C++/WinRT 的新功能What's new in C++/WinRT

隨著 C++/WinRT 後續版本的發行,本主題說明新功能和變更內容。As subsequent versions of C++/WinRT are released, this topic describes what's new, and what's changed.

2020 年 3 月為止的最新改良/新增彙總套件Rollup of recent improvements/additions as of March 2020

組建時間縮短達 23%Up to 23% shorter build times

C++/WinRT 和 C++ 編譯器小組已共同合作,盡可能縮短組建時間。The C++/WinRT and C++ compiler teams have collaborated to do everything possible to shorten build times. 我們仔細研究編譯器分析,以找出重組 C++/WinRT 內部結構的方法,來協助 C++ 編譯器消除額外的編譯時間,以及改進 C++ 編譯器本身以處理 C++/WinRT 程式庫的方法。We've pored over compiler analytics to figure out how the internals of C++/WinRT can be restructured to help the C++ compiler eliminate compile-time overhead, as well as how the C++ compiler itself can be improved to handle the C++/WinRT library. C++/WinRT 已針對編譯器最佳化;而編譯器也已針對 C++/WinRT 最佳化。C++/WinRT has been optimized for the compiler; and the compiler has been optimized for C++/WinRT.

以最差的情況為例,組建預先編譯的標頭 (PCH),其中包含每個單一 C++/WinRT 投影命名空間標頭。Let's take for example the worst case scenario of building a pre-compiled header (PCH) that contains every single C++/WinRT projection namespace header.

版本Version PCH 大小 (位元組)PCH size (bytes) 次數Time (s)
7 月的 C++/WinRT,含 Visual C++ 16.3C++/WinRT from July, with Visual C++ 16.3 3,004,104,6323,004,104,632 3131
C++/WinRT 2.0.200316.3 版,含 Visual C++ 16.5version 2.0.200316.3 of C++/WinRT, with Visual C++ 16.5 2,393,515,3362,393,515,336 2424

大小縮減 20%,組建時間減少 23%。A 20% reduction in size, and a 23% reduction in build time.

已改善 MSBuild 支援Improved MSBuild support

我們已投注大量心力來改善對各種不同方案的 MSBuild 支援。We've invested a lot of work into improving MSBuild support for a large selection of different scenarios.

更快速的處理站快取Even faster factory caching

我們改進了處理站快取的內嵌,以便更好地內嵌最忙碌路徑,從而加快執行速度。We've improved inlining of the factory cache in order to better inline hot paths, which leads to faster execution.

這項改進並不會影響程式碼大小 (如下方最佳化 EH 程式碼產生中所述),如果您的應用程式大量使用 C++ 例外狀況處理程式,則可以使用 /d2FH4 選項來壓縮二進位檔,依預設,使用 Visual Studio 2019 16.3 和更高版本建立新專案中已啟用該功能。That improvement doesn't affect code size—as described below in Optimized EH code-gen, if your application uses C++ exception handling heavily, then you can shrink your binary by using the /d2FH4 option, which is on by default in new projects created with Visual Studio 2019 16.3, and later.

更有效率的 BoxingMore efficient boxing

在 XAML 應用程式中使用時,winrt::box_value 現在更有效率 (請參閱 Boxing 和 Unboxing)。When used in a XAML application, winrt::box_value is now more efficient (see Boxing and unboxing). 執行大量 Boxing 的應用程式也會注意到程式碼大小的縮減。Applications that do a lot of boxing will also notice a reduction in code size.

支援執行 IInspectable 的實作 COM 介面Support for implementing COM interfaces that implement IInspectable

如果您需要執行一個 (非 Windows 執行時間) COM 介面,而該介面剛好實作了 IInspectable,則現在可以使用 C++/WinRT 來執行此動作。If you need to implement a (non-Windows-Runtime) COM interface that just happens to implement IInspectable, then you can now do so with C++/WinRT. 請參閱實作 IInspectable 的 COM 介面See COM interfaces that implement IInspectable.

模組鎖定改進Module-locking improvements

對模組鎖定的控制現在既可以自訂託管方案,也可以完全消除模組層級的鎖定。Control over module-locking now allows both custom hosting scenarios and the elimination of module-level locking altogether. 請參閱模組鎖定改進See Module-locking improvements.

支援非 Windows 執行階段錯誤資訊Support for non-Windows-Runtime error information

某些 API (即使是某些 Windows 執行階段 API) 會報告錯誤,而不會使用 Windows 執行階段錯誤來源 API。Some APIs (even some Windows Runtime APIs) report errors without using Windows Runtime error origination APIs. 在這種情況下,C++/WinRT 現在回到使用 COM 錯誤資訊。In cases like that, C++/WinRT now falls back to using COM error info. 請參閱非 WinRT 錯誤資訊的 C++/WinRT 支援See C++/WinRT support for non-WinRT error information.

啟用 C++ 模組支援Enable C++ module support

C++ 模組支援已恢復,但僅適用於實驗性表單。C++ module support is back, but only in an experimental form. 這項功能在 C++ 編譯器中尚未完成。The feature isn't complete in the C++ compiler, as yet.

協同程式恢復更有效率More efficient coroutine resumption

C++/WinRT 協同程式已經順利執行,但我們會繼續尋找改善的方式。C++/WinRT coroutines already perform well, but we continue to look for ways to improve that. 請參閱提高協同程式恢復的可擴縮性See Improve scalability of coroutine resumption.

新增 when_allwhen_any 非同步協助程式New when_all and when_any async helpers

when_all 協助程式函式建立了 IAsyncAction 物件,該物件在所有提供的可等候都完成時就會完成。The when_all helper function creates an IAsyncAction object that completes when all of the supplied awaitables have completed. when_any 協助程式建立了 IAsyncAction,其在所有提供的可等候都完成時就會完成。The when_any helper creates an IAsyncAction that completes when any of the supplied awaitables have completed.

請參閱新增 when_any 非同步協助程式新增 when_all 非同步協助程式See Add when_any async helper and Add when_all async helper.

其他最佳化和新增功能Other optimizations and additions

此外,還引進了許多錯誤修正和一些最佳化和新增功能,包括各種改善措施,以簡化偵錯功能並將內部和預設實作最佳化。In addition, many bug fixes and minor optimizations and additions have been introduced, including various improvements to simplify debugging and to optimize internals and default implementations. 如需完整清單,請進入此連結:https://github.com/microsoft/xlang/pulls?q=is%3Apr+is%3AclosedFollow this link for an exhaustive list: https://github.com/microsoft/xlang/pulls?q=is%3Apr+is%3Aclosed.

C++/WinRT 2.0 的新聞和變更News, and changes, in C++/WinRT 2.0

如需關於 C++/WinRT Visual Studio Extension (VSIX)Microsoft.Windows.CppWinRT NuGet packagecppwinrt.exe 工具的詳細資訊 — 包括如何取得並加以安裝 — 請參閱適用於 C++/WinRT、XAML、VSIX 擴充功能,以及 NuGet 封裝的 Visual Studio 支援For more info about the C++/WinRT Visual Studio Extension (VSIX), the Microsoft.Windows.CppWinRT NuGet package, and the the cppwinrt.exe tool—including how to acquire and install them—see Visual Studio support for C++/WinRT, XAML, the VSIX extension, and the NuGet package.

C++/WinRT Visual Studio 擴充功能 (VSIX) 2.0 版的變更Changes to the C++/WinRT Visual Studio Extension (VSIX) for version 2.0

  • 偵錯視覺特效播放器目前支援 Visual Studio 2019;並繼續支援 Visual Studio 2017。The debug visualizer now supports Visual Studio 2019; as well as continuing to support Visual Studio 2017.
  • 已進行許多錯誤修正。Numerous bug fixes have been made.

Microsoft.Windows.CppWinRT NuGet 封裝 2.0 版的變更Changes to the Microsoft.Windows.CppWinRT NuGet package for version 2.0

  • cppwinrt.exe 工具目前包含在 Microsoft.Windows.CppWinRT NuGet 封裝中,此工具可視需要為每個專案產生平台投影標頭。The cppwinrt.exe tool is now included in the Microsoft.Windows.CppWinRT NuGet package, and the tool generates platfom projection headers for each project on demand. 因此,cppwinrt.exe 工具不再依賴 Windows SDK (儘管基於相容性原因,此工具仍隨附 SDK)。Consequently, the cppwinrt.exe tool no longer depends on the Windows SDK (although, the tool still ships with the SDK for compatibility reasons).
  • cppwinrt.exe 現在會在每個平台/特定設定的中繼資料夾 ($IntDir) 之下產生投影標頭,以啟用平行組建。cppwinrt.exe now generates projection headers under each platform/configuration-specific intermediate folder ($IntDir) to enable parallel builds.
  • 如果您想要手動自訂專案檔案,C++/WinRT 組件支援 (屬性/目標) 現在已完整記載。The C++/WinRT build support (props/targets) is now fully documented, in case you want to manually customize your project files. 請參閱 Microsoft.Windows.CppWinRT NuGet 套件讀我檔案See the Microsoft.Windows.CppWinRT NuGet package readme.
  • 已進行許多錯誤修正。Numerous bug fixes have been made.

C++/WinRT 2.0 版的變更Changes to C++/WinRT for version 2.0

開放原始碼Open source

cppwinrt.exe 工具採用 Windows 執行階段中繼資料 (.winmd) 檔案,並從中產生以標頭檔案為基礎的標準 C++ 程式庫,其投影中繼資料中所述的 API。The cppwinrt.exe tool takes a Windows Runtime metadata (.winmd) file, and generates from it a header-file-based standard C++ library that projects the APIs described in the metadata. 如此一來,便可從 C++/WinRT 程式碼中使用取用這些 API。That way, you can consume those APIs from your C++/WinRT code.

此工具目前是完全開放的原始碼專案,可在 GitHub 上找到。This tool is now an entirely open source project, available on GitHub. 瀏覽 Microsoft/cppwinrtVisit Microsoft/cppwinrt.

xlang 程式庫xlang libraries

可完全移植的僅標頭程式庫 (用於剖析 Windows 執行階段所用的 ECMA-335 中繼資料格式),構成了所有 Windows 執行階段和 xlang 工具進步的基礎。A completely portable header-only library (for parsing the ECMA-335 metadata format used by the Windows Runtime) forms the basis of all the Windows Runtime and xlang tooling going forward. 值得注意的是,我們使用了 xlang 程式庫從頭開始重新撰寫 cppwinrt.exe 工具。Notably, we also rewrote the cppwinrt.exe tool from the ground up using the xlang libraries. 如使提供了更準確的中繼資料查詢,解決了 C++/WinRT 語言投影的一些長期問題。This provides far more accurate metadata queries, solving a few long-standing issues with the C++/WinRT language projection.

較低的相依性Fewer dependencies

由於 xlang 中繼資料讀取器,cppwinrt.exe 工具本身具有較低的相依性。Due to the xlang metadata reader, the cppwinrt.exe tool itself has fewer dependencies. 這使其更有彈性,並且可以在更多情況下使用 — 尤其是在受限制的建置環境中。This makes it far more flexible, as well as being usable in more scenarios—especially in constrained build environments. 值得注意的是,它不再依賴 RoMetadata.dllNotably, it no longer relies on RoMetadata.dll.   以下為 cppwinrt.exe 2.0 的相依性。These are the dependencies for cppwinrt.exe 2.0.  

  • ADVAPI32.dllADVAPI32.dll
  • KERNEL32.dllKERNEL32.dll
  • SHLWAPI.dllSHLWAPI.dll
  • XmlLite.dllXmlLite.dll

這些 DLL 不僅適用於 Windows 10,還能適用於 Windows 7,甚至適用於 Windows Vista。All of those DLLs are available not only on Windows 10, but all the way down to Windows 7, and even Windows Vista. 如果您想要,執行 Windows 7 的舊組建伺服器現在可以執行 cppwinrt.exe,為您的專案產生 C++ 標頭。If you want it to, your old build server running Windows 7 can now run cppwinrt.exe to generate C++ headers for your project. 透過少許工作,您甚至可以在 Windows 7 上執行 C++/WinRT (如果您有興趣的話)。With a bit of work, you can even run C++/WinRT on Windows 7, if that interests you.

對照上述清單與 cppwinrt.exe 1.0 具備的下列相依性。Contrast the list above with these dependencies, which cppwinrt.exe 1.0 has.

  • ADVAPI32.dllADVAPI32.dll
  • SHELL32.dllSHELL32.dll
  • api-ms-win-core-file-l1-1-0.dllapi-ms-win-core-file-l1-1-0.dll
  • XmlLite.dllXmlLite.dll
  • api-ms-win-core-libraryloader-l1-2-0.dllapi-ms-win-core-libraryloader-l1-2-0.dll
  • api-ms-win-core-processenvironment-l1-1-0.dllapi-ms-win-core-processenvironment-l1-1-0.dll
  • RoMetadata.dllRoMetadata.dll
  • SHLWAPI.dllSHLWAPI.dll
  • KERNEL32.dllKERNEL32.dll
  • api-ms-win-core-rtlsupport-l1-1-0.dllapi-ms-win-core-rtlsupport-l1-1-0.dll
  • api-ms-win-core-heap-l1-1-0.dllapi-ms-win-core-heap-l1-1-0.dll
  • api-ms-win-core-timezone-l1-1-0.dllapi-ms-win-core-timezone-l1-1-0.dll
  • api-ms-win-core-console-l1-1-0.dllapi-ms-win-core-console-l1-1-0.dll
  • api-ms-win-core-localization-l1-2-0.dllapi-ms-win-core-localization-l1-2-0.dll
  • OLEAUT32.dllOLEAUT32.dll
  • api-ms-win-core-winrt-error-l1-1-0.dllapi-ms-win-core-winrt-error-l1-1-0.dll
  • api-ms-win-core-winrt-error-l1-1-1.dllapi-ms-win-core-winrt-error-l1-1-1.dll
  • api-ms-win-core-winrt-l1-1-0.dllapi-ms-win-core-winrt-l1-1-0.dll
  • api-ms-win-core-winrt-string-l1-1-0.dllapi-ms-win-core-winrt-string-l1-1-0.dll
  • api-ms-win-core-synch-l1-1-0.dllapi-ms-win-core-synch-l1-1-0.dll
  • api-ms-win-core-threadpool-l1-2-0.dllapi-ms-win-core-threadpool-l1-2-0.dll
  • api-ms-win-core-com-l1-1-0.dllapi-ms-win-core-com-l1-1-0.dll
  • api-ms-win-core-com-l1-1-1.dllapi-ms-win-core-com-l1-1-1.dll
  • api-ms-win-core-synch-l1-2-0.dllapi-ms-win-core-synch-l1-2-0.dll 

Windows 執行階段 noexcept 屬性The Windows Runtime noexcept attribute

Windows 執行階段有新的 [noexcept] 屬性,您可用於裝飾 MIDL 3.0 中的方法與屬性。The Windows Runtime has a new [noexcept] attribute, which you may use to decorate your methods and properties in MIDL 3.0. 此屬性表示支援不會讓您的實作擲回例外狀況的工具 (也不會傳回失敗的 HRESULT)。The presence of the attribute indicates to supporting tools that your implementation doesn't throw an exception (nor return a failing HRESULT). 如此語言投影就能免除掉用於處理意外狀況的額外負荷,通常這是為了支援可能失敗之應用程式二進位介面 (ABI) 呼叫所需,以此方式可讓程式碼的產生作業達到最佳化。This allows language projections to optimize code-generation by avoiding the exception-handling overhead that's required to support application binary interface (ABI) calls that can potentially fail.

C++/WinRT 會產生取用和撰寫程式碼的 C++ noexcept 實作,充分運用此功能。C++/WinRT takes advantage of this by producing C++ noexcept implementations of both the consuming and authoring code. 如果您有零失誤的 API 方法或屬性,而且需要顧慮程式碼大小,就建議您深入研究此屬性。If you have API methods or properties that are fail-free, and you're concerned about code size, then you can investigate this attribute.

最佳化的程式碼產生Optimized code-generation

C++/WinRT 現在會產生更有效率的 C++ 原始程式碼 (幕後),以便 C++ 編譯器產生最小且最有效的二進位程式碼。C++/WinRT now generates even more efficient C++ source code (behind the scenes) so that the C++ compiler can produce the smallest and most efficient binary code possible. 許多改良功能的設計,目標都是避免不必要的回溯資訊,以期降低例外狀況處理的成本。Many of the improvements are geared toward reducing the cost of exception-handling by avoiding unnecessary unwind information. 使用了大量 C++/WinRT 程式碼的二進位檔,大約可減少 4% 的程式碼大小。Binaries that use large amounts of C++/WinRT code will see roughly a 4% reduction in code size. 由於指令數量減少,程式碼也會更有效率 (執行速度更快)。The code is also more efficient (it runs faster) due to the reduced instruction count.

這些改良功能依賴您可用的全新互通性功能。These improvements rely on a new interop feature that's available to you, as well. 作為資源擁有者的所有 C++/WinRT 類型,目前皆包含可直接獲取擁有權的建構函式,以避開先前的雙步驟方法。All of the C++/WinRT types that are resource owners now include a constructor for taking ownership directly, avoiding the previous two-step approach.

ABI::Windows::Foundation::IStringable* raw = ...

IStringable projected(raw, take_ownership_from_abi);

printf("%ls\n", projected.ToString().c_str());

最佳化的例外狀況處理 (EH) 程式碼產生Optimized exception-handling (EH) code-generation

此變更補強了 Microsoft C++ 最佳化工具小組為了降低例外狀況處理成本所做的工作。This change complements work that has been done by the Microsoft C++ optimizer team to reduce the cost of exception-handling. 如果您在程式碼中大量使用應用程式二進位介面 (ABI) (例如 COM),就會發現許多遵循此模式的程式碼。If you use application binary interfaces (ABIs) (such as COM) heavily in your code, then you'll observe a lot of code following this pattern.

int32_t Function() noexcept
{
    try
    {
        // code here constitutes unique value.
    }
    catch (...)
    {
        // code here is always duplicated.
    }
}

C++/WinRT 本身為每個實作的 API 產生此模式。C++/WinRT itself generates this pattern for every API that's implemented. 有了數千個 API 函式,這裡的任何最佳化可能會產生重大影響。With thousands of API functions, any optimization here can be significant. 在過去,最佳化工具不會偵測到那些 Catch 區塊皆完全相同,因此會圍繞每個 ABI 複製許多程式碼 (這又導致人們相信在系統程式碼中使用例外狀況會產生大型的二進位檔)。In the past, the optimizer wouldn't detect that those catch blocks are all identical, so it was duplicating a lot of code around each ABI (which in turn contributed to the belief that using exceptions in system code produces large binaries). 但是,從 Visual Studio 2019 開始,C++ 編譯器會摺疊所有 catch funclet,並且只儲存唯一的 catch funclet。However, from Visual Studio 2019 on, the C++ compiler folds all of those catch funclets, and only stores those that are unique. 結果是,重度依賴此模式的二進位檔程式碼大小進而減少了 18%。The result is a further and overall 18% reduction in code size for binaries that rely heavily on this pattern. 不僅是現在的 EH 程式碼比起使用傳回程式碼更有效率,而且對於較大型二進位檔的顧慮已成為過去。Not only is EH code now more efficient than using return codes, but also the concern about larger binaries is now a thing of the past.

累加建置改善Incremental build improvements

cppwinrt.exe 工具現在會將產生的標頭/來源檔案的輸出結果,與磁碟上任何現有檔案的內容進行比較,而且只有在檔案實際發生變更時,才會寫出檔案。The cppwinrt.exe tool now compares the output of a generated header/source file against the contents of any existing file on disk, and it only writes out the file if the file has in fact changed. 如此可大量節省磁碟 I/O 時間,並確保 C++ 編譯器不會將檔案視為「已變更」。This saves considerable time with disk I/O, and it ensures that the files are not considered "dirty" by the C++ compiler. 結果,在許多情況下避免或減少了重新編譯。The result is that recompilation is avoided, or reduced, in many cases.

現在都是產生泛型介面Generic interfaces are now all generated

由於 xlang 中繼資料讀取器,C++/WinRT 現在可以從中繼資料產生所有參數化或泛型介面。Due to the xlang metadata reader, C++/WinRT now generates all parameterized, or generic, interfaces from metadata. Windows::Foundation::Collections::IVector<T> 之類的介面現在會從中繼資料產生,而不是使用 winrt/base.h 手動撰寫。Interfaces such as Windows::Foundation::Collections::IVector<T> are now generated from metadata rather than hand-written in winrt/base.h. 結果是 winrt/base.h 的大小減少一半,而且在程式碼中產生最佳化 (這是透過手動方法難以達成的目標)。The result is that the size of winrt/base.h has been cut in half, and that optimizations are generated right into the code (which was tricky to do with the hand-rolled approach).

重要

目前範例所提供的這類介面會出現在各自的命名空間標頭中,而不是在 winrt/base.h 中。Interfaces such as the example given now appear in their respective namespace headers, rather than in winrt/base.h. 因此,如果尚未這麼做,則必須納入適當的命名空間標頭,才能使用該介面。So, if you have not already done so, you'll have to include the appropriate namespace header in order to use the interface.

元件最佳化Component optimizations

此更新新增對 C++/WinRT 幾個其他選擇加入最佳化的支援,如下列章節所述。This update adds support for several additional opt-in optimizations for C++/WinRT, described in the sections below. 由於這些最佳化是重大變更 (您可能需要對支援進行微幅變更),因此,您需要明確啟用這些最佳化。Because these optimizations are breaking changes (which you may need to make minor changes to support), you'll need to turn them on explicitly. 在 Visual Studio 中,將 [通用屬性] > [C++/WinRT] > [最佳化] 設為 [是] 。In Visual Studio, set project property Common Properties > C++/WinRT > Optimized to Yes. 此動作會將 <CppWinRTOptimized>true</CppWinRTOptimized> 新增至您的專案檔。That has the effect of adding <CppWinRTOptimized>true</CppWinRTOptimized> to your project file. 而且這與從命令列叫用 cppwinrt.exe 時,新增 -opt[imize] 參數的效果一樣。And it has the same effect as adding the -opt[imize] switch when invoking cppwinrt.exe from the command line.

依預設,新專案 (來自專案範本) 將使用 -optA new project (from a project template) will use -opt by default.

統一建構,以及直接實作存取Uniform construction, and direct implementation access

這些兩種最佳化可讓您的元件直接存取其實作類型,即使它只使用投影的類型。These two optimizations allow your component direct access to its own implementation types, even when it's only using the projected types. 如果您只是想要使用公用 API 表面,則不需要使用 makemake_self,也不需要 get_selfThere's no need to use make, make_self, nor get_self if you simply want to use the public API surface. 您的呼叫將編譯成直接呼叫實作,甚至可能完全內嵌。Your calls will compile down to direct calls into the implementation, and those might even be entirely inlined.

如需詳細資訊和程式碼範例,請參閱加入統一建構和直接實作存取For more info, and code examples, see Opt in to uniform construction, and direct implementation access.

已清除類型的處理站Type-erased factories

此最佳化可避免 module.g.cpp 中的 #include 相依性,因此不需要在每次變更任何單一實作類別時重新編譯。This optimization avoids the #include dependencies in module.g.cpp so that it need not be recompiled every time any single implementation class happens to change. 結果會提高建置效能。The result is improved build performance.

更聰明且更有效率的 module.g.cpp 適用於具有多個程式庫的大型專案Smarter and more efficient module.g.cpp for large projects with multiple libs

module.g.cpp 檔案現在也包含兩個額外的可組合協助程式,名稱為 winrt_can_unload_nowwinrt_get_activation_factoryThe module.g.cpp file now also contains two additional composable helpers, named winrt_can_unload_now, and winrt_get_activation_factory. 這些設計用於較大的專案,其中 DLL 由許多程式庫組成,每個程式庫都有自己的執行階段類別。These have been designed for larger projects where a DLL is composed of a number of libs, each with its own runtime classes. 在此情況下,您需要將 DLL 的 DllGetActivationFactoryDllCanUnloadNow 手動拼接在一起。In that situation, you need to manually stitch together the DLL's DllGetActivationFactory and DllCanUnloadNow. 這些協助程式可避免假性來源錯誤,讓您更容易進行此操作。These helpers make it much easier for you to do that, by avoiding spurious origination errors. cppwinrt.exe 工具的 -lib 旗標也可用於為每個單獨的程式庫提供自己的前序 (而不 winrt_xxx),以便每個程式庫函數可以單獨命名,進而明確地組合。The cppwinrt.exe tool's -lib flag may also be used to give each individual lib its own preamble (rather than winrt_xxx) so that each lib's functions may be individually named, and thus combined unambiguously.

協同程式支援Coroutine support

自動包含協同程式支援。Coroutine support is included automatically. 先前,支援位於多個地方,而感覺受到過多限制。Previously, the support resided in multiple places, which we felt was too limiting. 然後對於 v2.0 來說,曾暫時需要 winrt/coroutine.h 標頭檔案,但如今已不再需要。And then temporarily for v2.0, a winrt/coroutine.h header file was necessary, but that's no longer needed. 由於現在已出現 Windows 執行階段非同步介面,而不是手寫,因此現在是位於 winrt/Windows.Foundation.h 中。Since the Windows Runtime async interfaces are now generated, rather than hand-written, they now reside in winrt/Windows.Foundation.h. 除了更容易維護和支援以外,這表示不再需要將協同程式 (例如 resume_foreground) 附加至特定命名空間標頭的結尾。Apart from being more maintainable and supportable, it means that coroutine helpers such as resume_foreground no longer have to be tacked on to the end of a specific namespace header. 如此反而可以更自然地納入其相依性。Instead, they can more naturally include their dependencies. 這可以進一步讓 resume_foreground 不僅支援在特定的 Windows::UI::Core::CoreDispatcher 上繼續進行,現在也可以支援在特定的 Windows::System::DispatcherQueue 上繼續進行。This further allows resume_foreground to support not only resuming on a given Windows::UI::Core::CoreDispatcher, but it can now also support resuming on a given Windows::System::DispatcherQueue. 以前只能支援一個,而無法同時支援兩者,因為定義只能位於一個命名空間中。Previously, only one could be supported; but not both, since the definition could only reside in one namespace.

以下是 DispatcherQueue 支援的範例。Here's an example of the DispatcherQueue support.

...
#include <winrt/Windows.System.h>
using namespace Windows::System;
...
fire_and_forget Async(DispatcherQueueController controller)
{
    bool queued = co_await resume_foreground(controller.DispatcherQueue());
    assert(queued);

    // This is just to simulate queue failure...
    co_await controller.ShutdownQueueAsync();

    queued = co_await resume_foreground(controller.DispatcherQueue());
    assert(!queued);
}

協同程式協助程式現在也用 [[nodiscard]] 裝置,藉此提高其可用性。The coroutine helpers are now also decorated with [[nodiscard]], thereby improving their usability. 如果您忘記 co_await (或者不知道必須如此做),以讓其得以運作,則由於 [[nodiscard]],此類錯誤現在會產生編譯器警告。If you forget to (or don't realize you have to) co_await them for them to work then, due to [[nodiscard]], such mistakes now produce a compiler warning.

協助診斷直接 (堆疊) 配置Help with diagnosing direct (stack) allocations

由於投影和實作類別名稱 (依預設) 相同,而且只有命名空間不同,因此可能會誤用,並且可能會不小心在堆疊上建立實作,而不是使用協助程式的 make 系列。Since the projected and implementation class names are (by default) the same, and only differ by namespace, it's possible to mistake the one for the other, and to accidentally create an implementation on the stack, rather than using the make family of helpers. 在某些情況下,這可能很難診斷,因為物件可能會遭受破壞,而未完成的參照仍在執行中。This can be hard to diagnose in some cases, because the object may be destroyed while outstanding references are still in flight. 對於偵錯組件,判斷提示現在選擇此項目。An assertion now picks this up, for debug builds. 雖然判斷提示沒有偵測到協同程式中的堆疊配置,但它仍然有助於擷取大部分此類錯誤。While the assertion doesn't detect stack allocation inside a coroutine, it's nevertheless helpful in catching most such mistakes.

如需詳細資訊,請參閱診斷直接配置For more info, see Diagnosing direct allocations.

改善擷取協助程式,以及 variadic 委派Improved capture helpers, and variadic delegates

此更新藉由支援投影類型來修正擷取協助程式的限制。This update fixes the limitation with the capture helpers by supporting projected types as well. 當它們傳回投影類型時,這會隨著 Windows 執行階段互通性 API 而出現。This comes up now and then with the Windows Runtime interop APIs, when they return a projected type.

使更新也在建立 variadic (非 Windows 執行階段) 委派時,新增了 get_strongget_weak 的支援。This update also adds support for get_strong and get_weak when creating a variadic (non-Windows Runtime) delegate.

在解構期間支援遞延解構和安全 QISupport for deferred destruction and safe QI during destruction

在執行階段類別物件的解構函式中,呼叫可暫時壓縮參考計數的方法並不稀奇。It's not uncommon in the destructor of a runtime class object to call a method that temporarily bumps the reference count. 當參考計數會回到零時,物件會第二次解構。When the reference count returns to zero, the object destructs a second time. 在 XAML 應用程式中,您可能需要在解構函式中執行 QueryInterface (QI),以便在階層中向上或向下呼叫某些清除實作。In a XAML application, you might need to perform a QueryInterface (QI) in a destructor, in order to call some cleanup implementation up or down the hierarchy. 但是,物件的參考計數已經達到零,因此 QI 也會構成參考計數反彈。But the object's reference count has already reached zero, so that QI constitutes a reference count bounce, too.

此更新新增對消除彈跳引用計數的支援,確保一旦達到零之後,就永遠無法重新啟動;同時仍然允許將 QI 用於解構期間所需的任何暫存。This update adds support for debouncing the reference count, ensuring that once it reaches zero it can never be resurrected; while still allowing you to QI for any temporary that you require during destruction. 在某些 XAML 應用程式/控制項中,無法避免此過程,而 C++/WinRT 現在具有彈性。This procedure is unavoidable in certain XAML applications/controls, and C++/WinRT is now resilient to it.

您可以藉由在您的實作類型上提供靜態 final_release 函式來延遲解構。You can defer destruction by providing a static final_release function on your implementation type. 物件的最後一個剩餘指標 (std::unique_ptr形式) 會傳遞至您的 final_releaseThe last remaining pointer to the object, in the form of a std::unique_ptr, is passed to your final_release. 然後,您可以選擇將該指標的擁有權移至其他某些內容。You can then opt to move ownership of that pointer to some other context. 您可以安全地對指標使用 QI,而不觸發雙重解構。It's safe for you to QI the pointer without triggering a double-destruction. 但參考計數的淨變更在解構物件之處必須是零。But the net change to the reference count must be zero at the point you destruct the object.

final_release的傳回值可以是 void,也就是 IAsyncActionwinrt::fire_and_forget 等非同步作業物件。The return value of final_release can be void, an asynchronous operation object such as IAsyncAction, or winrt::fire_and_forget.

struct Sample : implements<Sample, IStringable>
{
    hstring ToString()
    {
        return L"Sample";
    }

    ~Sample()
    {
        // Called when the unique_ptr below is reset.
    }

    static void final_release(std::unique_ptr<Sample> self) noexcept
    {
        // Move 'self' as needed to delay destruction.
    }
};

在以下範例中,(最後一次) 釋出 MainPage 之後,會呼叫 final_releaseIn the example below, once the MainPage is released (for the final time), final_release is called. 該函式花費五秒鐘等待 (在執行緒集區上),然後使用頁面的 Dispatcher (需要 QI/AddRef/Release 進行運作) 以繼續進行。That function spends five seconds waiting (on the thread pool), and then it resumes using the page's Dispatcher (which requires QI/AddRef/Release to work). 接著,函式會清除該 UI 執行緒上的資源。It then cleans up a resource on that UI thread. 最後,清除 unique_ptr,這會導致實際呼叫 MainPage 解構函式。And finally it clears the unique_ptr, which causes the MainPage destructor to actually get called. 即使在該解構函式中,也會呼叫 DataContext,其需要適用於 IFrameworkElement 的 QI。Even in that destructor, DataContext is called, which requires a QI for IFrameworkElement.

您不需要實作 final_release 做為協同程式。You don't have to implement your final_release as a coroutine. 但這確實有效,而且可輕鬆地將解構移動到不同的執行緒,也就是此範例中的狀況。But that does work, and it makes it very simple to move destruction to a different thread, which is what's happening in this example.

struct MainPage : PageT<MainPage>
{
    MainPage()
    {
    }

    ~MainPage()
    {
        DataContext(nullptr);
    }

    static IAsyncAction final_release(std::unique_ptr<MainPage> self)
    {
        co_await 5s;

        co_await resume_foreground(self->Dispatcher());
        co_await self->resource.CloseAsync();

        // The object is destructed normally at the end of final_release,
        // when the std::unique_ptr<MyClass> destructs. If you want to destruct
        // the object earlier than that, then you can set *self* to `nullptr`.
        self = nullptr;
    }
};

如需詳細資訊,請參閱延遲解構For more info, see Deferred destruction.

已改善對 COM 樣式單一介面繼承的支援Improved support for COM-style single interface inheritance

與 Windows 執行階段程式設計一樣, C++/WinRT 也用於撰寫和取用僅限 COM 的 API。As well as for Windows Runtime programming, C++/WinRT is also used to author and consume COM-only APIs. 此更新可讓您實作存在介面階層的 COM 伺服器。This update makes it possible to implement a COM server where there exists an interface hierarchy. Windows 執行階段不需要這麼做;但它對於某些 COM 實作是必要的。This isn't required for the Windows Runtime; but it is required for some COM implementations.

正確處理 out 參數Correct handling of out params

使用 out 參數可能很棘手;尤其是 Windows 執行階段陣列。It can be tricky to work with out params; particularly Windows Runtime arrays. 透過此更新,涉及 out 參數和陣列方面時,C++/WinRT 可更加強大且彈性地抵禦錯誤;無論這些參數是透過語言投影到達,還是來自使用原始 ABI 的 COM 開發人員,以及犯下未利用一致的方式對變數進行初始化的錯誤。With this update, C++/WinRT is considerably more robust and resilient to mistakes when it comes to out params and arrays; whether those parameters arrive via a language projection, or from a COM developer who's using the raw ABI, and who's making the mistake of not initializing variables consistently. 在任一情況下,涉及將投影類型移交給 ABI 時 (藉由記住釋出任何資源),以及涉及歸零或清除通過 ABI 到達的參數時,C++/WinRT 現在皆會做出正確的操作。In either case, C++/WinRT now does the right thing when it comes to handing off projected types to the ABI (by remembering to release any resources), and when it comes to zeroing out or clearing out parameters that arrive across the ABI.

事件現在可靠地處理無效權杖Events now handle invalid tokens reliably

winrt::event 實作現在可以依正常程序處理使用無效權杖值 (陣列中不存在的值) 來呼叫其 remove 方法的情況。The winrt::event implementation now gracefully handles the case where its remove method is called with an invalid token value (a value that's not present in the array).

協同程式區域變數現在會在協同程式傳回之前終結Coroutine local variables are now destroyed before the coroutine returns

實作協同程式類型的傳統方式可能會讓協同程式內的區域變數在協同程式傳回/完成之後 (而不是在最終暫停之前) 終結。The traditional way of implementing a coroutine type may allow local variables within the coroutine to be destroyed after the coroutine returns/completes (rather than prior to final suspension). 現在必須延遲到最後暫停,才能重新恢復任何等候程序,以避免這個問題並產生其他好處。The resumption of any waiter is now deferred until final suspension, in order to avoid this problem and to accrue other benefits.

Windows SDK 版本 10.0.17763.0 (Windows 10 版本 1809) 中的新聞和變更News, and changes, in Windows SDK version 10.0.17763.0 (Windows 10, version 1809)

下表包含 Windows SDK 版本 10.0.17763.0 (Windows 10 版本 1809) 中 C++/WinRT 的新聞和變更。The table below contains news and changes for C++/WinRT in the Windows SDK version 10.0.17763.0 (Windows 10, version 1809).

新增或變更的功能New or changed feature 其他資訊More info
重大變更Breaking change. 若要進行編譯,C++/WinRT 不會根據 Windows SDK 的標頭。For it to compile, C++/WinRT doesn't depend on headers from the Windows SDK. 請參閱下方的從 Windows SDK 標頭檔案隔離See Isolation from Windows SDK header files, below.
Visual Studio 專案系統格式已變更。The Visual Studio project system format has changed. 請參閱下方如何將 C++/WinRT 專案的目標重定為 Windows SDK 的較新版本See How to retarget your C++/WinRT project to a later version of the Windows SDK, below.
有一些新函式和基底類別有助於將集合物件傳遞給 Windows 執行階段函式,或者實作您自己的集合屬性和集合類別。There are new functions and base classes to help you pass a collection object to a Windows Runtime function, or to implement your own collection properties and collection types. 請參閱使用 C++/WinRT 的集合See Collections with C++/WinRT.
您可以將 {Binding} 標記延伸與 C++/WinRT 執行階段類別搭配使用。You can use the {Binding} markup extension with your C++/WinRT runtime classes. 如需更多資訊與程式碼範例,請參閱資料繫結概觀For more info, and code examples, see Data binding overview.
支持取消協同程式可讓您註冊取消回呼。Support for canceling a coroutine allows you to register a cancellation callback. 如需更多資訊和程式碼範例,請參閱取消非同步作業,以及取消回呼For more info, and code examples, see Canceling an asynchronous operation, and cancellation callbacks.
建立指向成員函式的委派時,可以在註冊處理常式的位置建立對目前物件 (而不是原始的「this」 指標) 的強式參考或弱式參考。When creating a delegate pointing to a member function, you can establish a strong or a weak reference to the current object (instead of a raw this pointer) at the point where the handler is registered. 如需更多資訊和程式碼範例,請參閱使用事件處理委派安全地存取「this」 指標小節的如果您使用成員函式作為委派子小節。For more info, and code examples, see the If you use a member function as a delegate sub-section in the section Safely accessing the this pointer with an event-handling delegate.
修正 Visual Studio 對於 C++ 標準改善一致性未涵蓋的錯誤。Bugs are fixed that were uncovered by Visual Studio's improved conformance to the C++ standard. LLVM 和 Clang 工具鏈也可以更好地用於驗證 C++/WinRT 的標準一致性。The LLVM and Clang toolchain is also better leveraged to validate C++/WinRT's standards conformance. 您將不再遇到為什麼無法編譯我的新專案?我使用 Visual Studio 2017 (版本 15.8.0 或更高版本),以及 SDK 版本 17134 中描述的問題You'll no longer encounter the issue described in Why won't my new project compile? I'm using Visual Studio 2017 (version 15.8.0 or higher), and SDK version 17134

其他變更。Other changes.

  • 重大變更Breaking change. winrt::get_abi(winrt::hstring const&) 現在會傳回 void*,而不是 HSTRINGwinrt::get_abi(winrt::hstring const&) now returns void* instead of HSTRING. 您可以使用 static_cast<HSTRING>(get_abi(my_hstring)); 以取得 HSTRING。You can use static_cast<HSTRING>(get_abi(my_hstring)); to get an HSTRING. 請參閱交互操作 ABI 的 HSTRINGSee Interoperating with the ABI's HSTRING.
  • 重大變更Breaking change. winrt::put_abi(winrt::hstring&) 現在會傳回 void**,而不是 HSTRING*winrt::put_abi(winrt::hstring&) now returns void** instead of HSTRING*. 您可以使用 reinterpret_cast<HSTRING*>(put_abi(my_hstring)); 以取得 HSTRING*。You can use reinterpret_cast<HSTRING*>(put_abi(my_hstring)); to get an HSTRING*. 請參閱交互操作 ABI 的 HSTRINGSee Interoperating with the ABI's HSTRING.
  • 重大變更Breaking change. HRESULT 現在投影為 winrt::hresultHRESULT is now projected as winrt::hresult. 如果您需要 HRESULT (以進行類別檢查,或支援類型特性),您可以 static_castwinrt::hresultIf you need an HRESULT (to do type checking, or to support type traits), then you can static_cast a winrt::hresult. 否則,只要您在加入任何 C++/WinRT 標頭之前,先加入 unknwn.hwinrt::hresult 會轉換成 HRESULT。Otherwise, winrt::hresult converts to HRESULT, as long as you include unknwn.h before you include any C++/WinRT headers.
  • 重大變更Breaking change. GUID 現在投影為 winrt::guidGUID is now projected as winrt::guid. 對於您實作的 API,必須為 GUID 參數使用 winrt::guidFor APIs that you implement, you must use winrt::guid for GUID parameters. 否則,只要您在加入任何 C++/WinRT 標頭之前,先加入 unknwn.hwinrt::guid 會轉換成 GUID。Otherwise, winrt::guid converts to GUID, as long as you include unknwn.h before you include any C++/WinRT headers. 請參閱交互操作 ABI 的 GUID 結構See Interoperating with the ABI's GUID struct.
  • 重大變更Breaking change. winrt::handle_type 建構函式已透過明確宣告而強化 (現在很難使用它撰寫錯誤的程式碼)。The winrt::handle_type constructor has been hardened by making it explicit (it's now harder to write incorrect code with it). 如果需要指派原始的控制碼值,請改由呼叫 handle_type::attach 函式If you need to assign a raw handle value, call the handle_type::attach function instead.
  • 重大變更Breaking change. WINRT_CanUnloadNowWINRT_GetActivationFactory 的簽章已變更。The signatures of WINRT_CanUnloadNow and WINRT_GetActivationFactory have changed. 您不得宣告這些函式。You mustn't declare these functions at all. 相反,加入 winrt/base.h (如果包含任何 C++/WinRT Windows 命名空間標頭檔案,則會自動包含),以包含這些函式的宣告。Instead, include winrt/base.h (which is automatically included if you include any C++/WinRT Windows namespace header files) to include the declarations of these functions.
  • 對於 winrt::clock structfrom_FILETIME/to_FILETIME 已過時,建議使用 from_file_time/to_file_timeFor the winrt::clock struct, from_FILETIME/to_FILETIME are deprecated in favor of from_file_time/to_file_time.
  • 預期使用 IBuffer 參數的簡化 API。Simplified APIs that expect IBuffer parameters. 大部分的 API 偏好集合或陣列。Most APIs prefer collections, or arrays. 但我們認為應該讓您更輕鬆地呼叫依賴 IBuffer 的 API。But we felt that we should make it easier to call APIs that rely on IBuffer. 此更新可讓您直接存取 IBuffer 實作背後的資料。This update provides direct access to the data behind an IBuffer implementation. 其使用與 C++ 標準程式庫容器所用相同的資料命名慣例。It uses the same data naming convention as the one used by the C++ Standard Library containers. 該慣例也避免了通常以大寫字母開頭的中繼資料名稱產生衝突。That convention also avoids collisions with metadata names that conventionally begin with an uppercase letter.
  • 改善的程式碼產生:各種改善項目可縮減程式碼大小、改善內嵌,並最佳化處理站快取。Improved code generation: various improvements to reduce code size, improve inlining, and optimize factory caching.
  • 已移除不必要的遞迴。Removed unnecessary recursion. 當命令列指向資料夾而非特定的 .winmd 時,cppwinrt.exe 工具不會再以遞迴方式搜尋 .winmd 檔案。When the command-line refers to a folder, rather than to a specific .winmd, the cppwinrt.exe tool no longer searches recursively for .winmd files. cppwinrt.exe 工具現在也可以更有智慧的方式處理重複項目,使其更容易復原使用者錯誤,以及格式錯誤的 .winmd 檔案。The cppwinrt.exe tool also now handles duplicates more intelligently, making it more resilient to user error, and to poorly-formed .winmd files.
  • 強化的智慧型指標。Hardened smart pointers. 之前,當移動指派新值時,事件撤銷無法撤銷。Formerly, the event revokers failed to revoke when move-assigned a new value. 這有助於揭露智慧型指標類別無法可靠地處理自我指派的問題;植根於 winrt::com_ptr 結構範本This helped uncover an issue where smart pointer classes weren't reliably handling self-assignment; rooted in the winrt::com_ptr struct template. winrt::com_ptr 已修正,而且事件撤銷已修正為正確處理移動語意,以便在指派時撤銷。winrt::com_ptr has been fixed, and the event revokers fixed to handle move semantics correctly so that they revoke upon assignment.

重要

對於版本 1.0.181002.2 中的 C++/WinRT Visual Studio 延伸模組 (VSIX) 已進行重要變更,之後在版本 1.0.190128.4 中也進行了變更。Important changes were made to the C++/WinRT Visual Studio Extension (VSIX), both in version 1.0.181002.2, and then later in version 1.0.190128.4. 如需這些變更的詳細資料,以及如何影響您現有的專案,請參閱適用於 C++/WinRT 的 Visual Studio 支援舊版 VSIX 延伸模組For details of these changes, and how they affect your existing projects, Visual Studio support for C++/WinRT and Earlier versions of the VSIX extension.

從 Windows SDK 標頭檔案隔離Isolation from Windows SDK header files

這可能是您程式碼的重大變更。This is potentially a breaking change for your code.

若要進行編譯,C++/WinRT 不會再根據 Windows SDK 的標頭檔案。For it to compile, C++/WinRT no longer depends on header files from the Windows SDK. C 執行階段程式庫 (CRT) 和 C++ 標準範本程式庫 (STL) 中的標頭檔案也不包含任何 Windows SDK 標頭。Header files in the C run-time library (CRT) and the C++ Standard Template Library (STL) also don't include any Windows SDK headers. 這樣可以提高標準相容性,避免不小心產生的相依性,並可大幅減少必須防範的巨集數。And that improves standards compliance, avoids inadvertent dependencies, and greatly reduces the number of macros that you have to guard against.

這種獨立性表示 C++/WinRT 現在更具可移植性和標準相容性,而且進一步推動成為跨編譯器和跨平台程式庫的可能性。This independence means that C++/WinRT is now more portable and standards compliant, and it furthers the possibility of it becoming a cross-compiler and cross-platform library. 這也表示 C++/WinRT 標頭不會對巨集造成負面影響。It also means that the C++/WinRT headers aren't adversely affected macros.

如果您之前將其留在 C++/WinRT 中,以在專案中包含任何 Windows 標頭,那麼您現在需要自行包含標頭。If you previously left it to C++/WinRT to include any Windows headers in your project, then you'll now need to include them yourself. 在任何情況下,最佳做法永遠是明確包含您所需的標頭,而不是將其留給另一個程式庫以包含標頭。It is, in any case, always best practice to explicitly include the headers that you depend on, and not leave it to another library to include them for you.

目前,唯一的例外狀況為 Windows SDK 標頭檔案隔離是內建函式和數值。Currently, the only exceptions to Windows SDK header file isolation are for intrinsics, and numerics. 這些最後剩餘的相依性沒有已知問題。There are no known issues with these last remaining dependencies.

在專案中,您可以視需要使用 Windows SDK 標頭以重新啟用互通性。In your project, you can re-enable interop with the Windows SDK headers if you need to. 例如,您可以想要實作 COM 介面 (根植於 IUnknown)。You might, for example, want to implement a COM interface (rooted in IUnknown). 對於該範例,在包含任何 C++/WinRT 標頭之前包含 unknwn.hFor that example, include unknwn.h before you include any C++/WinRT headers. 這樣做會造成 C++/WinRT 基礎程式庫啟用各種勾點以支援傳統的 COM 介面。Doing so causes the C++/WinRT base library to enable various hooks to support classic COM interfaces. 如需程式碼範例,請參閱使用 C++/WinRT 撰寫 COM 元件For a code example, see Author COM components with C++/WinRT. 同樣地,請明確納入任何其他 Windows SDK 標頭,這些標頭會宣告您要呼叫的類型及/或函式。Similarly, explicitly include any other Windows SDK headers that declare types and/or functions that you want to call.

如何將 C++/WinRT 專案的目標重定為 Windows SDK 的較新版本How to retarget your C++/WinRT project to a later version of the Windows SDK

重定專案目標的方法,所產生的編譯器和連接器問題可能最少,卻也最耗費人力。The method for retargeting your project that's likely to result in the fewest compiler and linker issue is also the most labor-intensive. 該方法涉及建立新專案 (針對您選擇的 Windows SDK 版本),然後將檔案從舊專案複製到新專案。That method involves creating a new project (targeting the Windows SDK version of your choice), and then copying files over to your new project from your old. 您可以複製舊 .vcxproj.vcxproj.filters 檔案的部分,以省下在 Visual Studio 中新增檔案的過程。There will be sections of your old .vcxproj and .vcxproj.filters files that you can just copy over to save you adding files in Visual Studio.

但是,有另外兩種方法可以在 Visual Studio 中重定專案目標。However, there are two other ways to retarget your project in Visual Studio.

  • 移至專案屬性 [一般] >[Windows SDK 版本] ,然後選取 [所有組態] 和 [所有平台] 。Go to project property General > Windows SDK Version, and select All Configurations and All Platforms. Windows SDK 版本設為您要設定目標的版本。Set Windows SDK Version to the version that you want to target.
  • 在 [方案總管] 中,在專案節點上按一下滑鼠右鍵,按一下 [重定專案目標] ,選擇您要重定目標的版本,然後按一下 [確定] 。In Solution Explorer, right-click the project node, click Retarget Projects, choose the version(s) you wish to target, and then click OK.

如果使用這兩種方法之一後,遇到任何編譯器或連接器錯誤,則可以先嘗試清除解決方案 ([建置] > [清除解決方案] 及/或手動刪除所有暫存資料夾和檔案),然後再嘗試建置。If you encounter any compiler or linker errors after using either of these two methods, then you can try cleaning the solution (Build > Clean Solution and/or manually delete all temporary folders and files) before trying to build again.

如果 C++ 編譯器產生「錯誤 C2039:'IUnknown': 不是 '`global namespace'' 的成員」,則將 #include <unknwn.h> 新增至 pch.h 檔案的頂端 (在您加入任何 C++/WinRT 標頭之前)。If the C++ compiler produces "error C2039: 'IUnknown': is not a member of '`global namespace''", then add #include <unknwn.h> to the top of your pch.h file (before you include any C++/WinRT headers).

您可能需要在此之後加入 #include <hstring.h>You may also need to add #include <hstring.h> after that.

如果 C++ 連接器產生「錯誤 LNK2019:函式 _VSDesignerCanUnloadNow@0 中參照無法解析的外部符號 _WINRT_CanUnloadNow@0」,您可以藉由將 #define _VSDESIGNER_DONT_LOAD_AS_DLL 新增至 pch.h 檔案,以解決問題。If the C++ linker produces "error LNK2019: unresolved external symbol _WINRT_CanUnloadNow@0 referenced in function _VSDesignerCanUnloadNow@0", then you can resolve that by adding #define _VSDESIGNER_DONT_LOAD_AS_DLL to your pch.h file.