Clipper On Line • Ver Tópico - Erro em acesso ao banco de dados com internet lenta

Erro em acesso ao banco de dados com internet lenta

Discussão sobre Banco de Dados e RDDs para Clipper/[x]Harbour.

Moderador: Moderadores

 

Erro em acesso ao banco de dados com internet lenta

Mensagempor cjp » 15 Ago 2014 22:59

Resolvi de uma forma simples: mandar o error.log de dentro do recover. Ficou assim:

bError := ErrorBlock( {|e| Break(e) } )
begin sequence         
DBUSEAREA( .T.,, "SELECT * FROM ativ where data>'"+alltrim(str(year(date()-2)))+"-"+substr(dtoc(date()-2),4,2)+"-"+substr(dtoc(date()-2),1,2)+"'", "ativ")
recover
logerro()
mandmail1("error.log","Erro recuperado com o recover no fazmail")
endsequence            
ErrorBlock( bError )


Só que para isso eu precisei apenas separar uma parte do meu arquivo errorsys.prg em uma função que chamei logerro(), apenas para construir o error.log. Ficou assim:

function logerro
   cMessage := "Ocorreu o erro: "+ansi(cMessage) + Hb_Eol()
   cMessage += "Data..........: "+dtoc(date())+ Hb_Eol()
   cMessage += "Hora..........: "+time() + Hb_Eol()
   cMessage += "Máquina.......: "+netname() + hb_eol()
   cMessage += "Programa......: " + Hb_CmdArgArgV() + Hb_Eol() //+ hb_eol()
   cMessage += ansi("Versão........: ") + vers + Hb_Eol() + Hb_Eol()
   cMessage += ansi("Na função.....: ") + ProcName(2) + Hb_Eol() //+ hb_eol()
   cMessage += "Na linha......: " + NTRIM(ProcLine(2)) + Hb_Eol() //+ hb_eol()
   cMessage += "No prg........: " + procfile(2) + Hb_Eol() + hb_eol()
   cMessage += "Pasta.........: " + CurDir() + Hb_Eol()
   cMessage += ansi("Usuário.......: ") + us + Hb_Eol()
   cMessage += "Base em uso...: " + Alias() + Hb_Eol()
   cMessage += ansi("Área em uso...: ") + alltrim(str(select())) + Hb_Eol()
   cMessage += hb_eol() + ansi("Área 1........: ") + alias(1) + Hb_Eol()
   cMessage += if(!empty(alias(2)),ansi("Área 2........: ") + alias(2) + Hb_Eol(),"")
   cMessage += if(!empty(alias(3)),ansi("Área 3........: ") + alias(3) + Hb_Eol(),"")
   cMessage += if(!empty(alias(4)),ansi("Área 4........: ") + alias(4) + Hb_Eol(),"")
   cMessage += if(!empty(alias(5)),ansi("Área 5........: ") + alias(5) + Hb_Eol(),"")
   cMessage += if(!empty(alias(6)),ansi("Área 6........: ") + alias(6) + Hb_Eol(),"")
   cMessage += if(!empty(alias(7)),ansi("Área 7........: ") + alias(7) + Hb_Eol(),"")
   cMessage += if(!empty(alias(8)),ansi("Área 8........: ") + alias(8) + Hb_Eol(),"")
   cMessage += if(!empty(alias(9)),ansi("Área 9........: ") + alias(9) + Hb_Eol(),"")

   cMessage += Hb_Eol()
   cMessage += "Caminho Percorrido Antes do Erro:"  + Hb_Eol()

   i := 2
   While ( !Empty( ProcName(i) )) //.and. procname(i)#"MAIN" )
         cMessage += "Vindo de......: " + Trim(ProcName(i)) + "(" + NTRIM(ProcLine(i)) + " - " + procfile(i) + ")" + Hb_Eol() + hb_eol()
         i++
   EndDo
   
   cMessage += Hb_Eol()+"Mem¢ria dispon¡vel para valores caracteres: "+alltrim(str(memory(0)))
   cMessage += Hb_eol()+"Maior bloco dispon¡vel para valores caracteres: "+alltrim(str(memory(1)))
   cMessage += Hb_eol()+"µrea dispon¡vel para comandos RUN: "+alltrim(str(memory(2)))

   cMessage += Hb_Eol()
   cMessage += Hb_Eol()

         cMessage += "V¡deo Screen Dump:" + Hb_Eol()
           cMessage += Replicate( '-', nCols -15 ) + Hb_Eol()
           nCellSize := len( Savescreen( 0, 0, 0, 0 ) )
           nRange := ( nCols + 1 ) * nCellSize
           For nCount := 1 To nRows + 1
               cOutString := ''
               cSubString := Substr( cScreen, nStart, nRange )
               For nForLoop := 1 To nRange step nCellSize
                   cOutString += Substr( cSubString, nForLoop, 1 )
               Next
            cMessage += "|" + cOutString + "|" + Hb_Eol()
               nStart += nRange
           Next
           cMessage += Replicate( '-', nCols -18 ) + Hb_Eol()
   Use
   Ferase( "error.log")
   MemoWrit( "error.log", cMessage )
