Чтение родных данных / аргументов исключений win32 в .NET

Я пытаюсь получить данные об исключении, которое я выбрасываю в 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.

2

Решение

Исключения 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.

2

Другие решения


По вопросам рекламы [email protected]