Форум: "Основная";
Текущий архив: 2006.01.08;
Скачать: [xml.tar.bz2];
ВнизEOleException и сообщение об исключительной ситуации Найти похожие ветки
← →
Rem © (2005-12-06 22:40) [0]Описание ситуации: В DLL реализован класс, реализующий некий интерфейс. В случае возникновения исключительной ситуации в методе, "наружу" показывается исключение EOleException с сообщением "Разрушительный сбой", а исходное сообщение об ошибке - теряется.
Пример:{ Код в DLL }
type
IMyInterface = interface
["{3AF43797-4A63-4E07-99C0-5016CDCFBD22}"]
procedure MyMethod; safecall;
end;
TMyClass = class(TObject, IMyInterface)
...
procedure MyMethod; safecall;
...
end;
procedure TMyClass.MyMethod;
begin
raise Exception.Create("Test");
end;
function CreateMy: IMyClass; {экспортируется}
begin
Result := TMyClass.Create;
end;
{ Вызывающий код }
var
My: IMyInterface;
...
{DLL загружена, получен адрес функции CreateMy}
...
MyObject := CreateMy;
MyObject.MyMethod; {тут, в принципе, генерируется сообщение с текстом "Test"}
В результате, появляется неинформативное сообщение об ошибке "Разрушительный сбой".
Вопрос: Как получить текст исходного сообщения об ошибке? (в примере - "Test").
← →
Lamer@fools.ua © (2005-12-07 00:21) [1]>>Rem © (06.12.05 22:40)
Попробуйте так:{ Код в DLL }
type
IMyInterface = interface
["{6CC061A9-2DDA-4E0F-B9E2-5377A5CD0AE9}"]
procedure MyMethod; safecall;
end;
TMyClass = class(TInterfacedObject, IMyInterface)
procedure MyMethod; safecall;
public
function SafeCallException(ExceptObject: TObject; ExceptAddr: Pointer): HRESULT; override;
end;
procedure TMyClass.MyMethod;
begin
raise Exception.Create("Test");
end;
function CreateMy: IMyInterface; {экспортируется}
begin
Result := TMyClass.Create;
end;
procedure TForm1.Button1Click(Sender: TObject);
var
My: IMyInterface;
begin
My := CreateMy;
try
My.MyMethod;
except
on E: Exception do
begin
MessageDlg(E.Message, mtError, [mbOK], 0);
end;
end;
end;
function TMyClass.SafeCallException(ExceptObject: TObject; ExceptAddr: Pointer): HRESULT;
begin
Result := HandleSafeCallException(ExceptObject, ExceptAddr, IMyInterface, "", "");
end;
← →
Rem © (2005-12-07 01:50) [2]Lamer@fools.ua © (07.12.05 00:21) [1]
Вещь! 8-)
Щиро дякую!
P.S. Полуночные размышления по поводу подобной ситуации в экспортируемых функциях и процедурах DLL не дают результата.{DLL}
procedure OnExport; safecall;
begin
raise Exception.Create("Test");
end;
exports
OnExport;
{Вызывающее приложение}
{Загружена DLL и получен адрес OnExport}
OnExport; {Тот же самый "Разрушительный сбой"}
← →
Lamer@fools.ua © (2005-12-07 08:28) [3]>>Rem © (07.12.05 01:50) [2]
>P.S. Полуночные размышления по поводу подобной ситуации в экспортируемых функциях и процедурах DLL не дают результата.
Дык эта... safecall не предназначен для простых функций, только для методов COM-интерфейсов. Для простых используйте обычный stdcall и всё тут.
Из Help"а:
The safecall convention must be used for declaring dual-interface methods.
← →
Набережных С. © (2005-12-07 08:40) [4]
> Rem © (07.12.05 01:50) [2]
> Полуночные размышления по поводу подобной ситуации в экспортируемых
> функциях и процедурах DLL не дают результата.
При работе с интерфейсами задействуются совсем другие механизмы. C простыми функциями можешь посмотреть здесь:
http://kladovka.net.ru/download.cgi?id=288
← →
Rem © (2005-12-07 11:33) [5]Lamer@fools.ua © (07.12.05 08:28) [3]
Да, разобрался. Спасибо. (Хотя, SafeCall - гораздо более "красивше" звучит :-)
Набережных С. © (07.12.05 08:40) [4]
Класс! :-) Спасибо. Хоть и приходится код в процедурах и функциях в try-except-end "заворачивать", но, все равно, удобный подход.
Я, было, ходил другим путем - создавал маппированный файл, в котором сохранял сообщение, а при последующей обработке исключительной ситуации - проверял на факт наличия данных в этом файле. "Почти" как в Вашем примере, но явно более криво. Спасибо еще раз.
← →
Набережных С. © (2005-12-07 17:18) [6]
> Rem © (07.12.05 11:33) [5]
> Я, было, ходил другим путем - создавал маппированный файл,
> в котором сохранял сообщение, а при последующей обработке
> исключительной ситуации - проверял на факт наличия данных
> в этом файле.
Ну почему же, не так уж и криво, по-моему.
> Хоть и приходится код в процедурах и функциях в try-except-
> end "заворачивать
Это тоже не обязательно. Я все никак не соберусь, но может тебя это заинтересует, так и со мной поделешься:) А лучше со всеми:))
В модуле System есть переменная по прозвищу RaiseExceptionProc, в которую при инициализации модуля записывается адрес системной функции RaiseException. Когда мы генерим исключение, то системный вызов идет как раз через эту переменную, а сам вызов производится в процедуре System._RaiseExcept. Таким образом, мы в ДЛЛ можем подставить в RaiseExceptionProc адрес собственной функции, извлечь из стека всю информацию, а потом уже вызвать системную RaiseException так, как нам надо. Такой механизм будет универсальным, код и для ехе, и для ДЛЛ нужно написать только раз.
Я сам собирался, но судя по тому, что это "собирание" длится уже года два, не соберусь никогда:(. Если интересно, попробуй, IMHO неплохой механизм получится.
← →
Rem © (2005-12-08 08:03) [7]Набережных С. © (07.12.05 17:18) [6]
Очень интересно.
Попробую обязательно.
После Нового Года.
Сейчас - более приземленные задачи...
P. S. Надеюсь, мое "после" не затянется на два года... :-)
Страницы: 1 вся ветка
Форум: "Основная";
Текущий архив: 2006.01.08;
Скачать: [xml.tar.bz2];
Память: 0.47 MB
Время: 0.007 c