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

Вниз

Exceptions. Можно ли получить полный контроль над ними?   Найти похожие ветки 

 
Германн ©   (2004-02-19 02:33) [0]

Поясню. Есть ли нормальный вариант получить полный контроль над всеми исключениями? Имея в виду, что блоки try except/finally рассыпаны по всей VCL, а также по, возможно, использующимися сторонними компонетами. Т.е. есть ли (и какая) возможность обработки исключения в Дельфи приложении до обработки их в компонентах и функциях VCL+сторонние компоненты*


 
TUser ©   (2004-02-19 10:15) [1]

А оно надо?


 
Тимохов ©   (2004-02-19 10:32) [2]


> Германн © (19.02.04 02:33)

Согласен с 1. Оно надо? По каким критериям ты будешь обрабатывать исключения в компоненте, который написал Вася Пупков? Позвонишь ему?
Может быть речь о другом - о логе исключений? Проясни ситуацию...


 
Nikolay M. ©   (2004-02-19 11:45) [3]

Возможно, Application.OnException имеется ввиду?

А вообще про исключения копай в MSDN про Structured Exception Handling.


 
y-soft ©   (2004-02-19 11:55) [4]

>Германн © (19.02.04 02:33)

А почему нет?
try..finally и try..except могут ведь быть и вложенными, вложенный обработчик в правильно написанном приложении не отменяет возникшего исключения. Если есть объект Application, то можно все перехватывать в Application.OnException, если нет - поместить в try..except весь код программы. Отдельные трудности - с перехватом возможных исключений в дополнительных потоках и секциях initialization...

Другое дело - как Вы воспользуетесь этим контролем...


 
Германн ©   (2004-02-19 13:55) [5]

2 y-soft © (19.02.04 11:55) [4]
Из хелпа:
Use OnException to change the default behavior that occurs when an exception is not handled by application code.

Речь действительно идет в частности и о логе. Именно туда предполагается записывать все сообщения об ошибках. Но главное все таки в другом - убрать возможность появления окошек с сообщениями об ошибках, поскольку нажимать на кнопку ОК некому.


 
Тимохов ©   (2004-02-19 14:05) [6]

Если сделаете обрабтку этого события и не будете в нем показывать окошко с кнопкой, которую некому нажимать, то само окошко не появится.


 
Плохиш   (2004-02-19 14:06) [7]

>Германн © (19.02.04 13:55) [5]

Тогда, действительно Application.OnException.


 
Германн ©   (2004-02-19 14:23) [8]

Увы Application.OnException ловит только "exception is not handled by application code."


 
Тимохов ©   (2004-02-19 14:39) [9]


> Германн © (19.02.04 14:23) [8]

Что значит "увы"?
Зачем Вам ловить исключения, которые обработаны? Тем более, если обработаны не в Вашем коде, а в стороннем компоненте.


 
Verg ©   (2004-02-19 14:39) [10]

Значит получается. что в твоем приложении там, где возникают исключения
навтыканы
try

...........
..........
except
On E : Exception Aplication.ShowException(E);
// Или еще какая-то обработка типа ShowMessage
end;

Али как?


> [5] Германн © (19.02.04 13:55)
> 2 y-soft © (19.02.04 11:55) [4]
> Из хелпа:
> Use OnException to change the default behavior that occurs
> when an exception is not handled by application code.
>
> Речь действительно идет в частности и о логе. Именно туда
> предполагается записывать все сообщения об ошибках. Но главное
> все таки в другом - убрать возможность появления окошек
> с сообщениями об ошибках
, поскольку нажимать на кнопку ОК
> некому.


 
y-soft ©   (2004-02-19 14:48) [11]

>Германн © (19.02.04 13:55) [5]

Что могу сказать? Не используйте сторонних компонентов, которые ведут себя недопустимым для Вашей задачи образом. Возможно, они действительно ведут себя так, как сказал Verg © (19.02.04 14:39) [10], тогда без правки их кода не обойтись

P.S. IMHO лучше вообще не использовать сторонние компоненты без исходного кода


 
Amoeba ©   (2004-02-19 16:26) [12]


