針對 C++/WinRT 問題進行疑難排解
注意
如需安裝和使用 C++/WinRT Visual Studio 延伸模組 (VSIX) (提供專案範本支援) 的資訊,請參閱 C++/WinRT 的 Visual Studio 支援。
本主題是預先準備,這樣您就會立即知道;即使您還不需要。 無論您是剪下新的程式碼或移植現有的應用程式,下面的疑難排解問題和解決方式表格可能對您會很有幫助。 如果您正在移植,且您急著想要儘快進入建置及執行專案的階段,您可以暫時將任何非必要的程式碼標成註解或移除,稍後再回來解決。
如需常見問題清單,請參閱常見問題集。
追蹤 XAML 問題
XAML 剖析例外狀況可能難以診斷,特別是如果例外狀況中的錯誤訊息沒有意義。 請確定偵錯工具已設定為捕獲首次發生的例外狀況 (以便儘早嘗試並捕獲剖析例外狀況)。 您可以檢查偵錯工具中的例外狀況變數,以判斷 HRESULT 或訊息是否有任何有用的資訊。 此外,請檢查 Visual Studio 的輸出視窗,以取得 XAML 剖析器所輸出的錯誤訊息。
如果您的應用程式終止,而您知道的唯一事項是在 XAML 標記剖析期間擲回未處理的例外狀況,則有可能是所參考 (藉由索引鍵) 的資源遺失的結果。 或者,可能是在 UserControl、自訂控制項或自訂版面配置面板內擲回例外狀況。 最後手段則是二進位分割。 從「XAML 頁面」移除一半的標記,然後重新執行應用程式。 這樣您就會知道錯誤是出在您所移除的那半部內 (無論如何,您現在都應該還原這個部分),還是出在您「未」移除的那半部內。 透過分割包含錯誤的一半來重複此過程,依此繼續執行,直到您找到問題原因為止。
徵兆和解決方式
徵兆 | 補救方法 |
---|---|
在執行階段期間擲回例外狀況,其 HRESULT 值為 REGDB_E_CLASSNOTREGISTERED。 | 請參閱為什麼我會收到「類別未註冊」的例外狀況?。 |
C++ 編譯器產生錯誤「'implements_type': 不是 '<投影類型>' 任何直接或間接基底類別的成員」。 | 您呼叫 make 實作類型的不完整命名空間名稱 (例如,MyRuntimeClass),且您尚未包含該類型的標頭時,便會發生此情況。 編譯器解譯 MyRuntimeClass 作為投影型別。 解決方案會為您的實作類型包含標頭 (例如,MyRuntimeClass.h )。 |
C++ 編譯器產生錯誤「嘗試參考被刪除的函式」。 | 當您呼叫 make 且您作為範本參數傳遞的實作類型有 = delete 預設建構函式時,便會發生此情況。 編輯實作類型的標頭檔案,並將 = delete 變更為 = default 。 您也可以將建構函式新增至適用於執行階段類別的 IDL。 |
您已實作 INotifyPropertyChanged,但您的 XAML 繫結未更新 (且 UI 未訂閱 PropertyChanged)。 | 請記得在 XAML 標記中的繫結運算式上設定 Mode=OneWay (或 TwoWay)。 請參閱 XAML 控制項;繫結一個 C++/WinRT 屬性。 |
您把 XAML 項目控制項繫結到可觀察的集合,且在執行階段擲回例外狀況與訊息「參數不正確」。 | 在您的 IDL 和實作中,宣告任何可觀察的集合作為類型 Windows.Foundation.Collections.IVector<IInspectable>。 但傳回實作 Windows.Foundation.Collections.IObservableVector<T> 的物件,其中 T 為您的元素類型。 請參閱 XAML 項目控制項;繫結至 C++/WinRT 集合。 |
C++ 編譯器產生一個錯誤的表單「'MyImplementationType_base<MyImplementationType>': 沒有適當的預設建構函式」。 | 當您衍生自具有非一般建構函式的類型時,可能會發生這種情形。 您衍生的類型建構函式必須與需要基本類型建構函式的參數一起傳遞。 如需一個已執行的範例,請參閱從非一般建構函式衍生。 |
C++ 編譯器產生錯誤「無法從 'const std::vector<std::wstring,std::allocator<_Ty>>' 轉換至 'const winrt::param::async_iterable<winrt::hstring> &'」。 | 您將 std::wstring 的 std::vector 傳遞到預期收到集合的 Windows 執行階段 API,便可能會發生此情況。 如需詳細資訊,請參閱標準 C++ 資料類型與 C++/WinRT。 |
C++ 編譯器產生錯誤「無法從 'const std::vector<winrt::hstring,std::allocator<_Ty>>' 轉換至 'const winrt::param::async_iterable<winrt::hstring> &'」。 | 當您將 winrt::hstring 的 std::vector 傳遞至預期收到集合的 Windows 執行階段 API 時,且您沒有將向量複製或移動到非同步被呼叫者,便會發生此情況。 如需詳細資訊,請參閱標準 C++ 資料類型與 C++/WinRT。 |
開啟一個專案時,Visual Studio 產生此錯誤「未安裝專案的應用程式」。 | 如果您尚未開始,您需要從 Visual Studio 的 [新專案] 對話方塊中安裝 C++ 開發 Windows 通用工具。 如果無法解決問題,則此專案可能相依於 C++/WinRT Visual Studio 擴充功能 (VSIX) (請參閱 C++/WinRT 的 Visual Studio 支援)。 |
Windows 應用程式認證套件測試產生錯誤,指出執行階段類別「不衍生自 Windows 基底類別。所有可組合的類別最終必須衍生自 Windows 命名空間中的類型」。 | 從基底類別衍生的任何執行階段類別 (您在您的應用程式中宣告),都稱為「可組合」類別。 可組合類別的最終基底類別都必須是源自 Windows.* 命名空間的類別;例如,Windows.UI.Xaml.DependencyObject。 如需詳細資訊,請參閱 XAML 控制項;繫結至 C++/WinRT 屬性。 |
C++ 編譯器產生 EventHandler 或 TypedEventHandler 委派特製化的「T 必須為 WinRT 類型」錯誤。 | 請考慮改用 winrt::delegate<...T>。 請參閱在 C++/WinRT 中撰寫事件。 |
C++ 編譯器產生 Windows 執行階段非同步作業特製化的「T 必須為 WinRT 類型」錯誤。 | 請考慮改為傳回平行模式程式庫 (PPL) task。 請參閱並行和非同步作業。 |
當您呼叫 winrt::xaml_typename時,C++ 編譯器會產生「T 必須為 WinRT 類型」錯誤。 | 使用預估類型搭配 winrt::xaml_typename (例如,使用 BgLabelControlApp::BgLabelControl),而不是實作類型 (例如,請勿使用 BgLabelControlApp::implementation::BgLabelControl)。 請參閱 XAML 自訂 (範本化) 控制項。 |
C++ 編譯器產生「錯誤 C2220: 將警告視為錯誤處理 - 沒有產生 'object' 檔案」。 | 修正警告,或將 [C/C++]>[一般]>[將警告視為錯誤] 設定為 [否 (/WX-)]。 |
您的應用程式當機,因為在終結物件後,呼叫了在 C++/WinRT 物件中處理的事件。 | 請參閱使用事件處理委派安全地存取 this 指標。 |
C++ 編譯器產生「錯誤 C2338:這只適用於弱式參考支援」。 | 您為將 winrt::no_weak_ref 標記結構作為範本引數傳遞至其基底類別的類型,要求一個弱式參考。 請參閱不使用弱式參考支援。 |
C++ 編譯器產生「consume_Something:傳回 'auto' 的函式無法在其定義之前使用」 | 請查看C3779:為什麼編譯器給我「consume_Something:傳回 'auto' 的函式無法在其定義之前使用」錯誤?。 |
C++ 連接器產生「錯誤 LNK2019:無法解析的外部符號」 | 請查看為何連結器給我「LNK2019:無法解析的外部符號」錯誤?。 |
當 LLVM 和 Clang 工具鏈搭配使用 C++/WinRT 時,會產生錯誤。 | 針對 C++/WinRT,我們不支援 LLVM 和 Clang 工具鏈,但如果您想要模擬我們如何在內部使用它,則您可以嘗試實驗,如我可以使用 LLVM/Clang 來編譯 C++/WinRT 嗎?中所述的。 |
C++ 編譯器產生投影型別的「沒有適當的預設建構函式」。 | 如果您嘗試將執行階段類別物件的初始化延遲,或嘗試在相同專案中取用和實作執行階段類別,則您必須呼叫 std::nullptr_t 建構函式。 如需詳細資訊,請參閱使用 C++/WinRT 取用 API。 |
C++ 編譯器產生「錯誤 C3861: 'from_abi': 找不到識別碼」,及其他源自 base.h 的錯誤。 如果您是使用 Visual Studio 2017 (15.8.0 版或更新版本),且目標為 Windows SDK 10.0.17134.0 版 (Windows 10 1803 版),則您可能會看到此錯誤。 | 將 Windows SDK 的較新 (更一致) 版本設定為目標,或將專案屬性設為 C/C++>語言>一致性模式:否 (此外,如果 /permissive- 顯示在 [其他選項] 底下的專案屬性 [C/C++]>[語言]>[命令列] 中,請加以刪除)。 |
C++ 編譯器產生「錯誤 C2039:'IUnknown': 不是 [全域命名空間] 的成員」。 | 請參閱如何將您 C++/WinRT 專案的目標設定為 Windows SDK 的較新版本。 |
C++ 連接器產生「錯誤 LNK2019:在函式 _VSDesignerCanUnloadNow@0 中參考無法解析的外部符號 _WINRT_CanUnloadNow@0」 | 請參閱如何將您 C++/WinRT 專案的目標設定為 Windows SDK 的較新版本。 |
建置程序會產生錯誤訊息「C++/WinRT VSIX 不再提供專案的建置支援。請將專案參考加入 Microsoft.Windows.CppWinRT Nuget 套件」。 | 將 Microsoft.Windows.CppWinRT NuGet 套件安裝到您的專案中。 如需詳細資訊,請參閱舊版 VSIX 擴充功能。 |
C++ 連接器產生「錯誤 LNK2019: 無法解析的外部符號」,包含提及 winrt::impl::consume_Windows_Foundation_Collections_IVector。 | 自 C++/WinRT 2.0,如果您在 Windows 執行階段集合上使用範圍型 for ,則您現在必須 #include <winrt/Windows.Foundation.Collections.h> 。 |
C++ 編譯器產生「錯誤 C4002:函式類巨集引動過程 GetCurrentTime 有太多引數」。 | 請參閱如何解決 GetCurrentTime 和/或 TRY 意義不明的狀況?。 |
C++編譯器會產生「錯誤 C2334:'{' 前面有非預期的權杖;略過顯示的函式主體」。 | 請參閱如何解決 GetCurrentTime 和/或 TRY 意義不明的狀況?。 |
C++編譯器會產生「winrt::impl::produce<D,I> 無法具現化抽象類別,因為遺漏 GetBindingConnector」。 | 您需要 #include <winrt/Windows.UI.Xaml.Markup.h> 。 |
C++ 編譯器產生「錯誤 C2039:'promise_type': 不是 'std::experimental::coroutine_traits<void>' 的成員」。 | 您的協同程式需要傳回非同步作業物件或 winrt::fire_and_forget。 請參閱並行和非同步作業。 |
您的專案會產生「模稜兩可的 'PopulatePropertyInfoOverride' 存取」。 | 當您在 IDL 中宣告一個基底類別,並在 XAML 標記中宣告不同基底類別時,就會發生此錯誤。 |
第一次載入 C++/WinRT 解決方案時產生「專案 'MyProject.vcxproj' 組態 'Debug|x86' 的 Designtime 建置失敗。IntelliSense 可能無法使用。」 | 經過第一次建置之後,此 IntelliSense 問題就會解決。 |
註冊委派時嘗試指定 winrt::auto_revoke 會產生 winrt::hresult_no_interface 例外狀況。 | 請參閱如果您的自動撤銷委派無法註冊。 |
在 C++/WinRT 應用程式中,當取用使用 XAML 的 C# Windows 執行階段元件時,編譯器會產生形式為「'MyNamespace_XamlTypeInfo': 不是 'winrt::MyNamespace' 成員」的錯誤,其中 MyNamespace 是 Windows 執行階段元件命名空間的名稱。 | 在取用 C++/WinRT 應用程式的 pch.h 中,視適當情況新增 #include <winrt/MyNamespace.MyNamespace_XamlTypeInfo.h> 以取代 MyNamespace。 |
在 Visual Studio 的 C++/WinRT 專案中,IntelliSense 會產生形式為「錯誤 E1696:無法開啟原始碼檔案」的錯誤。 | 至少編譯新建立的專案一次。 然後在原始程式碼編輯器中以滑鼠右鍵按一下 >[重新掃描]>[重新掃描檔案]。 這會解決所有 IntelliSense 錯誤,包括 E1696。 |
注意
如果本主題無法解答您的問題,則您可藉由造訪 Visual Studio C++ 開發人員社群,或在 Stack Overflow 上使用 c++-winrt
標籤來尋找說明。