return
Inacio de Carvalho Neto
cjp
Usuário Nível 6

Usuário Nível 6
 
Mensagens: 1531
Data de registro: 19 Nov 2010 21:29
Cidade/Estado: paraná
Curtiu: 10 vezes
Mens.Curtidas: 20 vezes

Erro em acesso ao banco de dados com internet lenta

Mensagempor cjp » 11 Set 2014 16:46

Amigos,

Como havia dito, estou usando com êxito esse begin sequence para contornar erros. Em tudo está funcionando sem problema.

Mas agora tentei usar em uma outra função, desta forma:

               if upper(exclusivo)#"S"
                  if select(bssembarra) = 0
                     bError := ErrorBlock( {|e| Break(e) } )
                     begin sequence
                           use &nomebase. shared
                     recover
                         logerro()
                           mandmail1("error.log","Erro na função usebase contornado com o recover do begin sequence 19142",,2)
                         return .f.
                    endsequence
                    ErrorBlock( bError )
                  else
                     DbSelectArea(bssembarra)
                 exit
                  endif
            else
               if select(bssembarra) = 0
                     bError := ErrorBlock( {|e| Break(e) } )
                     begin sequence
                           use &nomebase. //new
                     recover
                         logerro()
                           mandmail1("error.log","Erro na função usebase contornado com o recover do begin sequence 19157",,2)
                         return .f.
                     endsequence
                     ErrorBlock( bError )
               else
                     DbSelectArea(bssembarra)
                 if exclusivo="S"
                   use
                   use &nomebase. //new
                 else
                   exit
                endif   
               endif
            endif    
               if neterr()
                  vezusb++
                  @ maxrow()-1,1 clear to maxrow()-1,maxcol()-1
                  @ maxrow()-1,1 say "Base "+upper(nomebase)+" ocupada; aguarde liberação ("+alltrim(str(vezusb))+")"
              inkey(8)
              @ maxrow()-1,1 clear to maxrow()-1,maxcol()-1
                  desiste:=inkey(8)
                  if desiste= 27 //K_ESC
                     conf="N"
                     @ maxrow()-2,1 clear to maxrow()-1,maxcol()-1
                     @ maxrow()-1,5 say "Confirma abandono da tentativa da utilização?"get conf pict "@!"
                     read
                     @ maxrow()-2,1 clear to maxrow()-1,maxcol()-1
                     if conf="S"
                   retf="S"
                  exit
*                        return .f.
                     endif
                  endif
               else
                  exit
               endif


Só que, neste caso, ao invés de entrar no recover, o programa está fechando automaticamente, e sem dar qualquer mensagem de erro.

