Я пытаюсь получить данные об исключении, которое я выбрасываю в native (c ++ / win32) в блоке catch управляемого (.net / c #).
Например, в c ++ мы можем:
void MyFunc()
{
const char* data = "my exception info";
ULONG_PTR args[1] { data };
RaiseException(0,0,1,args);
}
Эта функция может быть вызвана через P / Invoke из c #:
[DLLImport("MyLib.dll")]
extern public static void MyFunc();
static void Main()
{
try { MyFunc(); }
catch(SEHException seh)
{
// Where is my exception info? :(
}
}
SEHException не содержит мою строку из импортированной функции DLL.
SEHException.ErrorCode всегда выглядит как E_FAIL, но я бы хотел распределить более богатые данные, чем int в любом случае.
Я что-то упустил или есть другой способ вернуть эти строковые данные через исключение?
Цель состоит в том, чтобы повторно вызвать собственные исключения с помощью собственной трассировки стека, установив собственные фильтры, например, с помощью SetUnhandledExceptionFilter, FYI.
Исключения SEH обычно не имеют аргументов и очень мало данных. На самом деле все, что вы можете получить, это числовой код исключения а также состояние процессора при возникновении исключения (включая указатель инструкций и указатель стека).
Обработка исключений C ++ использует исключение SEH, используемое для запуска обработчика, но объект исключения C ++ фактически хранится в другом месте (детали являются внутренними для компилятора и его библиотеки времени выполнения). Получить доступ к нему с другого языка практически невозможно; даже другие компиляторы C ++ имеют ужасное время. Все исключения C ++ имеют общий код исключения.
призвание RaiseException
вручную, как вы делаете, позволяет хранить параметры исключений так же, как исключения ОС EXCEPTION_ACCESS_VIOLATION
а также EXCEPTION_IN_PAGE_ERROR
, увидеть EXCEPTION_RECORD
на MSDN. С помощью компилятора Microsoft C ++ вы можете получить к ним доступ через GetExceptionInformation
, И вам, безусловно, не следует комбинировать объекты C ++, такие как std::string
с RaiseException
— вам не хватает дополнительного волшебства, которое добавляет компилятор C ++ для управления этими объектами на протяжении жизни. Передача строковых данных как const char*
к строковому литералу должно быть хорошо, хотя ..
Тогда вы столкнулись с проблемой получения этой информации в .NET. Даже эта ограниченная (код исключения, контекст и запись, без объектов C ++) информация, которая есть, я не думаю, что вы можете получить из .NET SEHException
объект. Причина, по которой вы видите E_FAIL
является результатом этой заметки в документации, а не кодом исключения.
Класс SEHException обрабатывает ошибки SEH, которые вызываются из неуправляемого кода, но которые не были сопоставлены с другим исключением .NET Framework. Класс SEHException также отвечает на HRESULT E_FAIL, который имеет значение 0x80004005.