Главная страница
    Top.Mail.Ru    Яндекс.Метрика
Форум: "Основная";
Текущий архив: 2004.03.09;
Скачать: [xml.tar.bz2];

Вниз

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;
Скачать: [xml.tar.bz2];

Наверх




Память: 0.53 MB
Время: 0.012 c
1-25763
Romstein
2004-02-26 16:13
2004.03.09
2D движок


14-25905
Думкин
2004-02-14 06:10
2004.03.09
С днем рождения! 14 февраля.


1-25758
Pahan_
2004-02-26 16:16
2004.03.09
Drag n Drop в наследнике от TTreeView


3-25681
sherminator
2004-02-11 13:17
2004.03.09
поиск в большой базе


3-25695
garry79
2004-02-07 12:18
2004.03.09
Как после вызова ХП обратиться к набору данных?





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
Английский Французский Немецкий Итальянский Португальский Русский Испанский