Notei que isso ocorre sempre que a base está em uso por outro programa. Portanto, quando deveria entrar no neterr(), esperando a liberação da base. Mas daí, com o begin sequence, ele já fecha o programa logo.

Alguém saberia me dizer qual a razão disso? E o que eu faço para consertar isso?
Inacio de Carvalho Neto
cjp
Usuário Nível 6

Usuário Nível 6
 
Mensagens: 1531
Data de registro: 19 Nov 2010 21:29
Cidade/Estado: paraná
Curtiu: 10 vezes
Mens.Curtidas: 20 vezes

Erro em acesso ao banco de dados com internet lenta

Mensagempor alxsts » 12 Set 2014 03:26

Olá!

Embora o assunto deste tópico já tenha sido desviado, vou responder a mensagen anterior.
cjp escreveu:...Só que, neste caso, ao invés de entrar no recover, o programa está fechando automaticamente, e sem dar qualquer mensagem de erro...
No momento em que este erro ocorre, o manipulador padrão de erros já é o teu e não mais o ErrorSys. Não sei porque mas NetErr() (DOS Error 32) não é ativado quando ocorre esse erro (arquivo em uso por outra sessão). Assim, o erro não é tratado pelo teu manipulador de erro e não existe outro manipulador. Então, o controle é passado ao sistema operacional o programa é fechado. Teria que tratar "na unha", testando o DOS Error 32.

Veja o exemplo abaixo e adapte-o à suas necessidades.
#define DB_SHARED      .T.
#define DB_EXCLUSIVE   .F.

FUNCTION Main()

   AltD()
   
   SetMode( 50,100)
   OpenTable( "CadOs", { "CadOs" }, NIL, NIL, DB_EXCLUSIVE )
   
   Browse()
   
   If Select( "CadOs" ) > 0
      DbCloseArea( "CadOs" )
   Endif
   
   CLS
   
   RETURN NIL
//-------------------------------------------------------------------------------------------------------------
FUNCTION OpenTable( cName, aIndexList, cAlias, lNewArea, lShared, cDriver, lReadonly )

   LOCAL bError := ErrorBlock( {|e| Break(e) } )
   LOCAL oErr
   LOCAL nPos, nLen
   LOCAL lRet := .F.

   IF ! Empty( cName )
      // verificação dos parâmetros
      lShared := If( lShared == NIL, .T., lShared )
      lNewArea := If( lNewArea == NIL, .T., lNewArea )
      lReadonly := If( lReadonly == NIL, .F., lReadonly )
      cAlias := If( cAlias == NIL, cName, cAlias )
      cDriver := If( cDriver == NIL, "DBFNTX", cDriver )
      aIndexList := If( Empty( aIndexList ), {}, aIndexList )

      BEGIN SEQUENCE

         // Abre a tabela
         IF lNewArea
            DbSelectArea( 0 )
         ENDIF
         
         // DBUSEAREA( lNewArea, cDriver, cName, cAlias, lShared, lReadonly )    ou
         IF lShared
            USE (cName) ALIAS (cAlias) SHARED VIA (cDriver)          // não é necessário usar o macro operator (&) ...
         ELSE
            USE (cName) ALIAS (cAlias) EXCLUSIVE VIA (cDriver)       // ... basta colocar as variáveis entre parêntesis...
         ENDIF
         
         // Abre eventuais índices.
         // Abre de traz para a frente. Assim, o primeiro índice da lista se torna a ordem atual...
         IF ( nLen := Len( aIndexList ) ) > 0
            FOR nPos := nLen TO 1
               DbSetIndex( aIndexList[ nLen ] )
            NEXT
         ENDIF

         lRet := .T.

      RECOVER USING oErr
         IF oErr:osCode == 32
            NetErr( .T. )      //   é possível setar NetErr() para True mas, não se tem detalhes do erro...
         ENDIF                 // ... mas se existe o objeto erro, com os detalhes do erro, é melhor explorar ele
         
         ErrShow( oErr )       // passando o objeto erro para uma rotina de erro ou geração de logs

         // Dispara o erro com o manipulador padrão.
         Eval( bError, oErr )  // No caso de oErr:osCode == 32, nada acontece. Não olhei o ErrorSys.Prg padrão mas acho que ele não trata isso...
      ENDSEQUENCE
   END

   // Restaura o manipulador de erros padrão
   ErrorBlock( bError )

   RETURN lRet
