Главная страница
Top.Mail.Ru    Яндекс.Метрика
Текущий архив: 2006.01.08;
Скачать: CL | DM;

Вниз

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;
Скачать: CL | DM;

Наверх




Память: 0.49 MB
Время: 0.016 c
2-1134912561
Мадик777
2005-12-18 16:29
2006.01.08
Опять SQL


11-1116454469
Vans
2005-05-19 02:14
2006.01.08
Дада про taskbar


2-1134849990
newhite
2005-12-17 23:06
2006.01.08
Авторизация! Вход в систему.


2-1134580039
гость2
2005-12-14 20:07
2006.01.08
Определить открыто ли popup меню


1-1133898010
Rem
2005-12-06 22:40
2006.01.08
EOleException и сообщение об исключительной ситуации