Rozwiązywanie problemów z językiem C++/WinRT

Note

Aby uzyskać informacje na temat instalowania i używania rozszerzenia Visual Studio (VSIX) dla C++/WinRT (które zapewnia obsługę szablonów projektów), zobacz Obsługa C++/WinRT w programie Visual Studio.

Ten temat przedstawiono na początku, aby od razu mieć jego świadomość, nawet jeśli jeszcze go nie potrzebujesz. Poniższa tabela rozwiązywania problemów z objawami i środkami zaradczymi może być przydatna niezależnie od tego, czy wycinasz nowy kod, czy przenosisz istniejącą aplikację. Jeśli przenosisz projekt i chcesz ruszyć naprzód, aby dojść do etapu, na którym projekt się kompiluje i uruchamia, możesz tymczasowo posunąć prace naprzód, komentując lub zastępując atrapami każdy nieistotny fragment kodu, który powoduje problemy, a następnie wracając później, by spłacić ten dług techniczny.

Aby uzyskać listę często zadawanych pytań, zobacz Często zadawane pytania.

Śledzenie problemów z XAML

Wyjątki analizowania składni XAML mogą być trudne do zdiagnozowania — szczególnie jeśli w treści wyjątku nie ma żadnych przydatnych komunikatów o błędach. Upewnij się, że debugger jest skonfigurowany do przechwytywania wyjątków typu first-chance (co pozwoli odpowiednio wcześnie przechwycić wyjątek parsowania). Możesz sprawdzić zmienną wyjątku w debugerze, aby określić, czy element HRESULT lub komunikat ma jakiekolwiek przydatne informacje. Sprawdź również okno danych wyjściowych Visual Studio pod kątem komunikatów o błędach wyjściowych przez analizator XAML.

Jeśli aplikacja zakończy działanie i wiesz, że podczas analizowania znaczników XAML został zgłoszony nieobsługiwany wyjątek, może to być wynikiem odwołania (według klucza) do brakującego zasobu. Albo może to być wyjątek wyrzucany w kontrolce UserControl, kontrolce niestandardowej lub niestandardowym panelu układu. Ostatecznym rozwiązaniem jest podział binarny. Usuń około połowę znaczników ze strony XAML i uruchom ponownie aplikację. Wtedy będziesz wiedzieć, czy błąd znajduje się gdzieś w tej połowie, którą usunąłeś (którą w każdym razie należy teraz przywrócić), czy w połowie, której nie usunąłeś. Powtórz ten proces, dzieląc na pół tę część, która zawiera błąd, i tak dalej, aż namierzysz źródło problemu.

Objawy i środki zaradcze