//-------------------------------------------------------------------------------------------------------------

STATIC FUNCTION ErrShow( oErr )

   /*
   oErr:args            An array of function or operator arguments
   oErr:canDefault      Indicates whether or not default recovery is available
   oErr:canRetry        Indicates whether or not a retry is possible after an error
   oErr:canSubstitute   Indicates if a new result can be substituted after an error
   oErr:cargo           User-definable variable
   oErr:description     Character description of the error condition
   oErr:filename        Name of the file associated with the error
   oErr:genCode         CA-Clipper error code number
   oErr:operation       Character description of the failed operation
   oErr:osCode          Operating system error code number
   oErr:severity        Indicates error severity
   oErr:subCode         Subsystem-specific error code number
   oErr:subSystem       Character description of the subsystem generating the error
   oErr:tries           Number of times the failed operation has been attempted
   */

   HB_Alert( { "Ocorreu o erro : " + oErr:subSystem + "/" + Ltrim(Str(oErr:subCode)), "DOS Error " + LTrim(Str(oErr:osCode)), "Descricao: " + oErr:description, "Operacao: " + oErr:Operation, "Arquivo: " + oErr:fileName },{ 'Ok' },"W+/B", 15 )

   RETURN NIL
//-------------------------------------------------------------------------------------------------------------
[]´s
Alexandre Santos (AlxSts)
alxsts
Colaborador

Colaborador
 
Mensagens: 2945
Data de registro: 12 Ago 2008 15:50
Cidade/Estado: São Paulo-SP-Brasil
Curtiu: 21 vezes
Mens.Curtidas: 248 vezes

Erro em acesso ao banco de dados com internet lenta

Mensagempor cjp » 12 Set 2014 23:18

Obrigado, meu caro.

Mas fiquei com duas dúvidas:

1) quando vc diz "No momento em que este erro ocorre, o manipulador padrão de erros já é o teu e não mais o ErrorSys", isso significa que o erro ocorre na linha "use &nomebase.", certo? E este comando está dentro do begin sequence, certo? Bom, mas daí, dando erro dentro do begin sequence, ele não deveria desviar pro recover? E daí executar a função mandmail1?

2) No programa que vc postou, não está da mesma forma que o meu? Quero dizer a linha "USE (cName) ALIAS (cAlias) SHARED VIA (cDriver)" está entre o begin sequence e o RECOVER USING oErr, não?
Inacio de Carvalho Neto
cjp
Usuário Nível 6

Usuário Nível 6
 
Mensagens: 1531
Data de registro: 19 Nov 2010 21:29
Cidade/Estado: paraná
Curtiu: 10 vezes
Mens.Curtidas: 20 vezes

Erro em acesso ao banco de dados com internet lenta

Mensagempor alxsts » 13 Set 2014 12:12

Olá!

A resposta é sim para as duas questões.

Creio que ocorre algum erro dentro da MandMail1 e, como não há tratamento, o programa é encerrado.

Restaure o manipulador de erros padrão antes de invocar a função e veja o que acontece.
      RECOVER USING oErr

         // Restaura o manipulador de erros padrão
         ErrorBlock( bError )

         MandMail1()

      ENDSEQUENCE
   END

[]´s
Alexandre Santos (AlxSts)
alxsts
Colaborador

Colaborador
 
Mensagens: 2945
Data de registro: 12 Ago 2008 15:50
Cidade/Estado: São Paulo-SP-Brasil
Curtiu: 21 vezes
Mens.Curtidas: 248 vezes

