Solución de problemas de C++/WinRT

Nota

Para más información sobre cómo instalar y usar la Extensión de Visual Studio (VSIX) de C++/WinRT (que proporciona compatibilidad de plantilla de proyecto), consulta Compatibilidad de Visual Studio para C++/WinRT.

Este tema se muestra por adelantado para que lo tengas en cuenta, aunque no lo necesites todavía. La siguiente tabla de síntomas y soluciones de problemas puede resultarte útil si vas a cortar nuevo código o portar una aplicación existente. Si estás portando, y deseas seguir avanzando y llegar a la etapa de creación y ejecución de tu proyecto, puedes progresar temporalmente comentando o anulando cualquier código no esencial que esté causando problemas, y volver después para restaurar lo que has quitado.

Para ver una lista de las preguntas más frecuentes, consulta Preguntas más frecuentes.

Seguimiento de problemas XAML

Las excepciones de análisis XAML pueden ser difíciles de diagnosticar, especialmente si no hay ningún mensaje de error significativo dentro de la excepción. Asegúrate de que el depurador está configurado para capturar las primeras excepciones (para probar y capturar la excepción de análisis desde el principio). Podrás inspeccionar la variable de excepción en el depurador para determinar si el mensaje o HRESULT tiene información útil. Asimismo, consulta la ventana de salida de Visual Studio para comprobar si presenta mensajes de error emitidos por el analizador XAML.

Si tu aplicación finaliza y todo lo que sabes es que se ha producido una excepción no controlada durante el análisis de marcado XAML, podría ser el resultado de una referencia (por clave) a un recurso que falta. O bien, podría tratarse de una excepción dentro de UserControl, un control personalizado o un panel de diseño personalizado. Un último recurso es una división binaria. Quita aproximadamente la mitad del marcado de una página XAML y vuelve a ejecutar la aplicación. De este modo, sabrás si el error está en la mitad que quitaste (que ahora debes restaurar en cualquier caso) o en la mitad que no quitaste. Repite el proceso dividiendo la mitad que contiene el error y así sucesivamente, hasta que reduzcas a cero el problema.

Síntomas y soluciones

