Главная страница
    Top.Mail.Ru    Яндекс.Метрика
Форум: "Основная";
Текущий архив: 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.48 MB
Время: 0.008 c
2-1135065670
yk
2005-12-20 11:01
2006.01.08
Отправка почты из dll


2-1135035793
kizam
2005-12-20 02:43
2006.01.08
картинка на RichEdit-e


2-1135228511
RUBEY
2005-12-22 08:15
2006.01.08
Встроенные компоненты


14-1134635324
SPeller
2005-12-15 11:28
2006.01.08
А в чём смысл?


3-1131619501
Дмитрий_Б
2005-11-10 13:45
2006.01.08
MultiSelect в Гриде





Afrikaans Albanian Arabic Armenian Azerbaijani Basque Belarusian Bulgarian Catalan Chinese (Simplified) Chinese (Traditional) Croatian Czech Danish Dutch English Estonian Filipino Finnish French
Galician Georgian German Greek Haitian Creole Hebrew Hindi Hungarian Icelandic Indonesian Irish Italian Japanese Korean Latvian Lithuanian Macedonian Malay Maltese Norwegian
Persian Polish Portuguese Romanian Russian Serbian Slovak Slovenian Spanish Swahili Swedish Thai Turkish Ukrainian Urdu Vietnamese Welsh Yiddish Bengali Bosnian
Cebuano Esperanto Gujarati Hausa Hmong Igbo Javanese Kannada Khmer Lao Latin Maori Marathi Mongolian Nepali Punjabi Somali Tamil Telugu Yoruba
Zulu
Английский Французский Немецкий Итальянский Португальский Русский Испанский