Erro em acesso ao banco de dados com internet lenta

Mensagempor cjp » 13 Set 2014 12:45

Eu já fiz isso. Retirando o manipulador, volta ao normal, não há qualquer erro na mandmail1.

Poderia ser algum erro gerado no próprio manipulador?
Inacio de Carvalho Neto
cjp
Usuário Nível 6

Usuário Nível 6
 
Mensagens: 1531
Data de registro: 19 Nov 2010 21:29
Cidade/Estado: paraná
Curtiu: 10 vezes
Mens.Curtidas: 20 vezes

Erro em acesso ao banco de dados com internet lenta

Mensagempor alxsts » 13 Set 2014 14:22

Olá!

O que é "volta ao normal"?

Se na MandMail() não tem erro, talvez tenha na LogErro(). Teste este código:
   LOCAL bError := ErrorBlock( {|e| Break(e) } )

   BEGIN SEQUENCE
   
      ? 1 / 0

   RECOVER USING oErr
      // Restaura o manipulador de erros padrão
      ErrorBlock( bError )

      LogErro()

      MandMail1()
   
   ENDSEQUENCE
[]´s
Alexandre Santos (AlxSts)
alxsts
Colaborador

Colaborador
 
Mensagens: 2945
Data de registro: 12 Ago 2008 15:50
Cidade/Estado: São Paulo-SP-Brasil
Curtiu: 21 vezes
Mens.Curtidas: 248 vezes

Erro em acesso ao banco de dados com internet lenta

Mensagempor cjp » 13 Set 2014 16:05

Quando disse "volta ao normal" quis dizer que não dava mais erro.

Mas vc tinha razão: tinha erro na logerro(). Corrigi e resolveu. Agora vou testar na função que eu estava usando.

Mas antes, fiquei com uma dúvida: o erro que tinha era por falta de definição de uma variável (cMessage), que está definida no errorsys. Quando o logerro() é chamada da errorsys, sem problema. Mas quando ela era chamada do recover do meu manipulador, dava problema. Tentei definir essa variável dentro do próprio logerro(), do jeito que está no teu exemplo anterior, mas não funcionou. Veja, fiz assim:

cMessage := If( cMessage == NIL, "", cMessage )


Não era pra funcionar assim? Por que continuou dando variável inexistente?

Agora eu defini ela no início do programa, e deu certo. Mas eu preferia fazer desta forma que vc fez.
Inacio de Carvalho Neto
cjp
Usuário Nível 6

Usuário Nível 6
 
Mensagens: 1531
Data de registro: 19 Nov 2010 21:29
Cidade/Estado: paraná
Curtiu: 10 vezes
Mens.Curtidas: 20 vezes

Erro em acesso ao banco de dados com internet lenta

Mensagempor alxsts » 13 Set 2014 18:44

Olá!
cjp escreveu:Tentei definir essa variável dentro do próprio logerro(), do jeito que está no teu exemplo anterior, mas não funcionou.
Neste caso você não definiu a variável. Apenas testou se o conteúdo da variável estava NIL ou não. Como a variável não existe neste instante, gera erro.

Naquele exemplo acima, foram testadas as variáveis que a função recebeu como parâmetros de entrada. Sempre que uma função recebe parâmetros são criadas variáveis do tipo LOCAL, com os nomes dos parâmetros recebidos ou seja, são declaradas variáveis locais à função. Veja:
FUNCTION Teste()

   ? MessageShow( "Brasil" )

RETURN NIL
//--------------------------------------------

FUNCTION MessageShow( cMessage )

   cMessage := IF( cMessage == NIL, "NIL", cMessage )   // ou cMessage := IF( Empty( cMessage ), "NIL", cMessage )

   Alert( cMessage )

