Log de Erro - Capturar nome do Formulário.

Delphi

25/10/2005

[b:4ac1a04776]Descrição do Problema:[/b:4ac1a04776]

Estou utilizando uma função para criar um arquivo texto sempre que ocorrer um erro(exceção) na aplicação.

Neste arquivo texto gravo o erro, a data e hora do erro, contudo não sei como capturar e escrever no arquivo texto [u:4ac1a04776]em qual formulário o erro aconteceu[/u:4ac1a04776] o que é de extrema importância na hora de realizar o ´reparo´ na aplicação.


Desde já agradeço a Atenção de Todos


Lnunes

Lnunes

Curtidas 0

Respostas

Facc

Facc

25/10/2005

vc tentou com Nome_Formulário.Caption?


GOSTEI 0
Lnunes

Lnunes

25/10/2005

Facc agradeço primeiramente a sua atenção mas o problema é que esta função fica em um evento do componente application event no formulário principal destinado a capturar qualquer execeção que ocorra no sistema sendo assim se eu utiliza-se o Nome_Formulário.Caption iria sempre capturar o nome do formulário principal e não do formulário onde realmente o erro aconteceu.


GOSTEI 0
Facc

Facc

25/10/2005

esse código que vc criou, ´varre´ o código de todos os formulários? Se sim, não seria o caso de vc criar uma váriavel que receba o nome do formulário?


GOSTEI 0
Martins

Martins

25/10/2005

Facc agradeço primeiramente a sua atenção mas o problema é que esta função fica em um evento do componente application event no formulário principal destinado a capturar qualquer execeção que ocorra no sistema sendo assim se eu utiliza-se o Nome_Formulário.Caption iria sempre capturar o nome do formulário principal e não do formulário onde realmente o erro aconteceu.


Desculpe lhe perguntar isso mas, como essa rotina tá pegando esses exceptions, e vc não poderia capturar o nome do objeto (Form)?

Nunca fiz nada igual, apenas uma idéia!!

Boa Sorte


GOSTEI 0
Lnunes

Lnunes

25/10/2005

A ideia é justamente esta criar uma variável string e carrega-la com o nome do formulário que apresentou o erro mas eu não tenho ideia de como carrega-la.


GOSTEI 0
Facc

Facc

25/10/2005

A ideia é justamente esta criar uma variável string e carrega-la com o nome do formulário que apresentou o erro mas eu não tenho ideia de como carrega-la.


tente criar ela no Form Principal na parte de Public, daí nos demais Forms vc colocaria (veja o local mais apropriado) pra receber o nome do form
FPrincipal.VForm := NomeFormulario.Caption


e na rotina onde grava os erros, vc passaria a variável

nunca fiz isso, é uma idéia


GOSTEI 0
Lnunes

Lnunes

25/10/2005

Facc obrigado pela a dica vou tentar agora e mais tarde posto uma resposta informado se o código funcionou ou não.

Desde já agradeço a atenção de todos.


GOSTEI 0
Lnunes

Lnunes

25/10/2005

A utilização da variável neste caso funciona mas acaba dando muito trabalho.

descobrir que a solução mas adequada é utilizar o getactivewindow(não sei se escrevi corretamente) para capturar o nome do formulário.


Obrigado a todos pela ajuda.


GOSTEI 0
Facc

Facc

25/10/2005

A utilização da variável neste caso funciona mas acaba dando muito trabalho. descobrir que a solução mas adequada é utilizar o getactivewindow(não sei se escrevi corretamente) para capturar o nome do formulário. Obrigado a todos pela ajuda.


e aí cara... funcionou desse jeito que vc falou? com o comando GetActiveWindow? Pois se traduzindo ao pé da letra, o comando pega o nome da tela ativa... e pelo que eu entendi, vc quer que retorne o possível erro no exato momento que vc chama o Form Principal, seria isso?


GOSTEI 0
Braytiner Heggendorn

Braytiner Heggendorn

25/10/2005

Tente usar o objeto Screen do Delphi para obter o nome do controle e do formulário atual


GOSTEI 0
Thomaz_prg

Thomaz_prg

25/10/2005

tenta aí fazer um for usando o objeto screen (como dito pelo colega).

For i:= 0 to Screen.Forms.Count -1 do

Para pegar o nome dos forms
Screen.Forms[i].Name


GOSTEI 0
Marco Salles

Marco Salles

25/10/2005

e aí cara... funcionou desse jeito que vc falou? com o comando GetActiveWindow? Pois se traduzindo ao pé da letra, o comando pega o nome da tela ativa...


Olhe LNunes , tb estou curioso para saber se funcionou ...

A Idéia simples porem um pouquinho cansativa (eu digo so um pouquinho) , porque e so copiar e colar nos eventos onShow de cada formulário aberto , como foi colocado pelo amido Facc

tente criar ela no Form Principal na parte de Public, daí nos demais Forms vc colocaria (veja o local mais apropriado) pra receber o nome do form Código:
FPrincipal.VForm := NomeFormulario.Caption 
[b:4ec5514397]e na rotina onde grava os erros, vc passaria a variável [/b:4ec5514397]


