C++/WinRT 问题疑难解答Troubleshooting C++/WinRT issues

备注

有关安装和使用 C++/WinRT Visual Studio 扩展 (VSIX)(提供项目模板支持)的信息,请参阅 适用于 C++/WinRT 的 Visual Studio 支持For info about installing and using the C++/WinRT Visual Studio Extension (VSIX) (which provides project template support) see Visual Studio support for C++/WinRT.

将本主题放在前面是为了让你可以立即意识到它,即使你现在尚不需要它。This topic is up front so that you're aware of it right away; even if you don't need it yet. 无论你是要削减新代码还是要移植现有应用,下面的症状排查和补救措施表都可能对你有帮助。The table of troubleshooting symptoms and remedies below may be helpful to you whether you're cutting new code or porting an existing app. 如果你进行移植,并且迫不及待想要取得进展并到达项目生成和运行的阶段,则你可以通过注释掉或去掉任何导致出现问题的非必要代码并在稍后回来进行修补的方式来暂时向前继续。If you're porting, and you're eager to forge ahead and get to the stage where your project builds and runs, then you can make temporary progress by commenting or stubbing out any non-essential code that's causing issues, and then returning to pay off that debt later.

有关常见问题的列表,请参阅常见问题解答For a list of frequently-asked questions, see Frequently-asked questions.

跟踪 XAML 问题Tracking down XAML issues

XAML 分析异常可能很难进行诊断—特别是在此类异常中没有含义明确的错误消息时。XAML parse exceptions can be difficult to diagnose—particularly if there are no meaningful error messages within the exception. 请确保已将调试程序配置为捕获第一轮异常(以便试图捕获早期的分析异常)。Make sure that the debugger is configured to catch first-chance exceptions (to try and catch the parsing exception early on). 你可以检查调试程序中的异常变量,以确定 HRESULT 或消息中是否具有任何有用的信息。You may be able to inspect the exception variable in the debugger to determine whether the HRESULT or message has any useful information. 也可以检查 Visual Studio 的输出窗口,以获取由 XAML 分析器输出的错误消息。Also, check Visual Studio's output window for error messages output by the XAML parser.

如果应用终止,并且你只知道在 XAML 标记分析过程中引发了未经处理的异常,则此错误可能是由于(通过键)引用了缺失的资源。If your app terminates and all you know is that an unhandled exception was thrown during XAML markup parsing, then that could be the result of a reference (by key) to a missing resource. 或者,它可以是在 UserControl、自定义控件或自定义布局面板内部引发的异常。Or, it could be an exception thrown inside a UserControl, a custom control, or a custom layout panel. 最后一项措施是进行二进制拆分。A last resort is a binary split. 从 XAML 页面中删除大约一半标记并重新运行应用。Remove about half of the markup from a XAML Page and re-run the app. 然后,你将知道错误是在已删除的那一半中(你现在应该在任何情况下恢复)还是在未删除的那一半中。You will then know whether the error is somewhere inside the half you removed (which you should now restore in any case) or in the half you did not remove. 通过拆分包含错误的那一半来重复此过程,依此类推,直到完全解决了问题。Repeat the process by splitting the half that contains the error, and so on, until you've zeroed in on the issue.

症状和补救方法Symptoms and remedies