RETURN NIL
//--------------------------------------------
Resumindo: a melhor prática é sempre declarar todas as variáveis que o programa utiliza. Use sempre variáveis dos tipos LOCAL e/ou STATIC. Com os avanços do Harbour, é possível especificar o tipos das variáveis definidas. Ainda não podemos dizer que o Harbour é uma linguagem fortemente tipada mas, usar este recurso faz com que o compilador gere avisos (warnings), dependendo das configurações de compilação, quando o programador faz atribuições de valores de dados às variáveis diferentes dos tipos declarados.
LOCAL aArray AS Array
LOCAL nVal AS Numeric
LOCAL dDate AS Date
LOLAL cVal AS Character

   // as linhas abaixo gerarão warnings pois os dados atribuídos às variáveis são diferentes dos declarados
   aArray := "Teste"
   nVal := "10"
   dDate := DtoS( Date() )
   cVal := Date()
[]´s
Alexandre Santos (AlxSts)
alxsts
Colaborador

Colaborador
 
Mensagens: 2945
Data de registro: 12 Ago 2008 15:50
Cidade/Estado: São Paulo-SP-Brasil
Curtiu: 21 vezes
Mens.Curtidas: 248 vezes

Erro em acesso ao banco de dados com internet lenta

Mensagempor cjp » 14 Set 2014 02:21

Entendido. Muito obrigado.
Inacio de Carvalho Neto
cjp
Usuário Nível 6

Usuário Nível 6
 
Mensagens: 1531
Data de registro: 19 Nov 2010 21:29
Cidade/Estado: paraná
Curtiu: 10 vezes
Mens.Curtidas: 20 vezes

Erro em acesso ao banco de dados com internet lenta

Mensagempor cjp » 18 Out 2014 00:36

Caros colegas,

Por favor, observem este trecho de uma função minha:

         bError := ErrorBlock( {|e| Break(e) } )
         begin sequence
              append blank
              repl arqmand with am
              repl assmail with asm+"; bsusonow: "+alltrim(str(bsusonow))+"; área: "+alltrim(str(select()))+"; data: "+dtoc(date())+"; hora: "+time()
              repl maildst with md
             repl anexo with an
             repl tela with cMessage
         recover
              cMessage := ErrorMessage(e)
             logerro()
            mandmail1("error.log","Erro recuperado com o recover no fazmail",,2)
         endsequence
         ErrorBlock( bError )


A ideia é contornar eventuais erros no primeiro trecho, o que tem acontecido satisfatoriamente.

O único problema é que, quando ocorre o erro, eu precisaria saber qual é o erro. Por isso coloquei:

              cMessage := ErrorMessage(e)


Daí, na função logerro() eu crio um arquivo de log com vários detalhes que o programa me envia automaticamente com a função mandmail1().

O problema é que cMessage está retornando vazio. E assim eu não consigo saber qual o erro que está dando dentro da sequência.

Em outros testes, acontece também de o programa fechar sem dar nenhum erro. Daí eu restaurei o ErrorBlock( bError ) e deu o seguinte erro:

Error BASE/1003  Variável não existe: E


Se eu bem entendi, esse E não seria o e do bError := ErrorBlock( {|e| Break(e) } )? Se for, por que seria uma variável inexistente?

Alguém me ajuda?
Inacio de Carvalho Neto
cjp
Usuário Nível 6

Usuário Nível 6
 
Mensagens: 1531
Data de registro: 19 Nov 2010 21:29
Cidade/Estado: paraná
Curtiu: 10 vezes
Mens.Curtidas: 20 vezes

Erro em acesso ao banco de dados com internet lenta

Mensagempor Toledo » 22 Out 2014 17:02

Inácio, se você estiver usando o comando bError := ErrorBlock( {|e| Break(e) } ), infelizmente não tem como saber qual o erro que ocorreu, pois o comando Break(e) vai encerrar a chamada do ERRORSYS e desviar a execução do programa para depois do comando RECOVER. Então, sem a execução do ERRORSYS, não tem como saber qual foi o erro.

