Página 1 de 1

Try..Catch..End -> número da linha onde ocorre o erro

Enviado: 26 Ago 2016 20:57
por asimoes
Pessoal,

Não sei se é possível,

São erros "tratáveis"

Usando try..catch..end, é possível pegar o número da linha do código, onde no exemplo a=b, a variável b não existe.
Isso para não usar ErrorBlock que mostra a linha onde ocorre o erro mas encerra a aplicação:

Código: Selecionar todos

ErrorBlock( { | oErro | DefError( oErro ) } )

Código: Selecionar todos

   Try
      A=B //variável b não existe
   Catch oErro

   end

Try..Catch..End -> número da linha onde ocorre o erro

Enviado: 26 Ago 2016 21:35
por asimoes
Consegui,
Usando BEGIN..SEQUENCE

Código: Selecionar todos

   BEGIN SEQUENCE WITH {| oError | oError:cargo := { ProcName( 1 ), ProcLine( 1 ) }, Break( oError ) }
      A=B
   RECOVER USING oError   
     ? oError:Cargo[1] //Procname
     ? oError:Cargo[2] //Procline
   END

Try..Catch..End -> número da linha onde ocorre o erro

Enviado: 27 Ago 2016 00:29
por fladimir
:-Y :-Y :-Y

Try..Catch..End -> número da linha onde ocorre o erro

Enviado: 27 Ago 2016 11:44
por JoséQuintas
Se não me engano, a indicação na frente de BEGIN SEQUENCE é só pra quando NÃO vai usar a rotina de erro padrão.
E o TRY/CATCH ou outro, é pra não precisar algo mais.

Uso assim, não sei se interessa pra alguma situação:

Código: Selecionar todos

lOk := .F.
BEGIN SEQUENCE WITH __BreakBlock()
    ...
  lOk := .T.
END SEQUENCE
IF .NOT. lOk
   ? "deu erro na rotina"
ENDIF
Explicação:
Se tudo correr bem, chega até lOk := .T.
Se der algum erro no trajeto, não chega nessa linha, e lOk é .F.

Ou dependendo da rotina, uma variável string que vai se modificando, e no final contém "OK".

Código: Selecionar todos

cStatus := "ERRO"
BEGIN SEQUENCE WITH __BreakBlock()
   cStatus := "sei lá o que"
   ...
   cStatus := "sei lá de novo"
   ...
   cStatus := "ok"
END SEQUENCE
IF cStatus != "ok"
   MsgExclamation( "O erro foi " + cStatus )
ENDIF
Acho que quanto menos exceções melhor, mas cada caso é um caso diferente.

Try..Catch..End -> número da linha onde ocorre o erro

Enviado: 27 Ago 2016 13:10
por asimoes
Quintas,

Está correto o seu ponto de vista, o meu exemplo garante em código que tenha um grande número de if´s, do case, etc, e no meio tenha alguma variável atribuindo valor de uma outra que vai gerar um erro, ao indicar a linha do erro facilita para o programador uma rápida correção, concordo que cada caso é um caso.

Try..Catch..End -> número da linha onde ocorre o erro

Enviado: 27 Ago 2016 13:38
por JoséQuintas
Esquisito, nesse caso o BEGIN SEQUENCE até perde o sentido.
Melhor seria atrbiuir valores default.

Eu uso onde sei que pode ocorrer erro.
Exemplo, abrir uma conexão.

Código: Selecionar todos

METHOD Open( lError ) CLASS ADOClass

   LOCAL lOk := .F., nCont, cMessage

   hb_Default( @lError, .T. )
   WSave( MaxRow() - 1, 0, MaxRow(), MaxCol() )
   FOR nCont = 1 TO 5
      BEGIN SEQUENCE WITH __BreakBlock()
         IF ::cn:State() != AD_STATE_OPEN
            ::Cn:Open()
         ENDIF
         DO WHILE ::cn:State() != AD_STATE_OPEN
            Inkey(1)
         ENDDO
         lOk := .T.
      END SEQUENCE
      IF lOk
         EXIT
      ENDIF
      Mensagem( "Falhou pra conectar com servidor, tentativa " + LTrim( Str( nCont ) ) + "/5" )
      BEGIN SEQUENCE WITH __BreakBlock()
         cMessage := LTrim( Str( ::Cn:Errors(0):Number() ) ) + " " + ::Cn:Errors(0):Description()
         Mensagem( cMessage )
         WriteErrorLog( cMessage, 2 )
      END SEQUENCE
      Inkey(10)
   NEXT
   IF lError .AND. .NOT. lOk
      Eval( ErrorBlock() )
      QUIT
   ENDIF
   WRestore()

   RETURN lOk

Try..Catch..End -> número da linha onde ocorre o erro

Enviado: 27 Ago 2016 13:44
por JoséQuintas
Esta aqui também é legal, pra testar macro:

Código: Selecionar todos

cFiltro := "cliente->Código == 5 .and. cliente->Cidade=='SAO PAULO'"

IF MacroType( cFiltro ) != "L"
   MsgExclamation( "Expressão inválida para filtro" )
ENDIF
...

FUNCTION MacroType( cExpression )

   LOCAL cType := "U", bBlock

   BEGIN SEQUENCE WITH __BreakBlock()
      bBlock := hb_MacroBlock( cExpression )
      cType  := ValType( Eval( bBlock ) )
   END SEQUENCE

   RETURN cType

Try..Catch..End -> número da linha onde ocorre o erro

