Freigeben über


Desafio da Semana #5


Desafio da semana #5

Por: Roberto Alexis Farah

Oi pessoal!

Eis o novo desafio, simples, mas muito interessante.

CENÁRIO

Imagine uma situação típica: você foi o desenvolvedor designado para identificar onde um componente Visual Basic 6 rodando no COM+ está lançando uma exceção fatal e derrubando o processo.

Você precisa obter mais detalhes dessa exceção de modo a achar o real problema. Você faz idéia do método que esteja lançando a exceção.

Para simplificar, imagine que a solução proposta deverá servir para o pequeno método abaixo ou para um complexo e grande método. O código abaixo mostra claramente o ponto onde ocorre a exceção, sem corrigir o código você deve usar um mecanismo para obter mais detalhes da exceção e, preferivelmente, salvar isso em algum lugar, como Event Viewer.

Public Sub DivideByZero()
Dim x As Long
Dim y As Long

y = 5
MsgBox y / x 'error
End Sub

 

SINTOMA

Crash em componente rodando no COM+.

OBJETIVO

O PROBLEMA é bastante óbvio no exemplo acima, uma divisão por zero, entretanto, o que interessa nesse desafio é propor uma SOLUÇÃO que você possa aplicar em outros métodos, seja de uma aplicação executável, DLL ou componente rodando no COM+, desde que feitos com Visual Basic 6.

A solução deve consistir de:

- Salvar os detalhes da exceção e informações relevantes no Event Viewer de modo que ao analisar o Event Viewer seja fácil se saber de onde a exceção é lançada e os detalhes sobre a mesma.

Nota: Sim, é fácil, mas há um macete que torna a solução muito melhor e não é algo muito conhecido! ;)

Semana que vem apresento a resposta.

Boa semana a todos!

Comments

  • Anonymous
    June 02, 2006
    Pessoal, como nenhum post foi colocado, deixarei uma semana mais antes de publicar a resposta e colocar um novo desafio. Enquanto isso, estarei publicando um artigo ainda hoje. Fiquem de olho. :)
  • Anonymous
    June 08, 2006
    Olá amigos,

    Mais uma vez um assunto excelente para ser abordado aqui nesse blog.

    Inicialmente precisamos nos preocupar em certificarmos que todas as rotinas tem tratamento adequado de erro. Contudo apenas isso não é suficiente, imagine um método um pouco mais extenso que o apresentado, mesmo com um tratamento de erros regular não seríamos capazes de identificarmos exatamente qual comando dentre tantos presentes nesse método que possa ter gerado o problema. A mina sugestão é a utilização de uma técnica bastante antiga do Basic que fora também encorporada ao Visual Basic, que é a numeração de código.

    A enumeração de código é um antigo recurso do basic que era muito utilizado como marcador, podendo-se utilizá-la para definição de labels, como no exemplo abaixo:

    Private Function Contador(ByVal Qt As Integer) As Long
    1 Dim RetVal As Long
    2
    3 If Qt > 0 Then
    4  RetVal = RetVal + 1
    5  Qt = Qt - 1
    6  Goto 3             'move cursor de execução para linha 3
    7 End If
    8 Contador = RetVal
    End Function

    Claro que o exemplo acima, serve apenas para demonstração de labels por numeração, mas não é uma forma das mais elegantes de se escrever...

    O recurso de enumeração também pode ser utilizado para resolver o problema de melhor detecção de erros, da seguinte maneira:

    Public Sub DivideByZero()
    1  Dim x As Long
    2  Dim y As Long
    3  On Error GoTo DeuErro
    4  y = 5
    5  MsgBox y / x 'error
    6  Exit Sub
    7 DeuErro:
    8  MsgBox "Ocorreu um erro na execução" + vbCrLf + vbCrLf + "Número: " + CStr(Err) + vbCrLf + "Descrição: " + Error$ + vbCrLf + "Linha: " + CStr(Erl), vbCritical
    End Sub

    Note que, ocorrido um erro, o programa irá mostrar detalhadamente qual o número do erro, sua descrição e ainda a linha que gerou o problema.

    O uso de enumeração é uma boa prática para localização de problemas. Contudo, é bastante evidente que o código não fica nada agradável... É muito trabalhoso codificar e se preocupar simultaneamente com enumeração. Desenvolvi portanto um programa que faz de forma automática a enumeração de meu código antes que eu gere uma release do produto. Assim sempre guardo cópia enumerada do código referente a cada release para poder numa situação de erro, ter maiores detalhes quanto sua ocorrência.

    Acredito que deve existir uma série de outros programas que fazem também enumeração do código basic.

    Para escrita no Event Viewer conforme sugerido no desafio podemos fazer utilizando comandos internos do Visual Basic ou diretamente por API, para utilizaçao pelo Visual Basic utilizaríamos:

    App.LogEvent "Ocorreu um erro na execução" + vbCrLf + vbCrLf + "Número: " + CStr(Err) + vbCrLf + "Descrição: " + Error$ + vbCrLf + "Linha: " + CStr(Erl), 1

    Mas há uma forma um pouco mais rebuscada que seria utilizando-se a api:

    Private Declare Function ReportEvent
    Lib "advapi32" Alias "ReportEventA" (ByVal hEventLog As Long, ByVal wType As Long, ByVal wCategory As Long, ByVal dwEventID As Long,
    ByVal lpUserSid As Long, ByVal wNumStrings As Long, ByVal dwDataSize As Long, lpStrings As Any, lpRawData As Any) As Long

    Com a ReportEventA temos como detalhar um pouco mais o evento gerado.

    Até a próxima.

    Abraços
  • Anonymous
    June 09, 2006
    Olá Danilo,
    Parabéns pela resposta! Absolutamente correta!
    O legal dessa solução é que ela se baseia em um comando antigo do Visual Basic e, por isso, pouco utilizado.
    Obrigado pela participação! :)
  • Anonymous
    June 29, 2006
    Olá para todos,

    Achei bem interessante o mecanismo apresentado, bem aplicável para o ambiente VB6 e esse tipo de situação.

    E como curiosidade, para soluções em .NET, segue um artigo bem interessante sobre o tratamento de exceptions:

    http://msdn.microsoft.com/library/default.asp?url=/library/en-us/dnbda/html/exceptdotnet.asp

    Uma leitura valiosa.

    Abraços!

    Waldemas...