Quando lhe foi sugerido o uso do bError := ErrorBlock( {|e| Break(e) } ), foi exatamente porque você não queria que o ERRORSYS fosse executado.

Então, ou você usa o bError := ErrorBlock( {|e| Break(e) } ) e evitar que o ERRORSYS seja executado, ou retira a linha do ErrorBlock e deixa o ERRORSYS ser executado, onde você poderá saber qual o erro que está ocorrendo, criar o log e enviar o e-mail.

Abraços,
Toledo - Clipper On Line
toledo@pctoledo.com.br
Harbour 3.2/MiniGui/HwGui
Faça uma doação para o fórum, clique neste link: http://www.pctoledo.com.br/doacao
Avatar de usuário

Toledo
Administrador

Administrador
 
Mensagens: 3038
Data de registro: 22 Jul 2003 18:39
Cidade/Estado: Araçatuba - SP
Curtiu: 263 vezes
Mens.Curtidas: 258 vezes

Erro em acesso ao banco de dados com internet lenta

Mensagempor cjp » 22 Out 2014 17:23

Entendi.

Mas tem como executar o errorsys() e depois retornar, com o recover ou de alguma outra forma, para o ponto do programa onde deu erro e prosseguir normalmente?

O que eu preciso evitar é a interrupção do programa pelo erro, o que o begin sequence está fazendo maravilhosamente bem. Mas também preciso do log do erro. Dá pra juntar o melhor dos dois mundos?
Inacio de Carvalho Neto
cjp
Usuário Nível 6

Usuário Nível 6
 
Mensagens: 1531
Data de registro: 19 Nov 2010 21:29
Cidade/Estado: paraná
Curtiu: 10 vezes
Mens.Curtidas: 20 vezes

Erro em acesso ao banco de dados com internet lenta

Mensagempor Toledo » 22 Out 2014 18:17

cjp escreveu:Mas tem como executar o errorsys() e depois retornar, com o recover ou de alguma outra forma, para o ponto do programa onde deu erro e prosseguir normalmente?

Sim, é possível, basta modificar o ERRORSYS e trocar o comando QUIT por Break(e). Mas neste caso, o uso do comando Begin sequence... Recover... endsequence será obrigatório em todos os módulos do seu programa, porque quando ocorrer qualquer erro tem que ter o Recover para retornar a execução do programa, caso contrário, o erro ocorrer sem existir um Recover para retorno, a execução vai retornar no mesmo ponto onde ocorreu o erro e ai se o erro persistir será chamado novamente o ERRORSYS (ficando num LOOP infinito).

Geralmente quando o ERRORSYS tem o QUIT trocado por Break(e), o Begin Sequence é colocado no menu do programa inicial, logo após o comando MENU TO. Assim quando ocorrer qualquer erro no programa, a execução vai retornar para o menu no programa inicial. Já o comando QUIT no ERRORSYS vai finalizar o programa, retornando para o DOS.

Abraços,
Toledo - Clipper On Line
toledo@pctoledo.com.br
Harbour 3.2/MiniGui/HwGui
Faça uma doação para o fórum, clique neste link: http://www.pctoledo.com.br/doacao
Avatar de usuário

Toledo
Administrador

Administrador
 
Mensagens: 3038
Data de registro: 22 Jul 2003 18:39
Cidade/Estado: Araçatuba - SP
Curtiu: 263 vezes
Mens.Curtidas: 258 vezes

Erro em acesso ao banco de dados com internet lenta

Mensagempor alxsts » 23 Out 2014 01:01

Olá!

Inácio: creio que o que você não está entendendo é o funcionamento, a mecânica da coisa.

Sempre que um erro é detectado, o Clipper ou (x)Harbour automaticamente gera um objeto erro e passa este objeto erro ao manipulador de erros ativo. Se for o ErrorSys padrão, o objeto erro vai ser passado para ele. Se houver um manipulador de erros personalizado, como nos exemplos mostrados, o objeto erro será passado para este manipulador personalizado.

