Устранение неполадок с 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: не является прямым или косвенным базовым классом для <projected type>". Это может произойти, когда вы вызываете make с именем типа реализации, не соответствующим пространству имен (например, MyRuntimeClass), и не включили заголовок этого типа. Компилятор интерпретирует MyRuntimeClass в качестве проецируемого типа. Чтобы устранить ошибку, включите заголовок для вашего типа реализации (например, MyRuntimeClass.h).
Компилятор C++ выдает ошибку "предпринята попытка ссылки на удаленную функцию". Это может произойти, когда вы вызываете make и тип реализации, который вы передаете в качестве параметра шаблона, имеет конструктор по умолчанию = delete. Измените файл заголовка типа реализации и замените = delete на = default. Вы также можете добавить в код IDL конструктор для класса среды выполнения.
Вы реализовали INotifyPropertyChanged, но привязки XAML не обновляются (и пользовательский интерфейс не подписывается на событие PropertyChanged). Не забудьте установить Mode=OneWay (или TwoWay) в выражении привязки в разметке XAML. См. сведения в статье Элементы управления 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::vector std::wstring API-интерфейсу среды выполнения Windows, который ожидает коллекцию. Дополнительные сведения см. в статье Стандартные типы данных C++ и C++/WinRT.
Компилятор C++ выдает ошибку "невозможно выполнить преобразование из const std::vector<winrt::hstring,std::allocator<_Ty>> в const winrt::param::async_iterable<winrt::hstring> &". Это может произойти при передаче std::vector winrt::hstring асинхронному API-интерфейсу среды выполнения Windows, который ожидает коллекцию, при этом вектор не скопирован и не перемещен в асинхронный вызываемый. Дополнительные сведения см. в статье Стандартные типы данных C++ и C++/WinRT.
При открытии проекта Visual Studio выдает ошибку "Приложение для проекта не установлено". Если вы еще не сделали этого, необходимо установить средства универсальной платформы Windows для разработки на C++ в диалоговом окне Visual Studio Новый проект. Если это не устраняет проблему, то проект может зависеть от расширения C++/WinRT для Visual Studio (VSIX) (см. сведения в разделе о поддержке C++/WinRT в Visual Studio.
Тесты комплекта сертификации приложений Для Windows создают ошибку, что один из классов среды выполнения "не является производным от базового класса Windows. Все составные классы должны в конечном итоге быть производными от типа в пространстве имен Windows. Любой класс среды выполнения (объявленный в приложении), который является производным от базового класса, называется составным. Исходный базовый класс для составного класса должен быть типом из пространства имен Windows.*, например, Windows.UI.Xaml.DependencyObject. Дополнительные сведения см. в статье Элементы управления XAML; привязка к свойству C++/WinRT.
Компилятор C++ создает ошибку T must be WinRT type (T требуется тип WinRT) для специализации делегата EventHandler или TypedEventHandler. Рассмотрите возможность использования winrt::delegate<...T>. См. сведения в статье Создание событий в C++/WinRT.
Компилятор C++ создает ошибку T must be WinRT type (T требуется тип WinRT) для специализации асинхронной операции среды выполнения Windows. Рассмотрите возможность возврата класса task библиотеки параллельных шаблонов (PPL). См. сведения в статье Параллельная обработка и асинхронные операции с помощью C++/WinRT.
Компилятор C++ создает ошибку T must be WinRT type (T требуется тип WinRT) при вызове winrt::xaml_typename. Используйте проецируемый тип с winrt::xaml_typename (например, используйте BgLabelControlApp::BgLabelControl), а не тип реализации (например, не используйте BgLabelControlApp::implementation::BgLabelControl). См. статью Создание (на основе шаблона) пользовательских элементов управления XAML с помощью C++/WinRT.
Компилятор 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. Мы не поддерживаем цепочку инструментов LLVM и Clang для C++/WinRT, но если нужно эмулировать использование этой проекции на внутреннем уровне, то вы можете попробовать эксперимент, который описан в разделе Можно ли использовать LLVM/Clang для компиляции с C++/WinRT?.
Компилятор C++ выдает ошибку "нет подходящего конструктора по умолчанию" для проецируемого типа. Если вы пытаетесь отложить инициализацию объекта класса среды выполнения или использовать и реализовать класс среды выполнения в том же проекте, вам нужно вызвать конструктор std::nullptr_t. Дополнительные сведения см. в статье Использование API-интерфейсов с помощью C++/WinRT.
Компилятор C++ выдает ошибку C3861 "from_abi: идентификатор не найден" и другие ошибки, полученные в base.h. Эта ошибка может возникнуть, если вы используете Visual Studio 2017 (версия 15.8.0 или более поздней) и предназначение пакета SDK для Windows версии 10.0.17134.0 (Windows 10 версии 1803). Следует разрабатывать проект с более поздней (лучше соответствующей) версией Windows SDK или задать свойство проекта C/C++>Язык>Режим совместимости: Нет (кроме того, если параметр /permissive- отображается в свойстве проекта C/C++>Язык>Командная строка в разделе Дополнительные параметры, удалите его).
Компилятор C++ создает"Ошибка C2039: 'IUnknown': не является членом '`глобального пространства имен''". См. сведения в разделе How to retarget your C++/WinRT project to a later version of the Windows SDK (Как изменить целевую платформу проекта C++/WinRT на более позднюю версию Windows SDK).
Компоновщик C++ создает "ошибку LNK2019: неразрешенный внешний символ _WINRT_CanUnloadNow@0, на который указывает ссылка в функции _VSDesignerCanUnloadNow@0" См. сведения в разделе How to retarget your C++/WinRT project to a later version of the Windows SDK (Как изменить целевую платформу проекта C++/WinRT на более позднюю версию Windows SDK).
Процесс сборки выдает сообщение об ошибке C++/WinRT VSIX больше не предоставляет поддержку сборке проекта. Добавьте ссылку проекта на пакет Microsoft.Windows.CppWinRT Nuget. Установите пакет NuGet Microsoft.Windows.CppWinRT в проект. Дополнительные сведения см. в разделе Earlier versions of the VSIX extension (Более ранние версии расширения VSIX).
Компоновщик C++ создает ошибку "LNK2019: неразрешенный внешний символ" с упоминанием winrt::impl::consume_Windows_Foundation_Collections_IVector. Начиная с версии C++WinRT 2.0, если вы используете основанный на диапазоне параметр for в коллекции среды выполнения Windows, то теперь нужно добавить #include <winrt/Windows.Foundation.Collections.h>.
Компилятор C++ создает ошибку C4002: слишком много аргументов для вызова макросов GetCurrentTime, например функции. См. часто задаваемый вопрос о том, как устранить неоднозначности с GetCurrentTime и (или) TRY.
Компилятор C++ выдает сообщение Error C2334: unexpected token(s) preceding {; skipping apparent function body (Ошибка C2334: непредвиденные лексемы перед {; пропуск вероятного тела функции). См. часто задаваемый вопрос о том, как устранить неоднозначности с GetCurrentTime и (или) TRY.
Компилятор C++ выдает сообщение winrt::impl::produce<D,I> cannot instantiate abstract class, due to missing GetBindingConnector (winrt::impl::produce не может создать экземпляр абстрактного класса из-за отсутствия GetBindingConnector). Необходимо добавить #include <winrt/Windows.UI.Xaml.Markup.h>.
Компилятор C++ выдает сообщение "ошибка C2039: 'promise_type': не является членом 'std::experimental::coroutine_traits<недействительный>'". Сопрограмма должна возвращать либо объект асинхронной операции, либо winrt::fire_and_forget. См. сведения в статье Параллельная обработка и асинхронные операции с помощью C++/WinRT.
При работе с проектом появляется сообщение: Ambiguous access of PopulatePropertyInfoOverride (Неоднозначный уровень доступа PopulatePropertyInfoOverride). Эта ошибка может возникать при объявлении одного базового класса в IDL и другого базового класса в разметке XAML.
При первом запуске решения C++/WinRT отображается сообщение "Не удалось выполнить сборку designtime для проекта 'MyProject.vcxproj' конфигурации 'Debug|x86'. IntelliSense может быть недоступна.". Эта проблема с IntelliSense будет устранена после первого выполнения сборки.
Попытка задать winrt::auto_revoke при регистрации делегата вызывает исключение winrt::hresult_no_interface. См. раздел о сбое регистрации автоматически отзываемого делегата.
В приложении C++/WinRT, при работе с компонентом C# среды выполнения Windows, который использует XAML, компилятор создает ошибку в форме "'MyNamespace_XaRuntime componentmlTypeInfo': не является членом 'winrt::MyNamespace'"— где MyNamespace — имя пространства имен компонента среды выполнения Windows. В pch.hфайле используемого приложения C++/WinRT, добавьте #include <winrt/MyNamespace.MyNamespace_XamlTypeInfo.h>, заменив MyNamespace соответствующим образом.
В проекте C++/WinRT в Visual Studio IntelliSense выдает ошибку error E1696: cannot open source file (Ошибка E1696. Не удается открыть исходный файл). Скомпилируйте созданный проект по крайней мере один раз. Затем щелкните правой кнопкой мыши в редакторе исходного кода и выберите >Повторное сканирование>Отсканировать файл повторно. Это позволит устранить все ошибки IntelliSense, включая ошибку E1696.

Примечание.

Если в этой статье вы не нашли ответы на свои вопросы, можете перейти к сообществу разработчиковVisual Studio C++ или воспользоваться тегом c++-winrt на сайте Stack Overflow.