Wyjątki (C++/CX)
Obsługa błędów w języku C++/CX jest oparta na wyjątkach. Na najbardziej podstawowym poziomie składniki środowisko wykonawcze systemu Windows zgłaszają błędy jako wartości HRESULT. W języku C++/CX te wartości są konwertowane na silnie typizowane wyjątki zawierające wartość HRESULT i opis ciągu, do którego można uzyskać dostęp programowo. Wyjątki są implementowane jako element ref class
pochodzący z klasy Platform::Exception
. Platform
Przestrzeń nazw definiuje odrębne klasy wyjątków dla najbardziej typowych wartości HRESULT; wszystkie inne wartości są zgłaszane za pośrednictwem Platform::COMException
klasy. Wszystkie klasy wyjątków mają pole Exception::HResult , którego można użyć do pobrania oryginalnego HRESULT. Możesz również sprawdzić informacje o stosie wywołań dla kodu użytkownika w debugerze, który może pomóc w określeniu oryginalnego źródła wyjątku, nawet jeśli pochodzi on z kodu napisanego w języku innym niż C++.
Wyjątki
W programie języka C++ można zgłosić i przechwycić wyjątek pochodzący z operacji środowisko wykonawcze systemu Windows, wyjątek pochodzący z std::exception
klasy lub typu zdefiniowanego przez użytkownika. Należy zgłosić wyjątek środowisko wykonawcze systemu Windows tylko wtedy, gdy przekroczy granicę interfejsu binarnego aplikacji (ABI), na przykład gdy kod, który przechwytuje wyjątek, jest zapisywany w języku JavaScript. Gdy wyjątek inny niż środowisko wykonawcze systemu Windows C++ osiągnie granicę ABI, wyjątek jest tłumaczony na Platform::FailureException
wyjątek, który reprezentuje E_FAIL HRESULT. Aby uzyskać więcej informacji na temat usługi ABI, zobacz Tworzenie składników środowisko wykonawcze systemu Windows w języku C++.
Można zadeklarować parametr Platform::Exception przy użyciu jednego z dwóch konstruktorów, które przyjmują parametr HRESULT lub HRESULT parametru i parametru Platform::String^, który można przekazać w usłudze ABI do dowolnej aplikacji środowisko wykonawcze systemu Windows, która go obsługuje. Możesz też zadeklarować wyjątek przy użyciu jednego z dwóch przeciążeń metody Exception::CreateException, które przyjmują parametr HRESULT lub parametr HRESULT i Platform::String^
parametr.
Wyjątki standardowe
Język C++/CX obsługuje zestaw standardowych wyjątków reprezentujących typowe błędy HRESULT. Każdy wyjątek standardowy pochodzi z klasy Platform::COMException, który z kolei pochodzi z klasy Platform::Exception
. W przypadku zgłaszania wyjątku w granicach usługi ABI należy zgłosić jeden ze standardowych wyjątków.
Nie można utworzyć własnego typu wyjątku z klasy Platform::Exception
. Aby zgłosić wyjątek niestandardowy, użyj zdefiniowanego przez użytkownika hrESULT do konstruowania COMException
obiektu.
W poniższej tabeli wymieniono standardowe wyjątki.
Nazwisko | Podstawowy hrESULT | opis |
---|---|---|
ComException | hresult zdefiniowany przez użytkownika | Zgłaszany, gdy nierozpoznany HRESULT jest zwracany z wywołania metody COM. |
AccessDeniedException | E_ACCESSDENIED | Zgłaszany, gdy odmowa dostępu do zasobu lub funkcji. |
ChangedStateException | E_CHANGED_STATE | Zgłaszany, gdy metody iteratora kolekcji lub widoku kolekcji są wywoływane po zmianie kolekcji nadrzędnej, co spowoduje unieważnienie wyników metody. |
ClassNotRegisteredException | REGDB_E_CLASSNOTREG | Zgłaszany, gdy klasa COM nie została zarejestrowana. |
DisconnectedException | RPC_E_DISCONNECTED | Zgłaszany, gdy obiekt jest odłączony od swoich klientów. |
BłądException | E_FAIL | Zgłaszany, gdy operacja kończy się niepowodzeniem. |
InvalidArgumentException | E_INVALIDARG | Zgłaszany, gdy jeden z argumentów podanych w metodzie jest nieprawidłowy. |
InvalidCastException | E_NOINTERFACE | Zgłaszany, gdy nie można rzutować typu na inny typ. |
NotImplementedException | E_NOTIMPL | Zgłaszany, jeśli metoda interfejsu nie została zaimplementowana w klasie. |
NullReferenceException | E_POINTER | Zgłaszany podczas próby odwołania do odwołania do obiektu o wartości null. |
ObjectDisposedException | RO_E_CLOSED | Zgłaszany, gdy operacja jest wykonywana na usuniętym obiekcie. |
OperationCanceledException | E_ABORT | Zgłaszany po przerwaniu operacji. |
OutOfBoundsException | E_BOUNDS | Zgłaszany, gdy operacja próbuje uzyskać dostęp do danych poza prawidłowym zakresem. |
OutOfMemoryException | E_OUTOFMEMORY | Zgłaszany, gdy nie ma wystarczającej ilości pamięci do ukończenia operacji. |
WrongThreadException | RPC_E_WRONG_THREAD | Zgłaszany, gdy wątek wywołuje się za pośrednictwem wskaźnika interfejsu, który jest przeznaczony dla obiektu proxy, który nie należy do mieszkania wątku. |
Właściwości HResult i Message
Wszystkie wyjątki mają właściwość HResult i właściwość Message . Właściwość Exception::HResult pobiera podstawową wartość HRESULT wyjątku. Właściwość Exception::Message pobiera ciąg dostarczony przez system, który opisuje wyjątek. W systemie Windows 8 komunikat jest dostępny tylko w debugerze i jest tylko do odczytu. Oznacza to, że nie można go zmienić podczas ponownego wywróć wyjątku. W systemie Windows 8.1 można uzyskać dostęp do ciągu komunikatu programowo i podać nowy komunikat, jeśli ponownie wrócą wyjątek. Lepsze informacje o stosie wywołań są również dostępne w debugerze, w tym stosy wywołań metody asynchronicznej.
Przykłady
W tym przykładzie pokazano, jak zgłosić wyjątek środowisko wykonawcze systemu Windows dla operacji synchronicznych:
String^ Class1::MyMethod(String^ argument)
{
if (argument->Length() == 0)
{
auto e = ref new Exception(-1, "I'm Zork bringing you this message from across the ABI.");
//throw ref new InvalidArgumentException();
throw e;
}
return MyMethodInternal(argument);
}
W następnym przykładzie pokazano, jak przechwycić wyjątek.
void Class2::ProcessString(String^ input)
{
String^ result = nullptr;
auto obj = ref new Class1();
try
{
result = obj->MyMethod(input);
}
catch (/*InvalidArgument*/Exception^ e)
{
// Handle the exception in a way that's appropriate
// for your particular scenario. Assume
// here that this string enables graceful
// recover-and-continue. Why not?
result = ref new String(L"forty two");
// You can use Exception data for logging purposes.
Windows::Globalization::Calendar calendar;
LogMyErrors(calendar.GetDateTime(), e->HResult, e->Message);
}
// Execution continues here in both cases.
//#include <string>
std::wstring ws(result->Data());
//...
}
Aby przechwycić wyjątki zgłaszane podczas operacji asynchronicznej, użyj klasy zadań i dodaj kontynuację obsługi błędów. Wyjątki kontynuacji obsługiwane przez obsługę błędów, które są zgłaszane w innych wątkach z powrotem do wątku wywołującego, dzięki czemu można obsłużyć wszystkie potencjalne wyjątki tylko w jednym punkcie kodu. Aby uzyskać więcej informacji, zobacz Asynchroniczne programowanie w języku C++.
Nieobsługiwane zdarzenieErrorDetected
W systemie Windows 8.1 można subskrybować zdarzenie statyczne Windows::ApplicationModel::Core::CoreApplication::UnhandledErrorDetected , które zapewnia dostęp do nieobsługiwane błędy, które mają spowodować wyłączenie procesu. Niezależnie od tego, skąd pochodzi błąd, program obsługi jest osiągany jako obiekt Windows::ApplicationModel::Core::UnhandledError przekazany za pomocą args zdarzenia. Wywołanie Propagate
obiektu powoduje utworzenie obiektu i zgłoszenie Platform::*Exception
typu odpowiadającego kodowi błędu. W blokach catch można zapisać stan użytkownika w razie potrzeby, a następnie zezwolić na zakończenie procesu przez wywołanie throw
metody lub zrobić coś, aby program wrócił do znanego stanu. W poniższym przykładzie przedstawiono podstawowy wzorzec:
W pliku app.xaml.h:
void OnUnhandledException(Platform::Object^ sender, Windows::ApplicationModel::Core::UnhandledErrorDetectedEventArgs^ e);
W app.xaml.cpp:
// Subscribe to the event, for example in the app class constructor:
Windows::ApplicationModel::Core::CoreApplication::UnhandledErrorDetected += ref new EventHandler<UnhandledErrorDetectedEventArgs^>(this, &App::OnUnhandledException);
// Event handler implementation:
void App::OnUnhandledException(Platform::Object^ sender, Windows::ApplicationModel::Core::UnhandledErrorDetectedEventArgs^ e)
{
auto err = e->UnhandledError;
if (!err->Handled) //Propagate has not been called on it yet.
{
try
{
err->Propagate();
}
// Catch any specific exception types if you know how to handle them
catch (AccessDeniedException^ ex)
{
// TODO: Log error and either take action to recover
// or else re-throw exception to continue fail-fast
}
}
Uwagi
Język C++/CX nie używa klauzuli finally
.