Síntoma Solución
Se produce una excepción en tiempo de ejecución con un valor HRESULT de REGDB_E_CLASSNOTREGISTERED. Consulta ¿Por qué se muestra la excepción "clase no registrada"?
El compilador de C++ produce el error "'implements_type': no es un miembro de ninguna clase base directa o indirecta de '<tipo proyectado>'". Esto puede suceder cuando se llama a make con el nombre del espacio de nombres no completo de tu tipo de implementación (MyRuntimeClass, por ejemplo) y no has incluido el encabezado de dicho tipo. El compilador interpreta MyRuntimeClass como el tipo proyectado. La solución consiste en incluir el encabezado para el tipo de implementación (MyRuntimeClass.h, por ejemplo).
El compilador de C++ produce el error "se está intentando hacer referencia a una función eliminada". Esto puede suceder cuando se llama a make y el tipo de implementación que pasas como parámetro de plantilla tiene un constructor = delete predeterminado. Edita el archivo de encabezado del tipo de implementación y cambia = delete a = default. También puedes agregar un constructor al archivo IDL para la clase en tiempo de ejecución.
Has implementado INotifyPropertyChanged, pero tus enlaces de XAML no se actualizan (y la interfaz de usuario no se suscribe a PropertyChanged). Recuerda que tienes que establecer Mode=OneWay (o TwoWay) en tu expresión de enlace en marcado XAML. Consulta Controles XAML; enlazar a una propiedad C++/WinRT.
Vas a enlazar un control de elementos XAML a una colección observable y se produce una excepción en tiempo de ejecución con el mensaje "El parámetro no es correcto". En el IDL y la implementación, declare cualquier colección observable como el tipo Windows.Foundation.Collections.IVector<IInspectable>. Pero devuelve un objeto que implementa Windows.Foundation.Collections.IObservableVector<T>, donde T es el tipo de elemento. Consulta Controles de elementos XAML; enlazar a una colección C++/WinRT.
El compilador de C++ produce un error del formulario "'MyImplementationType_base<MyImplementationType>': no hay disponible un constructor predeterminado adecuado". Esto puede suceder si has derivado de un tipo que tiene un constructor no trivial. Tu constructor del tipo derivado debe pasar los parámetros que el constructor del tipo base necesita. Para obtener un ejemplo trabajado, consulta Derivar de un tipo que tiene un constructor no trivial.
El compilador de C++ produce el error"No se puede convertir de 'const std::vector<std::wstring,std::allocator<_Ty>>' a 'const winrt::param::async_iterable<winrt::hstring> &'". Esto puede suceder cuando se pasa std::vector de std::wstring a una API de Windows Runtime que espera una colección. Para más información, consulta Tipos de datos C++ estándar y C++/WinRT.
El compilador de C++ produce el error"No puede convertir de 'const std::vector<winrt::hstring,std::allocator<_Ty>>' a 'const winrt::param::async_iterable<winrt::hstring> &'". Esto puede suceder cuando se pasa std::vector de winrt::hstring a una API asincrónica de Windows Runtime que espera una colección y no has copiado ni movido el vector al destinatario asincrónico. Para más información, consulta Tipos de datos C++ estándar y C++/WinRT.
Al abrir un proyecto, Visual Studio genera el error "La aplicación del proyecto no está instalada". Si no lo has hecho todavía, debes instalar herramientas universales de Windows para el desarrollo de C++ desde el cuadro de diálogo Nuevo proyecto de Visual Studio. Si esto no resuelve el problema, el proyecto puede depender de la Extensión de Visual Studio (VSIX) para C++/WinRT (consulta Compatibilidad de Visual Studio para C++/WinRT).
Las pruebas del Kit de certificación de aplicaciones de Windows generan un error de que una de las clases en tiempo de ejecución "no se deriva de una clase base de Windows. Todas las clases que admiten composición deben derivar en última instancia de un tipo en el espacio de nombres de Windows". Cualquier clase en tiempo de ejecución (que declares en la aplicación) que se deriva de una clase base se conoce como una clase que admite composición. La clase base fundamental de una clase que admite composición debe ser un tipo que se origina en un espacio de nombres de Windows.*; por ejemplo, Windows.UI.Xaml.DependencyObject. Consulta Controles XAML; enlazar a una propiedad C++/WinRT para más información.
El compilador de C++ genera un error "T debe ser de tipo WinRT" para una especialización del delegado EventHandler o TypedEventHandler. Considera la posibilidad de utilizar winrt::delegate<... T> en su lugar. Consulta Crear eventos en C++/WinRT.
El compilador de C++ genera un error "T debe ser de tipo WinRT" para una especialización de la operación asincrónica de Windows Runtime. Considera la posibilidad de devolver una tarea de la biblioteca de patrones de procesamiento paralelo (PPL) en su lugar. Consulta Operaciones simultáneas y asincrónicas.
El compilador de C++ genera un error "T debe ser de tipo WinRT" cuando se llama a winrt::xaml_typename. Use el tipo proyectado con winrt::xaml_typename (por ejemplo, use BgLabelControlApp::BgLabelControl) y no el tipo de implementación (por ejemplo, no use BgLabelControlApp::implementation::BgLabelControl). Consulte Controles personalizados (con plantilla) de XAML.
El compilador de C++ genera el "error C2220: advertencia tratada como error - ningún archivo 'objeto' generado". Corrige la advertencia o establece C/C++>General>Tratar advertencias como errores en No (/WX-) .
La aplicación se bloquea porque se llama a un controlador de eventos en el objeto C++/WinRT un vez destruido el objeto. Consulta Acceso de forma segura al puntero this con un delegado de control de eventos.
El compilador de C++ genera el "error C2338: This is only for weak ref support (Esto es solo para compatibilidad con referencia débil) ". Estás solicitando una referencia débil para un tipo que ha pasado la estructura de marcador winrt::no_weak_ref como argumento de plantilla a su clase base. Consulta Rechazar el soporte de referencia débil.
El compilador de C++ genera el error consume_Something: function that returns 'auto' cannot be used before it is defined" (consume_Something. La función que devuelve 'auto' no se puede usar antes de definirse) Consulte ¿Por qué el compilador me devuelve el error "C3779: consume_Something: function that returns 'auto' cannot be used before it is defined" (C3779: consume_Something: la función que devuelve 'auto' no se puede usar antes de definirse)?
El enlazador de C++ genera el "error LNK2019: símbolo externo sin resolver" Consulta ¿Por qué el enlazador me da un "error LNK2019: símbolo externo sin resolver"?
La cadena de herramientas de LLVM y Clang produce errores cuando se usa con C++/WinRT. No admitimos la cadena de herramientas LLVM y Clang para C++/WinRT, pero si deseas emular cómo la utilizamos internamente, puedes intentar hacer un experimento, como el descrito en ¿Puedo usar LLVM/Clang para compilar con C++/WinRT?.
El compilador de C++ genera "no hay disponible un constructor predeterminado adecuado" para un tipo proyectado. Si estás intentando retrasar la inicialización de un objeto de clase en tiempo de ejecución, o consumir e implementar una clase en tiempo de ejecución en el mismo proyecto, debes llamar al constructor std::nullptr_t. Para obtener más información, consulta Consumir API con C++/WinRT.
El compilador de C++ genera el "error C3861: 'from_abi': no se encontró el identificador" y otros errores que se originan en base.h. Puede ver este error si usa Visual Studio 2017 (versión 15.8.0 o superior) y se dirige al SDK de Windows versión 10.0.17134.0 (Windows 10, versión 1803). Dirígete a una versión posterior (más compatible) del SDK de Windows o establece la propiedad del proyecto C/C++>Lenguaje>Modo de conformidad: No (además, si /permissive- aparece en la propiedad del proyecto C/C++>Lenguaje>Línea de comandos en Opciones adicionales, elimínalo).
El compilador de C++ genera el mensaje "error C2039: 'IUnknown': no es miembro del espacio de nombres global". Consulta Procedimientos para redirigir el proyecto de C++/WinRT a una versión posterior del SDK de Windows.
Si el enlazador de C++ devuelve el "error LNK2019: símbolo externo _WINRT_CanUnloadNow@0 sin resolver al que se hace referencia en la función _VSDesignerCanUnloadNow@0". Consulta Procedimientos para redirigir el proyecto de C++/WinRT a una versión posterior del SDK de Windows.
El proceso de compilación genera el mensaje de error C++/WinRT VSIX ya no proporciona compatibilidad con la compilación del proyecto. Agregue una referencia de proyecto al paquete NuGet Microsoft.Windows.CppWinRT. Instala el paquete NuGet Microsoft.Windows.CppWinRT en el proyecto. Para más información, consulta Versiones anteriores de la extensión VSIX.
El enlazador de C++ genera el error LNK2019: símbolo externo sin resolver, con una mención de winrt::impl::consume_Windows_Foundation_Collections_IVector. A partir de C++/WinRT 2.0, si usas for basado en intervalo en una colección de Windows Runtime, deberás aplicar ahora #include <winrt/Windows.Foundation.Collections.h>.
El compilador de C++ genera el error "error C4002: demasiados argumentos para la invocación de la macro como función GetCurrentTime". Consulta ¿Cómo se pueden resolver las ambigüedades con GetCurrentTime o TRY?
El compilador de C++ genera el error "error C2334: tokens inesperados antes de '{'; se omite el cuerpo de función aparente". Consulta ¿Cómo se pueden resolver las ambigüedades con GetCurrentTime o TRY?
El compilador de C++ genera el error "winrt::impl::produce<D,I> no se puede crear una instancia de la clase abstracta, porque falta GetBindingConnector". Tienes que #include <winrt/Windows.UI.Xaml.Markup.h>.
El compilador de C++ genera el error "error C2039: 'promise_type': no es un miembro de 'std::experimental::coroutine_traits<void>'". Tu corrutina debe devolver un objeto de operación asincrónica o winrt::fire_and_forget. Consulta Operaciones simultáneas y asincrónicas.
El proyecto genera "acceso ambiguo de 'PopulatePropertyInfoOverride'". Este error puede producirse cuando se declaran una clase base en el archivo IDL y una clase base diferente en el marcado XAML.
Cargar una solución de C++/WinRT por primera vez genera el error "Error de compilación en tiempo de diseño para la configuración del proyecto 'MyProject.vcxproj' 'Debug|x86'. Es posible que IntelliSense no esté disponible.". Después de compilar por primera vez, se resolverá este problema de IntelliSense.
Si intentas especificar winrt::auto_revoke al registrar un delegado, se genera una excepción winrt::hresult_no_interface. Consulta If your auto-revoke delegate fails to register (Si el delegado de revocación automática no se registra).
En una aplicación de C++ o WinRT, al consumir un componente de Windows Runtime para C# que usa XAML, el compilador genera un error con el formato "'MyNamespace_XamlTypeInfo': no es miembro de 'winrt::MyNamespace'" donde MyNamespace es el nombre del espacio de nombres del componente de Windows Runtime. En el archivo pch.h de la aplicación que consume C++ o WinRT, agregue #include <winrt/MyNamespace.MyNamespace_XamlTypeInfo.h> y reemplace MyNamespace según corresponda.
En un proyecto de C++/WinRT en Visual Studio, IntelliSense genera un error con el formato "error E1696: no se puede código abierto archivo". Compile el proyecto recién creado al menos una vez. A continuación, haga clic con el botón derecho en el editor de código fuente en >Volver a examinar>Volver a examinar archivo. Esto resolverá todos los errores de IntelliSense, incluido E1696.

Nota

Si en este tema no hemos respondido a tu pregunta, podrás encontrar ayuda en la comunidad de desarrolladores de C++ de Visual Studio o mediante la etiqueta c++-winrt en Stack Overflow.