> IMHO лучше вообще не использовать сторонние компоненты без
> исходного кода

Несколько спорное утверждение. Есть очень качественные профессионально сделанные, библиотеки идущие с исходным кодом за деньги и бесплатно без исходников, но обычно в урезанном виде. Все ли готовы и могут платить за исходники? И всегда ли эти расходы окупятся?


 
Digitman ©   (2004-02-19 16:35) [13]


> Германн © (19.02.04 02:33)


VCL не исключает создание и использование доп.код.потоков

для целей отслеживания необработанных исключений в доп.код.потоках вышеупомянутое App.OnException не годится - этот механизм работает только для осн.код.потока

более того - необработанное в поточной ф-ции исключение ведет к непредсказуемым послежствиям, вплоть до краха процесса


 
Плохиш   (2004-02-19 16:53) [14]

>Германн © (19.02.04 14:23) [8]

Если программа/компонент оказывают окошко с сообшением, то это нормальная обработка и то исключение, которое, возможно, этому предшествовало, уже обработано.


 
y-soft ©   (2004-02-19 17:18) [15]

>Amoeba © (19.02.04 16:26) [12]

Несколько спорное утверждение. Есть очень качественные профессионально сделанные, библиотеки идущие с исходным кодом за деньги и бесплатно без исходников, но обычно в урезанном виде. Все ли готовы и могут платить за исходники? И всегда ли эти расходы окупятся?


Основываюсь исключительно на личном горьком опыте - обидно натыкаться на чужие ошибки, так что тут надо выбирать - бесплатность vs надежность...

А библиотеки писать мы и сами могем :)


 
Германн ©   (2004-02-22 02:03) [16]

Во-первых, спасибо всем принявшим участие в данном обсуждении.
Во-вторых, высказался бы ранее, если бы был доступен delphimaster.
В-третьих, едучи на объект, после полудня 19.02.04 понял насколько я был глуп, точнее ничего не соображал, задавая этот вопрос.
То бишь я понял, что (кстати помятуя Verg © (19.02.04 14:39 [10])), у меня нет таких ситуаций. И все, что мне нужно - это обработать в OnException все необработанные ранее исключения, но с некоторой проверкой, как себя вести в зависимости от конкретной ситуации.
В-четвертых, отвечая на y-soft © (19.02.04 14:48) [11] - я никогда не использовал и не собираюсь использовать компоненты без исходников.

2 Digitman © (19.02.04 16:35) [13]
А вот это уже очень интересно. У меня пока только один поток, но для будущих целей - весьма! Спасибо. Сохраню данную страницу в свой архив.

Сие писал 21.02.04 в 02:27, но увы не смог отправить. То ли Delphimaster шалил, то ли мой провайдер.
Сейчас отправляю.

Но, учитывая возможность "многопоточности" дальнейшего развития приложения (см. Digitman © (19.02.04 16:35) [13]),
есть вопрос что и как следует сделать, чтобы обработать все исключения?


 
KSergey ©   (2004-02-22 10:17) [17]

> Германн © (22.02.04 02:03) [16]
> есть вопрос что и как следует сделать, чтобы обработать
> все исключения?

Обязательно заключить код метода Execute в try..except
И не выпусякать исключения наружу.


 
y-soft ©   (2004-02-22 15:38) [18]

Ну, все исключения в принципе перехватить нельзя, по крайней мере в программе на Delphi - например, не перехватываются исключения при инициализации RTL...


 
Германн ©   (2004-02-23 01:08) [19]

2 KSergey © (22.02.04 10:17) [17]
Спасибо. Учту как только так сразу и если многопоточность понадобится в данном случае.
А, кстати, термин выпусякать выглядит очень эстетно! :)

2 y-soft © (22.02.04 15:38) [18]
Это я примерно себе представлял, но имхо вероятность таких исключений либо 100% либо "мизер". Первый вариант легко находится, второй меня пока мало интересует. Заказчик понимает, что "раз в год и палка стреляет", и что программ, которые работают вечно (вместе с операционкой и самим компьютером) - не существует. Пока что минимальное время работы программы без сбоев, которое он хочет получить ~1.5 месяца.