Ate o momento acho a idéia mais plausivel

[b:4ec5514397]Na secção Public do Form Principal[/b:4ec5514397]

var
 NomeFormularioErro:Strings;


procedure TFormPrincipal.ApplicationEvents1Exception(Sender: TObject;
  E: Exception);
var
  Filename: string;
  LogFile: TextFile;
begin
  // prepares log file
  FileName:=´C:\NomeDaPasta.txt´;
  AssignFile (LogFile, Filename);
  if FileExists (FileName) then
    Append (LogFile) // open existing file
  else
    Rewrite (LogFile); // create a new one

  // write to the file and show error
  Writeln (LogFile, DateTimeToStr (Now) + ´-> Ocorreu um Erro No Formulário :´+ NomeFormularioErro);
  Writeln (LogFile,´ O Tipo de erro apresentado foi :´ + E.Message);
  // close the file
  CloseFile (LogFile);
end;



GOSTEI 0
Thomaz_prg

Thomaz_prg

25/10/2005

Amigo, uso da forma com a qual eu disse, e funciona legal... se você quer pegar o nome do form com erro, é só pegar o último formulário instanciado no Objeto Screen ( Screen.Forms[ Screen.Forms.Count-1 ]).


GOSTEI 0
Marco Salles

Marco Salles

25/10/2005

Amigo, uso da forma com a qual eu disse, e funciona legal... se você quer pegar o nome do form com erro, é só pegar o último formulário instanciado no Objeto Screen ( Screen.Forms[ Screen.Forms.Count-1 ]).


Eu entendi e confesso que ate tinha me esquecido do objeto global Screen
..

Mas o problema é que quando ocorre um erro em algum formulario , para que o nome dele seje passado para o manipulador de evento Application , voce deve saber o indice do formulario que esta ativo..
Na minha opinião não basta escrever
Screen.Forms[ Screen.Forms.Count-1 ].Name porque nen sempre sera o formulário onde foi gerado a exceção
Mas de modo geral a idéia de usar o Screen é válida eu particularmente vou tentar dar uma investida nela amanhã


GOSTEI 0
Lnunes

Lnunes

25/10/2005

Agradeço a atenção de todos mas até o momento não encontrei a solução para este problemas , contudo com as novas idéias postadas pelo Marco Salles ,thomaz_prg e braytiner acredito que a solução esteja mais próxima,
principalmente a idéia de realizar um for usando o objeto screen.

Vou tentar e caso tenha êxito vou disponibilizar o código para todos, pois acho que a captura de erros sendo feita desta forma vai ajudar a todos.


GOSTEI 0
Marco Salles

Marco Salles

25/10/2005

[b:87be56a274]LNunes Citou:[/b:87be56a274]
Agradeço a atenção de todos mas até o momento não encontrei a solução para este problemas...


[b:87be56a274]Marco Salles citou:[/b:87be56a274]
Mas de modo geral a idéia de usar o Screen é válida eu particularmente vou tentar dar uma investida nela amanhã


Não posso garantir porque cada caso é um caso , mas fiz uns testes aqui e nas primeiras simulaçoes , a resposta foi satisfatória.. Utilizei o Objeto Global Screen como foi lembrado pelos amigos. Mas usei a propriedade [b:87be56a274]Screen.activeForm.Caption[/b:87be56a274] , que fornece o nome do formulário que esta ativo..

procedure TFormPrincipal.ApplicationEvents1Exception(Sender: TObject; 
  E: Exception); 
var 
  Filename: string; 
  LogFile: TextFile; 
begin 
  // prepares log file 
  FileName:=´C:\NomeDaPasta.txt´; 
  AssignFile (LogFile, Filename); 
  if FileExists (FileName) then 
    Append (LogFile) // open existing file 
  else 
    Rewrite (LogFile); // create a new one 

  // write to the file and show error 
  Writeln (LogFile, DateTimeToStr (Now) + ´-> Ocorreu um Erro No Formulário :´+ Screen.activeForm.Caption); 
  Writeln (LogFile,´ O Tipo de erro apresentado foi :´ + E.Message); 
  // close the file 
  CloseFile (LogFile); 
end;


boa sorte...


GOSTEI 0
Rgaffo

Rgaffo

25/10/2005

Tenta assim:

(Components[0].Owner).ClassName --> Isso resulta na classe form que deu o erro.
Ex.: Se o nome do formulário for frmClientes o resultado do comando acima é: TfrmClientes, já ajuda neh?

Sem mais,

Robert


GOSTEI 0
Rgaffo

Rgaffo

25/10/2005

melhor ainda:

[b:457e70dfcf]procedure [/b:457e70dfcf]TForm1.Erro(Sender: TObject; E : Exception);
[b:457e70dfcf]var[/b:457e70dfcf]
ClassRef: TComponent;
[b:457e70dfcf]begin[/b:457e70dfcf]
ClassRef := TComponent(Sender).Components[0].Owner;
ShowMessage(ClassRef.ClassName);
[b:457e70dfcf]end[/b:457e70dfcf];