Objaw Rozwiązanie
Wyjątek jest zgłaszany w czasie wykonywania programu o wartości HRESULT REGDB_E_CLASSNOTREGISTERED. Zobacz Dlaczego otrzymuję wyjątek "Klasa niezarejestrowana"?
Kompilator języka C++ generuje błąd ""implements_type": nie jest elementem członkowskim żadnej bezpośredniej lub pośredniej klasy bazowej "<przewidywanego typu>". Może się tak zdarzyć, gdy wywołasz make, używając nazwy typu implementacji bez kwalifikacji przestrzenią nazw (na przykład MyRuntimeClass), a plik nagłówkowy tego typu nie został dołączony. Kompilator interpretuje klasę MyRuntimeClass jako typ przewidywany. Rozwiązaniem jest dołączenie nagłówka dla typu implementacji (MyRuntimeClass.hna przykład).
Kompilator języka C++ generuje błąd "próba odwołania się do usuniętej funkcji". Może się tak zdarzyć, gdy wywołasz make, a typ implementacji przekazany jako parametr szablonu ma = deletekonstruktor domyślny. Zmodyfikuj plik nagłówkowy typu implementacji i zmień wartość = delete na = default. Można również dodać konstruktor do IDL dla klasy środowiska uruchomieniowego.
Zaimplementowano interfejs INotifyPropertyChanged, ale powiązania XAML się nie aktualizują (a UI nie subskrybuje zdarzenia PropertyChanged). Pamiętaj, aby ustawić Mode=OneWay (lub TwoWay) w wyrażeniu wiązania w znacznikach XAML. Zobacz kontrolki XAML; wiązanie z właściwością C++/WinRT.
Wiążesz kontrolkę elementów XAML z kolekcją obserwowalną, a w czasie wykonywania zgłaszany jest wyjątek z komunikatem „Parametr jest niepoprawny”. W pliku IDL i swojej implementacji zadeklaruj dowolną kolekcję obserwowalną jako typ Windows.Foundation.Collections.IVector<IInspectable>. Ale zwróć obiekt implementujący Windows.Foundation.Collections.IObservableVector<T>, gdzie T to typ elementu. Zobacz kontrolki elementów XAML; powiązanie z kolekcją C++/WinRT.
Kompilator języka C++ generuje błąd formularza "'MyImplementationType_base<MyImplementationType>': brak odpowiedniego konstruktora domyślnego". Może się tak zdarzyć, gdy pochodzisz z typu, który ma nietrywialny konstruktor. Konstruktor typu pochodnego musi przekazać parametry, których potrzebuje konstruktor typu podstawowego. Aby zapoznać się z przykładowym przykładem, zobacz Wyprowadzanie z typu, który ma konstruktor nietrygalny.
Kompilator języka C++ generuje błąd „nie można dokonać konwersji z 'const std::vector<std::wstring,std::allocator<_Ty>>' na 'const winrt::param::async_iterable<winrt::hstring> &'”. Może się to zdarzyć, gdy przekazujesz std::vector typu std::wstring do interfejsu API środowiska środowisko wykonawcze systemu Windows, który oczekuje kolekcji. Aby uzyskać więcej informacji, zobacz Standardowe typy danych C++ i C++/WinRT.
Kompilator języka C++ generuje błąd "nie można dokonać konwersji z 'const std::vector<winrt::hstring,std::allocator<_Ty>>' na 'const winrt::param::async_iterable<winrt::hstring> &'". Może się tak zdarzyć, gdy przekazujesz obiekt std::vector do asynchronicznego interfejsu API środowiska środowisko wykonawcze systemu Windows, który oczekuje kolekcji, a wektor nie został ani skopiowany, ani przeniesiony do asynchronicznie wywoływanej funkcji. Aby uzyskać więcej informacji, zobacz Standardowe typy danych C++ i C++/WinRT.
Podczas otwierania projektu Visual Studio generuje błąd "Aplikacja dla projektu nie jest zainstalowana". Jeśli jeszcze tego nie zrobiono, musisz zainstalować szablony języka C++ Zestaw SDK do aplikacji systemu Windows oraz rozszerzenie C++/WinRT Visual Studio (VSIX) (zobacz Visual Studio obsługę języka C++/WinRT).
Testy zestawu certyfikacji aplikacja dla systemu Windows generują błąd, że jedna z klas środowiska uruchomieniowego "nie pochodzi z klasy bazowej Windows. Wszystkie klasy komponowalne muszą ostatecznie pochodzić z typu w przestrzeni nazw Windows". Każda klasa środowiska uruchomieniowego (zadeklarowana w aplikacji) pochodząca z klasy bazowej jest znana jako klasa komponowalna . Ostateczna klasa bazowa klasy komponowalnej musi być typem pochodzącym z Windows.* lub Microsoft.* przestrzeni nazw, na przykład Microsoft. Interfejs użytkownika. Xaml.DependencyObject. Aby uzyskać więcej informacji, zobacz Kontrolki XAML; powiązanie z właściwością C++/WinRT.
Kompilator języka C++ generuje błąd „T musi być typem WinRT” dla specjalizacji delegata EventHandler lub TypedEventHandler. Rozważ użycie winrt::delegate<...T> zamiast tego. Zobacz Tworzenie zdarzeń w języku C++/WinRT.
Kompilator języka C++ generuje błąd „T musi być typem WinRT” dla specjalizacji asynchronicznej operacji środowiska uruchomieniowego Windows. Rozważ zamiast tego zwrócenie obiektu task biblioteki Parallel Patterns Library (PPL). Zobacz Współbieżność i operacje asynchroniczne.
Kompilator języka C++ generuje błąd "T musi być typem WinRT" podczas wywoływania winrt::xaml_typename. Użyj typu projekcji z winrt::xaml_typename (na przykład użyj BgLabelControlApp::BgLabelControl) zamiast typu implementacji (na przykład nie używaj BgLabelControlApp::implementation::BgLabelControl). Zobacz Kontrolki niestandardowe (szablony) języka XAML.
Kompilator języka C++ generuje "błąd C2220: ostrzeżenie traktowane jako błąd — nie wygenerowano pliku "object". Popraw ostrzeżenie lub ustaw opcję C/C++>General>Traktuj ostrzeżenia jako błędy na wartość Nie (/WX-).
Aplikacja ulega awarii, ponieważ program obsługi zdarzeń w obiekcie C++/WinRT jest wywoływany po zniszczeniu obiektu. Zobacz Bezpieczne uzyskiwanie dostępu do tego wskaźnika za pomocą delegata obsługi zdarzeń.
Kompilator języka C++ generuje "błąd C2338: dotyczy to tylko słabej obsługi ref". Żądasz słabej referencji dla typu, który przekazał strukturę znacznika winrt::no_weak_ref jako argument szablonu do swojej klasy bazowej. Zobacz Rezygnacja z obsługi słabych odwołań.
Kompilator języka C++ tworzy "consume_Something: funkcja zwracająca wartość "auto" nie może być używana przed zdefiniowaną funkcją" Zobacz C3779: Dlaczego kompilator zgłasza błąd „consume_Something: funkcja zwracająca „auto” nie może być używana, zanim zostanie zdefiniowana”?
Linker języka C++ generuje "błąd LNK2019: niezdefiniowany symbol zewnętrzny" Zobacz Dlaczego linker zgłasza błąd „LNK2019: Unresolved external symbol”?
Łańcuch narzędzi LLVM i Clang generuje błędy w przypadku użycia z językiem C++/WinRT. Nie obsługujemy łańcucha narzędzi LLVM i Clang dla języka C++/WinRT, ale jeśli chcesz emulować sposób używania go wewnętrznie, możesz wypróbować eksperyment, taki jak opisany w temacie Czy mogę użyć języka LLVM/Clang do skompilowania za pomocą języka C++/WinRT?.
Kompilator języka C++ tworzy "nie ma odpowiedniego domyślnego konstruktora dostępnego" dla przewidywanego typu. Jeśli próbujesz opóźnić inicjowanie obiektu klasy środowiska uruchomieniowego lub użyć i zaimplementować klasę środowiska uruchomieniowego w tym samym projekcie, należy wywołać konstruktor std::nullptr_t . Aby uzyskać więcej informacji, zobacz Korzystanie z interfejsów API za pomocą języka C++/WinRT.
Kompilator języka C++ generuje błąd C3861: "from_abi": nie znaleziono identyfikatora" i inne błędy pochodzące z pliku base.h. Ten błąd może wystąpić, jeśli używasz programu Visual Studio 2017 (wersja 15.8.0 lub nowsza) i jako docelową ustawiono wersję 10.0.17134.0 pakietu Windows SDK (Windows 10, wersja 1803). Wybierz jako docelową nowszą (bardziej zgodną) wersję pakietu Windows SDK albo ustaw właściwość projektu C/C++>Language>Conformance mode: No (jeśli /permissive- pojawia się we właściwości projektu C/C++>Language>Command Line w sekcji Additional Options, usuń ją).
Kompilator języka C++ generuje "błąd C2039: "IUnknown": nie jest członkiem "globalnej przestrzeni nazw". Zobacz Jak przekierować projekt C++/WinRT na nowszą wersję zestawu SDK systemu Windows.
Konsolidator C++ generuje komunikat „błąd LNK2019: nierozpoznany symbol zewnętrzny _WINRT_CanUnloadNow@0, do którego odwołanie znajduje się w funkcji _VSDesignerCanUnloadNow@0 Zobacz Jak przekierować projekt C++/WinRT na nowszą wersję zestawu SDK systemu Windows.
Proces kompilacji generuje komunikat o błędzie VSIX C++/WinRT nie zapewnia już obsługi kompilacji projektu. Dodaj odwołanie do pakietu NuGet Microsoft.Windows.CppWinRT. Zainstaluj pakiet NuGet Microsoft.Windows.CppWinRT w projekcie. Aby uzyskać szczegółowe informacje, zobacz Wcześniejsze wersje rozszerzenia VSIX.
Linker języka C++ generuje błąd LNK2019: nierozwiązany symbol zewnętrzny, ze wzmianką o winrt::impl::consume_Windows_Foundation_Collections_IVector. Począwszy od C++/WinRT 2.0, jeśli używasz instrukcji for opartej na zakresie dla kolekcji środowiska środowisko wykonawcze systemu Windows, musisz teraz użyć #include <winrt/Windows.Foundation.Collections.h>.
Kompilator języka C++ generuje "błąd C4002: Zbyt wiele argumentów wywołania makra przypominającego funkcję GetCurrentTime". Zobacz Jak rozwiązać niejednoznaczności za pomocą polecenia GetCurrentTime i/lub TRY?.
Kompilator języka C++ generuje "błąd C2334: nieoczekiwane tokeny poprzedzające "{"; pomijanie widocznej treści funkcji". Zobacz Jak rozwiązać niejednoznaczności za pomocą polecenia GetCurrentTime i/lub TRY?.
Kompilator języka C++ zgłasza komunikat „winrt::impl::produce<D,I> nie można utworzyć instancji klasy abstrakcyjnej z powodu braku GetBindingConnector”. Musisz wykonać następujące kroki: #include <winrt/Microsoft.UI.Xaml.Markup.h>.
Kompilator języka C++ generuje błąd „error C2039: 'promise_type': nie jest składową elementu 'std::experimental::coroutine_traits<void>'”. Coroutine musi zwrócić obiekt operacji asynchronicznej lub winrt::fire_and_forget. Zobacz Współbieżność i operacje asynchroniczne.
Projekt generuje "niejednoznaczny dostęp do „PopulatePropertyInfoOverride”". Ten błąd może wystąpić, gdy zadeklarujesz jedną klasę bazową w pliku IDL, a inną klasę bazową w znacznikach XAML.
Przy pierwszym ładowaniu rozwiązania C++/WinRT pojawia się komunikat: „Kompilacja w czasie projektowania nie powiodła się dla projektu „MyProject.vcxproj” w konfiguracji „Debug|x86”. IntelliSense może być niedostępny.” Ten problem z funkcją IntelliSense zostanie rozwiązany po pierwszym skompilowaniu projektu.
Próba określenia winrt::auto_revoke podczas rejestrowania delegata generuje wyjątek winrt::hresult_no_interface . Zobacz Jeśli delegat automatycznego odwoływania nie rejestruje się.
W aplikacji C++/WinRT podczas korzystania ze składnika środowisko wykonawcze systemu Windows języka C# używającego języka XAML kompilator generuje błąd formularza "'MyNamespace_XamlTypeInfo': nie jest członkiem "winrt::MyNamespace", gdzie MyNamespace jest nazwą przestrzeni nazw składnika środowisko wykonawcze systemu Windows. W pch.h w używającej C++/WinRT aplikacji klienckiej dodaj #include <winrt/MyNamespace.MyNamespace_XamlTypeInfo.h> — zastępując odpowiednio MyNamespace.
W projekcie C++/WinRT w programie Visual Studio funkcja IntelliSense generuje błąd w postaci „błąd E1696: nie można otworzyć pliku źródłowego”. Skompiluj nowo utworzony projekt co najmniej raz. Następnie kliknij prawym przyciskiem myszy w edytorze kodu źródłowego >Ponownie przeskanuj>Ponownie przeskanuj plik. Spowoduje to rozwiązanie wszystkich błędów funkcji IntelliSense, w tym E1696.

Note

Jeśli ten temat nie odpowiedział na twoje pytanie, możesz znaleźć pomoc, odwiedzając społeczność deweloperów języka C++ Visual Studio lub używając taguc++-winrt w witrynie Stack Overflow.

Note

Wiele tematów języka C++/WinRT jest w trakcie migracji z dokumentacji platformy UWP do tej sekcji. Dopóki migracja nie zostanie ukończona, linki na poniższej liście mogą prowadzić do sekcji dokumentacji platformy UWP. Projekcja języka C++/WinRT jest taka sama zarówno dla aplikacji platformy UWP, jak i WinUI 3, dzięki czemu zawartość ma zastosowanie w obu kontekstach. Wszelkie wzorce specyficzne dla UWP (takie jak cykl życia aplikacji lub interfejsy API przestrzeni nazw Windows.UI) zostały wyraźnie wskazane w tych artykułach.