Veja:

1 - você define o seu manipulador de erros personalizado com bError := ErrorBlock( {|e| Break(e) } ). Neste momento, o ErrorSys padrão é armazenado em bError e um novo manipulador de erros se torna ativo.
2 - durante o processamento da aplicação, ocorre um erro qualquer. O Clipper ou (x)Harbour intercepta o erro e gera um objeto da classe Error
3 - em seguida, o Clipper ou (x)Harbour passa o objeto Error gerado para o manipulador de erros ativo. Supondo que o manipulador ativo tenha sido definido com bError := ErrorBlock( {|e| Break(e) } ), o objeto Error será recebido como o parâmetro e ( {|e| Break( e ) } ) no code block do manipulador de erros e será repassado como parâmetro de entrada da função tratadora de erros. Neste caso, está sendo usada a função Break() mas poderia ser uma outra, definida por você mesmo. Veja que a função recebeu o objeto de erro como parâmetro de entrada ( Break( e ) )
4 - Para que você possa capturar e tratar este objeto Erro gerado em sua aplicação, é necessário receber este objeto Erro. Este é o ponto que acho que você ainda não percebeu. Para receber o objeto, é necessária a cláusula RECOVER USING. Quando Break( e ) é executado, o objeto Erro é passado para a variável declarada (neste caso oErr) e fica disponível para o teu programa tratar
LOCAL oErr

BEGIN SEQUENCE
.
.
.
RECOVER USING oErr
.
.
.
ENDSEQUENCE

5 - com este objeto Erro em mãos, você poderá tratar o erro de forma muito flexível, explorando todas as propriedades do objeto Erro (listadas no link acima), sem ter que recorrer ao GetSys. Se preferir recorrer a ele, basta executar um Break( bError ) - lembra que você guardou o manipulador padrão em bError?
6 - exemplo de operação que dá erro e permite que se tente novamente:
FUNCTION Teste()

   LOCAL bError := ErrorBlock( {|e| Break(e) } ), nOption

   Altd()
   
   CLS

   WHILE .T.

      BEGIN SEQUENCE
         
         ?

         FOR nOption := 10 TO 0 STEP -1
            ? 10 / nOption
         NEXT

      RECOVER USING oErr

         nOption := Alert( "Ocorreu o erro " + ;
                           oErr:subsystem + "/" + ;
                           Ltrim( Str( oErr:subCode ) ) + ;
                           " - " + oErr:description +  ;
                           ' na operação "' + oErr:operation + '"', { " Continuar ", " Fechar "} )
     
   
         //LogErro()

         //MandMail1()
   
         IF nOption != 1
            EXIT
         ELSE
            LOOP
         ENDIF

      ENDSEQUENCE
   ENDDO

   // Restaura o manipulador de erros padrão
   ErrorBlock( bError )

   RETURN NIL
[]´s
Alexandre Santos (AlxSts)
alxsts
Colaborador

Colaborador
 
Mensagens: 2945
Data de registro: 12 Ago 2008 15:50
Cidade/Estado: São Paulo-SP-Brasil
Curtiu: 21 vezes
Mens.Curtidas: 248 vezes

Anterior Próximo



Retornar para Banco de Dados

Quem está online

Usuários vendo este fórum: Nenhum usuário registrado online e 6 visitantes


Ola Amigo, espero que meu site e forum tem lhe beneficiado, com exemplos e dicas de programacao.
Entao divulgue o link da Doacao abaixo para seus amigos e redes sociais ou faça uma doacao para o site forum...
MUITO OBRIGADO PELA SUA DOACAO!
Faça uma doação para o forum
cron
v
Olá visitante, seja bem-vindo ao Fórum Clipper On Line!
Efetue o seu login ou faça o seu Registro