症状Symptom 纠正方法Remedy
在运行时抛出异常,并显示 HRESULT 值 REGDB_E_CLASSNOTREGISTERED。An exception is thrown at runtime with a HRESULT value of REGDB_E_CLASSNOTREGISTERED. 请参阅为什么会收到“类未注册”异常?See Why am I getting a "class not registered" exception?.
C++ 编译器生成以下错误:“‘implements_type’: 不是 <投影类型>** 的任何直接或间接基类的成员”。The C++ compiler produces the error "'implements_type': is not a member of any direct or indirect base class of '<projected type>'". 使用实现类型的未限定命名空间的名称(例如“MyRuntimeClass”)来调用“make”时,如果没有包括该类型的标头,就会出现此错误********。This can happen when you call make with the namespace-unqualified name of your implementation type (MyRuntimeClass, for example), and you haven't included that type's header. 编译器会将“MyRuntimeClass”解释为投影类型****。The compiler interprets MyRuntimeClass as the projected type. 解决办法是包括实现类型的标头(例如 MyRuntimeClass.h)。The solution is to include the header for your implementation type (MyRuntimeClass.h, for example).
C++ 编译器生成以下错误:“正在尝试引用已删除的函数”**。The C++ compiler produces the error "attempting to reference a deleted function". 调用“make”并且你作为模板参数传递的实现类型具有 = delete 默认构造函数时,就会出现此错误****。This can happen when you call make and the implementation type that you pass as the template parameter has an = delete default constructor. 编辑实现类型的标头文件并将 = delete 更改为 = defaultEdit the implementation type's header file and change = delete to = default. 你还可以为运行时类添加一个构造函数到 IDL 中。You can also add a constructor into the IDL for the runtime class.
你已经实现 INotifyPropertyChanged,但 XAML 绑定没有更新(UI 没有订阅 PropertyChanged)********。You've implemented INotifyPropertyChanged, but your XAML bindings are not updating (and the UI is not subscribing to PropertyChanged). 请记得在 XAML 标记中的绑定表达式上设置 Mode=OneWay(或 TwoWay)。Remember to set Mode=OneWay (or TwoWay) on your binding expression in XAML markup. 请参阅 XAML 控件;绑定到 C++/WinRT 属性See XAML controls; bind to a C++/WinRT property.
你将一个 XAML 项目控件绑定到一个可观测集合,在运行时引发了异常并显示消息“参数不正确”。You're binding a XAML items control to an observable collection, and an exception is thrown at runtime with the message "The parameter is incorrect". 在 IDL 和实现中,将任何可观测的集合声明为“Windows.Foundation.Collections.IVector”****。In your IDL and your implementation, declare any observable collection as the type Windows.Foundation.Collections.IVector. 但返回一个实现“Windows.Foundation.Collections.IObservableVector”(其中的 T 是元素类型)的对象****。But return an object that implements Windows.Foundation.Collections.IObservableVector, where T is your element type. 请参阅 XAML 项目控件;绑定到 C++/WinRT 集合See XAML items controls; bind to a C++/WinRT collection.
C++ 编译器生成以下形式的错误:“‘MyImplementationType_base<MyImplementationType>’: 没有适当的默认构造函数可用”**。The C++ compiler produces an error of the form "'MyImplementationType_base<MyImplementationType>': no appropriate default constructor available". 从具有特殊构造函数的类型派生时会出现此错误。This can happen when you have derived from a type that has a non-trivial constructor. 派生类型的构造函数需要传递基类型的构造函数所需的参数。Your derived type's constructor needs to pass along the parameters that the base type's constructor needs. 有关工作示例,请参阅从具有特殊构造函数的类型派生For a worked example, see Deriving from a type that has a non-trivial constructor.
C++ 编译器生成以下错误:“无法从‘const std::vector<std::wstring,std::allocator<_Ty>>’转换为‘const winrt::param::async_iterable<winrt::hstring> &’”。The C++ compiler produces the error "cannot convert from 'const std::vector<std::wstring,std::allocator<_Ty>>' to 'const winrt::param::async_iterable<winrt::hstring> &'". 将 std::wstring 的 std::vector 传递给需要一个集合的 Windows 运行时 API 时,将会出现此错误。This can happen when you pass a std::vector of std::wstring to a Windows Runtime API that expects a collection. 有关更多信息,请参阅标准 C++ 数据类型和 C++/WinRTFor more info, see Standard C++ data types and C++/WinRT.
C++ 编译器生成以下错误:“无法从‘const std::vector<<_Ty>>’转换为‘const winrt::param::async_iterable<winrt::hstring> &’”。The C++ compiler produces the error "cannot convert from 'const std::vector<winrt::hstring,std::allocator<_Ty>>' to 'const winrt::param::async_iterable<winrt::hstring> &'". 将 winrt::hstring 的 std::vector 传递给需要一个集合的异步 Windows 运行时 API 时,如果没有将相应的矢量复制或移动到异步被调用方,就会出现此错误。This can happen when you pass a std::vector of winrt::hstring to an asynchronous Windows Runtime API that expects a collection, and you've neither copied nor moved the vector to the async callee. 有关更多信息,请参阅标准 C++ 数据类型和 C++/WinRTFor more info, see Standard C++ data types and C++/WinRT.
打开项目时,Visual Studio 生成错误“该项目的应用程序未安装”**。When opening a project, Visual Studio produces the error "The application for the project is not installed". 需要从 Visual Studio 的“新建项目”对话框中安装“用于 C++ 开发的 Windows 通用工具”(如果你尚未这样做的话)********。If you haven't already, you need to install Windows Universal tools for C++ development from within Visual Studio's New Project dialog. 如果上述方法未能解决问题,则项目可能依赖于 C++/WinRT Visual Studio Extension (VSIX)(请参阅 Visual Studio 对于 C++/WinRT 的支持)。If that doesn't resolve the issue, then the project may depend on the C++/WinRT Visual Studio Extension (VSIX) (see Visual Studio support for C++/WinRT.
Windows 应用认证工具包测试将产生一个错误,表示一个运行时类“不是派生自 Windows 基类。所有可组合类必须最终派生自 Windows 命名空间中的类型”。The Windows App Certification Kit tests produce an error that one of your runtime classes "does not derive from a Windows base class. All composable classes must ultimately derive from a type in the Windows namespace". 从基类派生的任何运行时类(在应用程序中声明)都称为可组合类**。Any runtime class (that you declare in your application) that derives from a base class is known as a composable class. 可组合类的最终基类必须是源自 Windows.* 命名空间的类型;例如,Windows.UI.Xaml.DependencyObject****。The ultimate base class of a composable class must be a type originating in a Windows.* namespace; for example, Windows.UI.Xaml.DependencyObject. 有关更多详细信息,请参阅 XAML 控件;绑定到 C++/WinRT 属性See XAML controls; bind to a C++/WinRT property for more details.
对于 EventHandler 或 TypedEventHandler 委托专用化,C++ 编译器产生“T 必须是 WinRT 类型”错误。The C++ compiler produces a "T must be WinRT type" error for an EventHandler or TypedEventHandler delegate specialization. 请考虑改为使用“winrt::delegate<…T>”****。Consider using winrt::delegate<...T> instead. 请参阅 在 C++/WinRT 中创作事件See Author events in C++/WinRT.
对于 Windows 运行时异步操作专用化,C++ 编译器产生“T 必须是 WinRT 类型”错误。The C++ compiler produces a "T must be WinRT type" error for a Windows Runtime asynchronous operation specialization. 请考虑改为返回并行模式库 (PPL) 任务****。Consider returning a Parallel Patterns Library (PPL) task instead. 请参阅并发操作和异步操作See Concurrency and asynchronous operations.
在调用 winrt::xaml_typename 时,C++ 编译器会产生“T 必须是 WinRT 类型”错误。The C++ compiler produces a "T must be WinRT type" error when you call winrt::xaml_typename. 请将投影类型与 winrt::xaml_typename 配合使用(例如,使用 BgLabelControlApp::BgLabelControl),而不是实现类型(例如,不要使用 BgLabelControlApp::implementation::BgLabelControl) 。Use the projected type with winrt::xaml_typename (for example, use BgLabelControlApp::BgLabelControl), and not the implementation type(for example, don't use BgLabelControlApp::implementation::BgLabelControl). 请参阅 XAML 自定义(模板化)控件See XAML custom (templated) controls.
C++ 编译器生成“错误 C2220: 视为错误的警告 - 未生成 object 文件”**。The C++ compiler produces "error C2220: warning treated as error - no 'object' file generated". 更正警告,或者将“C/C++” > “常规” > “将警告视为错误”设置为“否(/WX-)” 。Either correct the warning, or set C/C++ > General > Treat Warnings As Errors to No (/WX-).
应用发生崩溃,因为在 C++/WinRT 对象销毁后调用了其中的一个事件处理程序。Your app crashes because an event handler in your C++/WinRT object is called after the object has been destroyed. 请参阅使用事件处理委托安全访问该指针**。See Safely accessing the this pointer with an event-handling delegate.
C++ 编译器产生“错误 C2338: 此项仅用于弱引用支持”。The C++ compiler produces "error C2338: This is only for weak ref support". 你请求针对某个类型的弱引用,该类型将“winrt::no_weak_ref”标记结构作为模板参数传递给其基类****。You're requesting a weak reference for a type that passed the winrt::no_weak_ref marker struct as a template argument to its base class. 请参阅选择退出弱引用支持See Opting out of weak reference support.
C++ 链接器生成“错误 LNK2019:未解析的外部符号”The C++ linker produces "error LNK2019: Unresolved external symbol" 请参阅为什么链接器会提供“LNK2019:未解析的外部符号”错误?See Why is the linker giving me a "LNK2019: Unresolved external symbol" error?.
与 C++/WinRT 一起使用时,LLVM 和 Clang 工具链会生成错误。The LLVM and Clang toolchain produces errors when used with C++/WinRT. 我们不支持适用于 C++/WinRT 的 LLVM 和 Clang 工具链,但是如果你想模拟如何在内部使用它,则可尝试进行实验,如是否可以结合使用 C++/WinRT 和 LLVM/Clang 进行编译?中所述。We don't support the LLVM and Clang toolchain for C++/WinRT, but if you wanted to emulate how we use it internally, then you could try an experiment such as the one described in Can I use LLVM/Clang to compile with C++/WinRT?.
C++ 编译器为投影类型生成“没有适当的默认构造函数”**。The C++ compiler produces "no appropriate default constructor available" for a projected type. 如果试图延迟运行时类对象的初始化,或者在同一个项目中使用和实现运行时类,则需要调用 std::nullptr_t 构造函数。If you're trying to delay the initialization of a runtime class object, or to consume and implement a runtime class in the same project, then you'll need to call the std::nullptr_t constructor. 有关详细信息,请参阅通过 C++/WinRT 使用 APIFor more info, see Consume APIs with C++/WinRT.
C++ 编译器生成“错误 C3861:'from_abi':未找到标识符”,以及源自 base.h 的其他错误****。The C++ compiler produces "error C3861: 'from_abi': identifier not found", and other errors originating in base.h. 如果使用 Visual Studio 2017(版本 15.8.0 或更高版本),并且要面向 Windows SDK 版本 10.0.17134.0(Windows 10 版本 1803),则可能会看到此错误。You may see this error if you are using Visual Studio 2017 (version 15.8.0 or higher), and targeting the Windows SDK version 10.0.17134.0 (Windows 10, version 1803). 要么定位 Windows SDK 的更新(更符合)版本,要么设置项目属性“C/C++” > “语言” > “一致性模式: 否”(此外,如果“/permissive-”出现在“其他选项”下的项目属性“C/C++” > “语言” > “命令行”中,将其删除) 。Either target a later (more conformant) version of the Windows SDK, or set project property C/C++ > Language > Conformance mode: No (also, if /permissive- appears in project property C/C++ > Language > Command Line under Additional Options, then delete it).
C++ 编译器会生成“错误 C2039:IUnknown: 不是 `global namespace 的成员”。The C++ compiler produces "error C2039: 'IUnknown': is not a member of '`global namespace''". 请参阅如何将 C++/WinRT 项目重新定位到更高版本的 Windows SDKSee How to retarget your C++/WinRT project to a later version of the Windows SDK.
C++ 链接器生成“错误 LNK2019: 函数 _VSDesignerCanUnloadNow@0 中引用了未解析的外部符号 _WINRT_CanUnloadNow@0”**The C++ linker produces "error LNK2019: unresolved external symbol _WINRT_CanUnloadNow@0 referenced in function _VSDesignerCanUnloadNow@0" 请参阅如何将 C++/WinRT 项目重新定位到更高版本的 Windows SDKSee How to retarget your C++/WinRT project to a later version of the Windows SDK.
生成过程生成错误消息“C++/WinRT VSIX 不再提供项目生成支持。请将项目引用添加到 Microsoft.Windows.CppWinRT Nuget 包”。The build process produces the error message The C++/WinRT VSIX no longer provides project build support. Please add a project reference to the Microsoft.Windows.CppWinRT Nuget package. 请在项目中安装 Microsoft.Windows.CppWinRT NuGet 包。Install the Microsoft.Windows.CppWinRT NuGet package into your project. 有关详细信息,请参阅早期版本的 VSIX 扩展For details, see Earlier versions of the VSIX extension.
C++ 链接器生成“错误 LNK2019: 未解析的外部符号”,并提及“winrt::impl::consume_Windows_Foundation_Collections_IVector”****。The C++ linker produces error LNK2019: unresolved external symbol, with a mention of winrt::impl::consume_Windows_Foundation_Collections_IVector. C++/WinRT 2.0 开始,如果在 Windows 运行时集合上使用基于范围的 for,那么现在需要 #include <winrt/Windows.Foundation.Collections.h>As of C++/WinRT 2.0, If you're using a range-based for on a Windows Runtime collection, then you'll now need to #include <winrt/Windows.Foundation.Collections.h>.
C++ 编译器会生成“错误 C4002:类函数宏的调用 GetCurrentTime 参数太多”。The C++ compiler produces "error C4002: Too many arguments for function-like macro invocation GetCurrentTime". 请参阅如何使用 GetCurrentTime 和/或 TRY 解析多义性?See How do I resolve ambiguities with GetCurrentTime and/or TRY?.
C++ 编译器生成“错误 C2334: '{' 的前面有意外标记;跳过明显的函数体”**。The C++ compiler produces "error C2334: unexpected token(s) preceding '{'; skipping apparent function body". 请参阅如何使用 GetCurrentTime 和/或 TRY 解析多义性?See How do I resolve ambiguities with GetCurrentTime and/or TRY?.
C++ 编译器生成“winrt::impl::produce<D,I> 无法实例化抽象类,因为缺少 GetBindingConnector**”。The C++ compiler produces "winrt::impl::produce<D,I> cannot instantiate abstract class, due to missing GetBindingConnector". 你需要 #include <winrt/Windows.UI.Xaml.Markup.h>You need to #include <winrt/Windows.UI.Xaml.Markup.h>.
C++ 编译器生成“错误 C2039: 'promise_type': 不是 'std::experimental::coroutine_traits' 的成员**”。The C++ compiler produces "error C2039: 'promise_type': is not a member of 'std::experimental::coroutine_traits'". 协同例程需要返回异步操作对象或 winrt::fire_and_forgetYour coroutine needs to return either an asynchronous operation object, or winrt::fire_and_forget. 请参阅并发操作和异步操作See Concurrency and asynchronous operations.
项目生成“'PopulatePropertyInfoOverride' 的访问不明确**”。Your project produces "ambiguous access of 'PopulatePropertyInfoOverride'". 在 IDL 中声明一个基类,同时在 XAML 标记中声明一个不同的基类时,可能发生此错误。This error can occur when you declare one base class in your IDL and a different base class in your XAML markup.
首次加载 C++/WinRT 解决方案时生成“项目 'MyProject.vcxproj' 的配置 'Debug|x86' 的设计时生成失败。IntelliSense 可能不可用。”。Loading a C++/WinRT solution for the first time produces "Designtime build failed for project 'MyProject.vcxproj' configuration 'Debug|x86'. IntelliSense might be unavailable.". 在首次生成后,此 IntelliSense 问题会解决。This IntelliSense issue will resolve after you build for the first time.
在注册委托时尝试指定 winrt::auto_revoke 会生成 winrt::hresult_no_interface 异常。Attempting to specify winrt::auto_revoke when registering a delegate produces a winrt::hresult_no_interface exception. 请参阅如果“自动撤销”委托无法注册See If your auto-revoke delegate fails to register.
在 C++/WinRT 应用中,当使用利用 XAML 的 C# Windows 运行时组件时,编译器会生成一个错误,格式为:"'MyNamespace_XamlTypeInfo': 不是 'winrt::MyNamespace' 的成员"—其中 MyNamespace 是 Windows 运行时组件命名空间的名称。In a C++/WinRT app, when consuming a C# Windows Runtime component that uses XAML, the compiler produces an error of the form "'MyNamespace_XamlTypeInfo': is not a member of 'winrt::MyNamespace'"—where MyNamespace is the name of the Windows Runtime component's namespace. 在 C++/WinRT 应用中的 pch.h 中,根据需要添加 #include <winrt/MyNamespace.MyNamespace_XamlTypeInfo.h>— 来替换 MyNamespace。In pch.h in the consuming C++/WinRT app, add #include <winrt/MyNamespace.MyNamespace_XamlTypeInfo.h>—replacing MyNamespace as appropriate.

备注

如果本主题未解答你的问题,可以访问 Visual Studio C++ 开发人员社区或使用 c++-winrtStack Overflow 上的标记来获得帮助。If this topic didn't answer your question, then you might find help by visiting the Visual Studio C++ developer community, or by using the c++-winrt tag on Stack Overflow.