Еще раз спасибо всем принявшим участие.


 
KSergey ©   (2004-02-23 09:20) [20]

> Германн © (23.02.04 01:08) [19]
> А, кстати, термин выпусякать выглядит очень эстетно! :)

Ачепятка...


 
Германн ©   (2004-02-25 01:48) [21]

А я и не сомневался, поэтому и поставил смайлик. :) Просто очень понравилось "звучаение" сей ачепятки. :)


 
Германн ©   (2004-02-25 03:19) [22]

Кстати "звучаение" - тоже очепятка. (первое "е" там явно лишнее). :)


 
}|{yk ©   (2004-02-25 11:02) [23]

Сейчас дорабатываю чей-то код (достался мне без опознавательных знаков) который делает именно то, о чем ты спрашиваешь.

unit ErrorCatcher;

interface

uses Classes, SysUtils, JPEG, LinarBitmap,PNGLoader;

type
TClassRef = class of TObject;
TImageFormat = (JPG, BMP, PNG);
type TImageQuality = 1..100;

type
TErrorCatcher = class(TComponent)
private
FEnabled: boolean;
FGenerateScreenshot: boolean;
FImageQuality: TImageQuality;
FCollectInfo: boolean;
Fn: TFilename;
FImageFileMask: string;
FSuffix: string;
ClassRef: TClassRef;
FErrorLogName: TFileName;
FFolderScreenShoots: string;
FImageFormat: TImageFormat;
procedure SetEnabled(const Value: boolean);
function CollectUserName: string;
function CollectComputerName: string;
{ Private declarations }
protected
{ Protected declarations }
procedure EnableCatcher;
procedure DisableCatcher;
public
{ Public declarations }
constructor Create(AOwner: TComponent); override;
destructor Destroy; override;
procedure Catcher(Sender: TObject; E: Exception);
procedure DoGenerateScreenshot;
procedure DoCollectInfo(E: Exception);
published
{ Published declarations }
property Enabled: boolean read FEnabled write SetEnabled default False;
property GenerateScreenshot: boolean read FGenerateScreenshot write FGenerateScreenshot default False;
property ImageQuality: TImageQuality read FImageQuality write FImageQuality default 100;
property CollectInfo: boolean read FCollectInfo write FCollectInfo default False;
property UserName: string read CollectUserName;
property ComputerName: string read CollectComputerName;
property ErrorLogName: TFileName read FErrorLogName write FErrorLogName;
property FolderScreenShoots: string read FFolderScreenShoots write FFolderScreenShoots;
property ImageFNameMask: string read FImageFileMask write FImageFileMask nodefault;
property ImageFormat: TImageFormat read FImageFormat write FImageFormat default PNG;
end;

procedure Register;

implementation

uses Windows, Forms, Dialogs, Graphics;

procedure Register;
begin
RegisterComponents("Additional", [TErrorCatcher]);
end;

{ TErrorCatcher }

constructor TErrorCatcher.Create(AOwner: TComponent);
begin
inherited;
ImageQuality := 100;
end;

destructor TErrorCatcher.Destroy;
begin
DisableCatcher;
inherited;
end;

procedure TErrorCatcher.SetEnabled(const Value: boolean);
begin
FEnabled := Value;
if Enabled then EnableCatcher else DisableCatcher;
end;

procedure TErrorCatcher.DisableCatcher;
begin
Application.OnException := nil;
end;

procedure TErrorCatcher.EnableCatcher;
begin
Application.OnException := Catcher;
end;

procedure TErrorCatcher.Catcher(Sender: TObject; E: Exception);
begin
if Screen.ActiveForm <> nil then
begin
FSuffix := "_" + Screen.ActiveForm.Name +
FormatDateTime("_ddmmyyyy_hhnnss", Now()) +
"_error";
if GenerateScreenshot then DoGenerateScreenshot;
end
else Exit;
if CollectInfo then DoCollectInfo(E);
end;

procedure TErrorCatcher.DoGenerateScreenshot;
var bitmap: TBitmap;
begin
if Screen.ActiveForm = nil then
Exit;
bitmap := Screen.ActiveForm.GetFormImage;
try
case FImageFormat of
BMP:
bitmap.SaveToFile(FFolderScreenShoots + FImageFileMask + FSuffix + ".bmp");
JPG:
begin
with TJPEGImage.Create do
begin
CompressionQuality := ImageQuality;
Assign(bitmap);
SaveToFile(FFolderScreenShoots +"\"+ FImageFileMask + FSuffix + ".jpg");
Free();
end;
end;
PNG:
begin
with TLinearBitmap.Create do
try
GetFromTBitmap(bitmap);
SaveToFile(FFolderScreenShoots + FImageFileMask + FSuffix + ".png");
finally
Free;
end;
end;
end;
finally
FreeAndNil(bitmap);
end;
end;

function TErrorCatcher.CollectUserName: string;
var
uname: pchar;
unsiz: cardinal;
begin
uname := StrAlloc(255);
unsiz := 254;
GetUserName(uname, unsiz);
if (unsiz > 0) then
Result := string(uname) else
Result := "n/a";
StrDispose(uname);
end;

function TErrorCatcher.CollectComputerName: string;
var
cname: pchar;
cnsiz: cardinal;
begin
cname := StrAlloc(MAX_COMPUTERNAME_LENGTH + 1);
cnsiz := MAX_COMPUTERNAME_LENGTH + 1;
GetComputerName(cname, cnsiz);
if (cnsiz > 0) then
Result := string(cname) else
Result := "n/a";
StrDispose(cname);
end;

procedure TErrorCatcher.DoCollectInfo(E: Exception);
var sl: TStringList;
ClassThree: string; {строка с деревом классов}
time: string;
begin
time := FormatDateTime("_dd.mm.yyyy_hh.nn.ss", now);
ClassThree := E.ClassName;
ClassRef := E.ClassType;
while ClassRef.ClassParent <> nil do
begin
ClassRef := ClassRef.ClassParent;
ClassThree := ClassRef.ClassName + " => " + ClassThree;
end;
sl := TStringList.Create;
if (FileExists(self.FErrorLogName)) then
sl.LoadFromFile(self.FErrorLogName);
sl.add("--- This report is created by automated reporting system at " + time);
sl.add("Computer name is: [" + ComputerName + "]");
sl.add("User name is : [" + UserName + "]");
sl.Add("ClassThree : [" + ClassThree + "]");
sl.Add("Message : [" + E.Message + "]");
sl.Add(time);
sl.add("--- End of report ---------------------------------------");
sl.SaveToFile(self.FErrorLogName);
end;

end.



Если здесь есть автор исходного кода, пусть отозвется


 
Германн ©   (2004-02-26 00:41) [24]

2 }|{yk © (25.02.04 11:02) [23]

Спасибо за дополнительную инфу. Днем почитаю ее внимательно. Может поможет не изобретать заново какие-то детали велосипеда.


 
Гаврила   (2004-02-26 00:49) [25]

Приведенный выше код - всего навсего обертка вокруг Application.OnException. На обработку не перехваченных блоком try-except ичключений он не повлияет, равно как и не повлияет на обработку исключений, возникших вне основного потока программы


 
KSergey ©   (2004-02-26 05:33) [26]

Если не ошибаюсь, в Jedi есть еще более навороченый перехватчик, который даже стек вызовов раскручивает... Там и код прилагается...



Страницы: 1 вся ветка

Текущий архив: 2004.03.09;
Скачать: CL | DM;

Наверх




Память: 0.55 MB
Время: 0.027 c
1-25754
Leech
2004-02-26 13:37
2004.03.09
OnMouseMove


8-25827
arcoant
2003-09-19 22:45
2004.03.09
OpenGL - Shadows


14-25900
Soft
2004-02-15 03:51
2004.03.09
Россия. Воры в Законе.


1-25731
Mihalich
2004-02-27 00:22
2004.03.09
Работа с файлом смешанного типа.


3-25706
User_OKA
2004-02-09 10:30
2004.03.09
FibDataSet