Enviado: 27 Ago 2016 17:23
por asimoes
Quintas,

O intuito é esse mesmo, estamos usando agora begin..sequence do exemplo em uma classe que faz operações no banco oracle.

Usava-se antes o try..catch, mas o try..catch tem limitações.

E no recover, estamos enviando email para a equipe responsável pelo sistema, estes sistemas são corporativos da prefeitura.

Aconteceu um problema no banco esta semana onde um colega nosso simplesmente tirou os grants do usuário aplicação do banco e começou a pipocar erro, só que ficava em try..catch e o usuário não estava nos informando o que estava acontecendo, enfim agora todos nós vamos saber quando acontecer de novo.

Try..Catch..End -> número da linha onde ocorre o erro

Enviado: 27 Ago 2016 18:19
por JoséQuintas
Uso isto.
Até o comando SQL usado vém na mensagem de erro.

Código: Selecionar todos

METHOD ExecuteCmd( cSql, lError ) CLASS ADOClass

   LOCAL lOk := .F., cMensagem := "", Rs

   IF ::Cn == NIL
      RETURN NIL
   ENDIF
   hb_Default( @lError, .T. )
   cSql := iif( cSql == NIL, ::cSql, cSql ) // não pode usar hb_Default
   IF ::Cn:State() != AD_STATE_OPEN
      ::Open()
   ENDIF
   cSql := Trim( cSql )
   IF Right( AllTrim( cSql ), 1 ) != ";"
      cSql += ";"
   ENDIF
   IF Len( Trim( cSql ) ) != 0
      BEGIN SEQUENCE WITH __BreakBlock()
         Rs := ::Cn:Execute( cSql )
         lOk := .T.
      ENDSEQUENCE
      IF .NOT. lOk
         cMensagem += "Erro executando comando:" + LTrim( Str( ::Cn:Errors( 0 ):Number( ) ) ) + " " + ::Cn:Errors( 0 ):Description()
         WriteErrorLog( cMensagem )
         WriteErrorLog( cSql, 2 )
         IF lError
            Eval( ErrorBlock() )
            QUIT
         ENDIF
      ENDIF
   ENDIF

   RETURN Rs

Try..Catch..End -> número da linha onde ocorre o erro

Enviado: 28 Ago 2016 22:47
por JoséQuintas
Aproveitar que deu erro nos testes pra mostrar como sai minha mensagem de erro.

Código: Selecionar todos

Erro executando comando:-2147217900 [MySQL][ODBC 3.51 Driver][mysqld-5.7.12-log]You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near 'HLDIMRAT WHERE LOCADOR=1764 LOCATARIO=1764010 AND CIC='xxx'' at line 1
--------------------------------------------------------------------------------
Error on 28/08/2016 22:41:52
JPA: 2016.08.28.2240
Login JPA: JOSEQ
Alias:  TEMPRATEIO
MySQL local: SIM

Harbour: Harbour 3.4.0dev (b6c8382) (2016-08-12 12:06)
Compiler: Microsoft Visual C++ 16.0.40219 (32-bit)
GT: WVG
Folder: d:\JPA\haroldo\locacao\
Windows: Windows 7 6.1 SP1
Computer Name: JOSEJPA

DELETE FORM HLDIMRAT WHERE LOCADOR=1764 LOCATARIO=1764010 AND CIC='xxxx';
Called from PDIMOBFUNCRATEIOTBROWSE(584)  
Called from (b)RATEIOTBROWSE(553)  
Called from DBVIEW(156)  
Called from RATEIOTBROWSE(553)  
Called from PDIMOBFUNCLOCATARIOTBROWSE(464)  
Called from (b)LOCATARIOTBROWSE(415)  
Called from DBVIEW(156)  
Called from LOCATARIOTBROWSE(415)  
Called from PDIMOBFUNCLOCADORTBROWSE(265)  
Called from (b)LOCADORTBROWSE(235)  
Called from DBVIEW(156)  
Called from LOCADORTBROWSE(235)  
Called from PDIMOBCAD(34)  
Called from DO(0)  
Called from BOXMENU(497)  
Called from BOXMENU(479)  
Called from MAINMENU(347)  
Called from MAIN(107)  

Try..Catch..End -> número da linha onde ocorre o erro

Enviado: 14 Dez 2016 15:16
por Vlademiro
Não precisa usar a variável lOk para controlar o erro, basta fazer conforme o exemplo abaixo:

Código: Selecionar todos


 BEGIN SEQUENCE WITH __BreakBlock()
      oInmail := TIPClientSMTP():New( oUrl, xTrace,, cClientHost )
   RECOVER
      RETURN .F.  // Executa somente se deu erro 
   END SEQUENCE

Try..Catch..End -> número da linha onde ocorre o erro

Enviado: 14 Dez 2016 16:17
por JoséQuintas
Por coincidência vi isso hoje.
Olhei em hbcompat.ch a definição de TRY/CATCH.

Try..Catch..End -> número da linha onde ocorre o erro

Enviado: 14 Dez 2016 16:21
por JoséQuintas
E voltando ao assunto que deu origem a tudo:

A errorsys normal já mostra erro, com linha e toda callstack.
Porque BEGIN SEQUENCE, se vai fazer exatamente a mesma coisa?

Try..Catch..End -> número da linha onde ocorre o erro

Enviado: 15 Dez 2016 09:27
por asimoes
Porque o programador pode tratar o erro e decidir se encerra a aplicação ou não
Errorsys encerra a aplicação