排查C++/WinRT 问题

注释

有关安装和使用 C++/WinRT Visual Studio 扩展(VSIX)(提供项目模板支持)的信息,请参阅 Visual Studio 对 C++/WinRT 的支持

本主题被放在前面,以便你能马上注意到它,即使你还不需要它。 以下故障排除症状和补救措施表可能对你是削减新代码还是移植现有应用都很有帮助。 如果要移植,并且你渴望向前推进并进入项目生成和运行的阶段,则可以通过注释或删除导致问题的任何非基本代码进行注释或删除,然后稍后返回偿还债务,从而暂时取得进展。

有关常见问题解答的列表,请参阅 常见问题解答

排查 XAML 问题

XAML 分析异常可能难以诊断,尤其是在异常中没有有意义的错误消息时。 确保调试器配置为捕获首次异常(以便尝试及早捕获解析异常)。 您可以在调试器中检查异常变量,以确定 HRESULT 或消息是否包含任何有用的信息。 此外,请检查 Visual Studio 的输出窗口,了解 XAML 分析器输出的错误消息。

如果你的应用程序终止,并且你所知道的是在 XAML 标记解析期间引发了未经处理的异常,那么这可能是由于通过键引用了缺失的资源导致的。 或者,这可能是在 UserControl、自定义控件或自定义布局面板内引发的异常。 最后的手段是二进制拆分。 从 XAML 页面删除大约一半的标记,然后重新运行应用。 然后,你将知道错误是出在你删除的一半(现在应当恢复)的内容中,还是在你未删除的一半中。 通过拆分出包含错误的部分,重复这个过程,直到找到具体的问题。

症状和补救措施

症状 补救
在运行时引发异常,HRESULT 值为 REGDB_E_CLASSNOTREGISTERED。 请参阅 ,了解为什么会收到“类未注册”的异常情况。
C++编译器生成了错误:“'implements_type' 不是 ‘<’ 投影类型 ‘>’ 的任何直接或间接基类的成员”。 调用 时,如果使用未限定命名空间的实现类型名称(例如,MyRuntimeClass)来进行,而尚未包含该类型的头文件,可能会发生这种情况。 编译器将 MyRuntimeClass 解释为投影类型。 解决方案是为您的实现类型包括相应的标头(例如MyRuntimeClass.h)。
C++编译器生成错误“尝试引用已删除的函数”。 当你调用 来进行 并且将作为模板参数传递的实现类型具有 = 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 的 “新建项目” 对话框中安装 Windows 通用工具以进行 C++ 开发。 如果这无法解决问题,则项目可能依赖于 C++/WinRT Visual Studio 扩展(VSIX)(请参阅 Visual Studio 对 C++/WinRT 的支持)。
Windows 应用认证工具包测试生成一个错误,即其中一个运行时类“不派生自 Windows 基类”。所有可组合类最终必须派生自 Windows 命名空间中的类型”。 在应用程序中声明的任何派生自基类的运行时类被称为 可组合 类。 可组合类的最终基类必须是源自 Windows.* 命名空间的类型;例如 ,Windows.UI.Xaml.DependencyObject。 请参阅 XAML 控件;有关更多详细信息,请绑定到 C++/WinRT 属性
对于 EventHandler 或 TypedEventHandler 的委托特化,C++ 编译器会生成“T 必须是 WinRT 类型”错误。 请考虑使用 winrt::delegate<...T>。 请参阅 C++/WinRT中的 创作事件。
对于 Windows Runtime 异步操作专用化,C++ 编译器生成 "T 必须是 WinRT 类型" 错误。 请考虑改为返回并行模式库(PPL)任务。 参见 并发和异步操作
调用 winrt::xaml_typename时,C++编译器生成“T 必须为 WinRT 类型”错误。 使用投影类型 winrt::xaml_typename(例如,使用 BgLabelControlApp::BgLabelControl),而不是使用实现类型(例如,不要使用 BgLabelControlApp::implementation::BgLabelControl)。 请参阅 XAML 自定义(模板化)控件
C++编译器生成“错误 C2220:警告被视为错误 - 未生成'object'文件”。 更正警告,或将 C/C++>常规>的“将警告视为错误” 设置为 No (/WX-)
应用崩溃,因为C++/WinRT 对象中的事件处理程序在对象被销毁后调用。 请参阅 使用事件处理委托安全地访问此 指针
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++编译器生成“error C3861:”from_abi“:找不到标识符”,以及源自 base.h 的其他错误。 如果使用 Visual Studio 2017(版本 15.8.0 或更高版本),并且面向 Windows SDK 版本 10.0.17134.0(Windows 10 版本 1803),则可能会出现此错误。 面向更高版本的 Windows SDK,或设置项目属性 C/C++语言一致性模式:如果没有(如果项目属性 C/C++语言命令行其他选项,则不会显示任何(如果 /宽松 出现在项目属性命令行中, 然后删除它。
C++编译器生成“error C2039:”IUnknown“:不是”全局命名空间“的成员 请参阅 如何将C++/WinRT 项目重定向到更高版本的 Windows SDK
C++链接器生成“错误LNK2019:未解析的外部符号_WINRT_CanUnloadNow@0在函数_VSDesignerCanUnloadNow@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上的 标记来找到帮助。