Essa é minha procedure em que eu centralizo o erro em toda a aplicação, todos os erros vão para essa procedure.
Com o código acima vc consegue pegar o nome do form que deu erro, da mesma forma que o outro código que eu citei, mas com esse ele pega o nome de qq formulário da sua aplicação.


GOSTEI 0
Lnunes

Lnunes

25/10/2005

Marco Salles já testei o código que você postou e funciona exatamente da forma que preciso, ficou muito bom.

Mas gostaria de agradecer tambem a colegas thomaz_prg e braytiner que deram a idéia de utilizar o objeto Screen do Delphi , e dos outros que participaram como o Martins e o Facc.

rgaffo não testei a sua dica pois a minha idéia é utilizar o ApplicationEvents
mas agradeço a sua ajuda.


GOSTEI 0
Rgaffo

Rgaffo

25/10/2005

mas essa dica funciona independente do lugar que vc usar.

[]s


GOSTEI 0
Marco Salles

Marco Salles

25/10/2005

[b:06df9658c1]Citação de LNunes[/b:06df9658c1]
Marco Salles já testei o código que você postou e funciona exatamente da forma que preciso, ficou muito bom.


rgaffo não testei a sua dica pois a minha idéia é utilizar o ApplicationEvents mas agradeço a sua ajuda
.

[b:06df9658c1]Citação de rgaffo[/b:06df9658c1]
mas essa dica funciona independente do lugar que vc usar.



[color=darkred:06df9658c1]Vamos Voltar no tunel do tempo....[/color:06df9658c1]

[b:06df9658c1]Citação de LNunes[/b:06df9658c1]
Facc agradeço primeiramente a sua atenção mas o problema é que esta função fica em um evento do [b:06df9658c1]componente application [/b:06df9658c1]event no formulário principal destinado a capturar qualquer execeção que ocorra no sistema


[color=red:06df9658c1]Vamos recordar um pouco de teoria[/color:06df9658c1]

O Objeto global Application tem um evento chamado OnException...Podemos escrever um método correto e conectar esse método ao código.

Porém a partir do delphi 5.0 foi definido um novo componente que é o AppliationEvents.

E desse componente que o [b:06df9658c1]Lnunes[/b:06df9658c1] se refere . A dica do [b:06df9658c1]rgaffo[/b:06df9658c1] na minha concepção [b:06df9658c1]funciona[/b:06df9658c1] , so que ela ficou um pouco solta no ar... Eu não sei se ele mudou o nome do Componente ApllicationEvents Para Erros ou se ele [b:06df9658c1]não usou o Componente [/b:06df9658c1]e resolveu escrever o método e conencta-lo ao Objeto Global Application, o que acredito eu , deixou o nosso amigo LNunes um pouco confuso

Em poutras palavras , não basta escrever um método Erros do tipo:

procedure TForm1.Erro(Sender: TObject; E : Exception); 
begin 
blablabla....
end; 


[b:06df9658c1]é preciso conecta-lo ou usar o objeto ApplicationEvents...[/b:06df9658c1]

:P :P
Pois bem foi so uma tentativa de entendimento de ambas as partes


GOSTEI 0
Rgaffo

Rgaffo

25/10/2005

Delphiano Marco Salles, o intuito da procedure completa era para dar a visão geral do código, mas o que tinha que ser usado era:

[b:1fa5f30a0f]var[/b:1fa5f30a0f]
ClassRef: TComponent;
[b:1fa5f30a0f]begin[/b:1fa5f30a0f]
ClassRef := TComponent(Sender).Components[0].Owner;
ShowMessage(ClassRef.ClassName);

Que pode ser simplificado para:

[b:1fa5f30a0f]var[/b:1fa5f30a0f]
NomeForm : String;
[b:1fa5f30a0f]begin[/b:1fa5f30a0f]
NomeForm := (TComponent(Sender).Components[0].Owner).ClassName;

Como no exemplo que eu tinha dados antes.

No objeto ApplicationEvents no evento OnException eu posso implementar qualquer código, não é?
Então talvez o que tenha confudindo é por eu ter colocado a visualização do código em uma procedure, dando entender assim que essa procedure tinha que ser usada, mas não era para usa-la é sim o código implementado nela, porém se eu tivesse escrito assim:

[b:1fa5f30a0f]procedure [/b:1fa5f30a0f]TForm1.ApplicationEvents1Exception(Sender: TObject;
E: Exception);
[b:1fa5f30a0f]var[/b:1fa5f30a0f]
ClassRef: TComponent;
[b:1fa5f30a0f]begin[/b:1fa5f30a0f]
ClassRef := TComponent(Sender).Components[0].Owner;
ShowMessage(ClassRef.ClassName);
[b:1fa5f30a0f]end[/b:1fa5f30a0f];

Ninguém tinha ficado com dúvida, mas é a mesma coisa, certo? rsrs :D
Mas o seu código e bem menor e mais fácil de entender.

[]s

Até mais.


GOSTEI 0
POSTAR