Tratamento de Erros
Teoricamente é possível criar uma aplicação em que todos os erros são tratados de modo a não acontecerem, ou seja, nunca existirem. Esta teoria na realidade não acontece por vários motivos, sendo como principal o facto do programador não contemplar ou não conseguir contemplar todos os possíveis problemas durante o desenvolvimento.
Uma correcta gestão dos erros na aplicação evita mensagens difíceis de analisar, aplicações a fecharem inesperadamente e torna, obviamente, as aplicações mais profissionais e robustas.
Com a introdução do .NET apareceu um novo método em substituição ao On Error Go To <label>. O método Try … Catch … End Try permite criar um bloco no código onde o erro é verificado e tratado. É simples de implementar, muito eficiente e com diversas variações que dão uma maior flexibilidade. Num exemplo simples funciona desta forma:
Try
' código do programa
Catch ex As Exception
MessageBox.Show(ex.Message)
End Try
No entanto existem mais variações que permitem uma melhor gestão dos erros. São o caso de instruções com o Finally, que permite que o código execute sempre, ou seja, caso exista ou não erro, e o When, que permite decidir se o erro é ou não “agarrado”.
Além disso pode-se a qualquer momento dizer que ocorreu um erro e forçar a mensagem sem duplicar código, através da instrução Throw.
Eis um pequeno exemplo, com a alteração de um valor ou outro, permite alterar a forma como a mensagem/erro é tratado, e mostra alguns métodos que é possível implementar:
Sub CalculaResultado(ByVal valor1 As Integer, ByVal valor2 As Integer, ByVal ignoraErro As Boolean)
Try
' Verifica se os valores são zero
If valor1 = 0 AndAlso valor2 = 0 Then
' Define uma nova ArgumentNullException
Dim msgErro As String = "Os valores a calcular não podem ser os dois 0"
Throw New ArgumentNullException(msgErro, New Exception(String.Empty))
End If
' Caso o valor 1 seja zero, vai ser originada uma
' ArithmeticException devido à divisão por zero
Dim valorfinal As Integer = valor2 / valor1
' Neste exemplo caso o resultado seja menor que 10
' origina uma Exception simples
If valorfinal < 10 Then
Throw New Exception("O valor final não é valido")
End If
Catch ex As ArithmeticException When ignoraErro = False
Debug.WriteLine("Não é permitida uma divisão de um valor por zero")
Catch ex As ArgumentNullException When ignoraErro = False
Debug.WriteLine(ex.Message)
Catch ex As Exception
Debug.WriteLine(ex.Message)
Finally
Debug.WriteLine("Fim do exemplo!")
End Try
End Sub
E alguns resultados:
' Calcula o resultado com números a zero
CalculaResultado(0, 0, False)
Os valores a calcular não podem ser os dois 0
Fim do exemplo!
' Provoca uma divisão por zero
CalculaResultado(0, 50, False)
Não é permitida uma divisão de um valor por zero
Fim do exemplo!
' Provoca uma divisão por zero, mas não trata o erro
CalculaResultado(0, 50, True)
Arithmetic operation resulted in an overflow.
Fim do exemplo!
' Calcula onde o resultado é inferior a 10
CalculaResultado(45, 50, False)
O valor final não é valido
Fim do exemplo!
Inserir Imagens no SQL Server
Em dois artigos anteriores, foram abordadas algumas formas de trabalhar com dados num servidor SQL. Gestão de Dados em SQL Server - Parte I e Gestão de Dados em SQL Server - Parte II mostraram como inserir, modificar, apagar e ler dados, mas no entanto podem-se também inserir imagens e não basta simplesmente indicar qual é a imagem.
Existem duas alternativas para a gestão de imagens: guardar apenas a localização e colocar a imagem no servidor ou gravar a imagem directamente num campo.
Para inserir a imagem é necessário ler, gravar num array de bytes e finalmente utilizar esse array para gravar na base de dados.
Eis um exemplo de como o fazer:
' Define a Connection String
Dim myConnectionString As String = _
"Data Source=.\SQLEXPRESS;AttachDbFilename='c:\myDatabase.mdf';Integrated Security=True;User Instance=True"
Try
' Cria um novo FileStream para leitura da imagem
Dim fs As New IO.FileStream("c:\image.jpg", IO.FileMode.Open, IO.FileAccess.Read)
' Cria um array de Bytes do tamanho do FileStream
Dim ImageData(fs.Length() - 1) As Byte
' Lê os bytes do FileStream para o array criado
fs.Read(ImageData, 0, ImageData.Length)
' Fecha o FileStream ficando a imagem guardada no array
fs.Close()
Using connection As New SqlClient.SqlConnection(myConnectionString)
' Define o comando Transact-SQL para inserir dados
Dim SQL As String = "INSERT INTO contacts ([name],[img]) VALUES (@name,@img);"
Dim command As New SqlClient.SqlCommand(SQL, connection)
' Define os parâmetros para a inserção de dados, onde está o array
' de bytes(imagem) a ser inserida. O tipo do campo é Image
command.Parameters.Add("@name", SqlDbType.VarChar).Value = "jpaulino"
command.Parameters.Add("@img", SqlDbType.Image).Value = ImageData
connection.Open()
' Insere os campos no SQL
command.ExecuteNonQuery()
End Using
Catch ex As Exception
MessageBox.Show(ex.Message, My.Application.Info.Title, MessageBoxButtons.OK, MessageBoxIcon.Error)
End Try
PS: Como sempre, qualquer dúvida, comentário ou correcção ao artigo é sempre bem vinda!
No VB.NET não está disponível uma label que permita criar um sombreado no texto de modo a tornar-lo com mais destaque. Esta propriedade é muito comum em ambiente Office, em programas como o Excel, Word, etc, mas está disponível também em muitos outros programas.
Para criar uma label que permita criar um sombreado é preciso desenhar o texto através do namespace System.Drawing. O conceito é bastante simples: a label escreve um texto, que será a sombra, e através do evento onPaint() desenha-se o texto que fica por cima.
Depois é escondida a propriedade ForeColor (que define a cor do texto) porque esta não será a cor do texto mas sim da sombra e são criadas algumas novas propriedades:
- OffsetX (define o offset, ou desvio, na vertical face ao texto inicial)
- OffsetY (define o offset, ou desvio, na horizontal face ao texto inicial)
- ForeColorFront (define a cor que fica por cima)
- ForeColorBack (define a cor que fica por baixo – sombra)
É necessário então criar uma nova classe e utilizar o seguinte código:
Imports System.Drawing
Imports System.ComponentModel
Public Class ShadowLabel
Inherits Label
#Region "Properties"
Private m_offsetX As Integer
Private m_offsetY As Integer
Private m_ForeColorFront As Color
''' <summary>
''' Definição do offset em X
''' </summary>
<DefaultValue(0)> _
<Category("Shadow")> _
<Description("Definição do offset em X")> _
Public Property OffsetX() As Integer
Get
Return m_offsetX
End Get
Set(ByVal value As Integer)
m_offsetX = value
Me.Invalidate()
End Set
End Property
''' <summary>
''' Definição do offset em Y
''' </summary>
<DefaultValue(-1)> _
<Category("Shadow")> _
<Description("Definição do offset em Y")> _
Public Property OffsetY() As Integer
Get
Return m_offsetY
End Get
Set(ByVal value As Integer)
m_offsetY = value
Me.Invalidate()
End Set
End Property
''' <summary>
''' Definição da cor da frente
''' </summary>
<DefaultValue(GetType(Color), "RoyalBlue")> _
<Category("Shadow")> _
<Description("Definição da cor da frente")> _
Public Property ForeColorFront() As Color
Get
Return m_ForeColorFront
End Get
Set(ByVal value As Color)
m_ForeColorFront = value
Me.Invalidate()
End Set
End Property
''' <summary>
''' Definição da cor de sombreado
''' </summary>
<DefaultValue(GetType(Color), "White")> _
<Category("Shadow")> _
<Description("Definição da cor de sombreado")> _
Public Property ForeColorBack() As Color
Get
Return Me.ForeColor
End Get
Set(ByVal value As Color)
Me.ForeColor = value
Me.Invalidate()
End Set
End Property
' Serve apenas para definir que a propriedade ForeColor
' não está disponível para alterar no editor e no design
<Browsable(False), EditorBrowsable(EditorBrowsableState.Never)> _
Public Overrides Property ForeColor() As System.Drawing.Color
Get
Return MyBase.ForeColor
End Get
Set(ByVal value As System.Drawing.Color)
MyBase.ForeColor = value
End Set
End Property
#End Region
' Define algumas propriedades por defeito
Public Sub New()
' Definição dos valores iniciais de offset
Me.OffsetX = 0
Me.OffsetY = -1
' Definição das cores iniciais do texto
Me.ForeColorFront = Color.RoyalBlue
Me.ForeColorBack = Color.White
End Sub
' No evento Paint desenha o texto
Protected Overrides Sub OnPaint(ByVal e As System.Windows.Forms.PaintEventArgs)
MyBase.OnPaint(e)
' Desenha o texto que fica na frente
Dim BackBrush As New SolidBrush(Me.ForeColorFront)
e.Graphics.DrawString(Me.Text, Me.Font, BackBrush, OffsetX, OffsetY, StringFormat.GenericDefault)
BackBrush.Dispose()
End Sub
End Class
No final é preciso compilar a aplicação e o controlo estará disponível na toolbar.
Este é um exemplo que pretende mostrar como criar uma label com uma sombra, mas também como utilizar algumas funcionalidades do namespace Drawing.
PS: Como sempre, qualquer dúvida, comentário ou correcção ao artigo é sempre bem vinda!
A segurança de dados é algo fundamental em qualquer aplicação e cada vez mais é um motivo de preocupação. Quando se guarda determinado tipo de informação, numa base de dados por exemplo, é importante que a mesma esteja segura, principalmente em alguns campos como é o caso de passwords, números de cartões de crédito, informações confidenciais, etc.
É aí que a criptografia entra, através da encriptação ou codificação de dados. A encriptação é a transformação de informação electrónica de texto legível em texto incompreensível, através de um cifra, também conhecido por algoritmo.
Este processo é bastante complexo mas a .Net Framework através da Namespace System.Security.Cryptography simplifica bastante, tornando-o acessível e fácil de utilizar. Existem diversas classes disponíveis que implementam diferentes tipos de encriptação, como é o caso de: AES (Advanced Encryption Standard), DES (Data Encryption Standard), RC2 (Rivest Cipher), Rijndael, TripleDES (Triple Data Encryption Standard), entre outras.
De entre todos os métodos de encriptação disponíveis, alguns são mais seguros do que outros, como é o caso do Rijndael ou do AES. No entanto e para este exemplo, será mostrado a utilização do TripleDES, por ser bastante simples de implementar.
Como curiosidade o TripleDES baseia-se no algoritmo DES que foi utilizado pelo governo norte-americano e que, actualmente, pode ser decifrado. Posteriormente foi desenvolvida uma versão melhorada onde o algoritmo corre três vezes com duas chaves simétricas: o TripleDES.
Para a implementação de uma encriptação utilizando o algoritmo TripleDES devemos criar a seguinte classe:
Imports System.Text
Imports System.Security.Cryptography
''' <summary>
''' Encriptação simples usando TripleDES
''' (Triple Data Encryption Standard)
''' </summary>
Public Class Crypto
Private Shared TripleDES As New TripleDESCryptoServiceProvider
Private Shared MD5 As New MD5CryptoServiceProvider
' Definição da chave de encriptação/desencriptação
Private Const key As String = "CHAVE12345teste"
''' <summary>
''' Calcula o MD5 Hash
''' </summary>
''' <param name="value">Chave</param>
Public Shared Function MD5Hash(ByVal value As String) As Byte()
' Converte a chave para um array de bytes
Dim byteArray() As Byte = ASCIIEncoding.ASCII.GetBytes(value)
Return MD5.ComputeHash(byteArray)
End Function
''' <summary>
''' Encripta uma string com base em uma chave
''' </summary>
''' <param name="stringToEncrypt">String a encriptar</param>
Public Shared Function Encrypt(ByVal stringToEncrypt As String) As String
Try
' Definição da chave e da cifra (que neste caso é Electronic
' Codebook, ou seja, encriptação individual para cada bloco)
TripleDES.Key = Crypto.MD5Hash(key)
TripleDES.Mode = CipherMode.ECB
' Converte a string para bytes e encripta
Dim Buffer As Byte() = ASCIIEncoding.ASCII.GetBytes(stringToEncrypt)
Return Convert.ToBase64String(TripleDES.CreateEncryptor().TransformFinalBlock(Buffer, 0, Buffer.Length))
Catch ex As Exception
MessageBox.Show(ex.Message, My.Application.Info.Title, MessageBoxButtons.OK, MessageBoxIcon.Error)
Return String.Empty
End Try
End Function
''' <summary>
''' Desencripta uma string com base em uma chave
''' </summary>
''' <param name="encryptedString">String a decriptar</param>
Public Shared Function Decrypt(ByVal encryptedString As String) As String
Try
' Definição da chave e da cifra
TripleDES.Key = Crypto.MD5Hash(key)
TripleDES.Mode = CipherMode.ECB
' Converte a string encriptada para bytes e decripta
Dim Buffer As Byte() = Convert.FromBase64String(encryptedString)
Return ASCIIEncoding.ASCII.GetString(TripleDES.CreateDecryptor().TransformFinalBlock(Buffer, 0, Buffer.Length))
Catch ex As Exception
MessageBox.Show(ex.Message, My.Application.Info.Title, MessageBoxButtons.OK, MessageBoxIcon.Error)
Return String.Empty
End Try
End Function
End Class
Depois, para a implementar na aplicação, é só necessário
Dim source As String = "vbtuga"
' Mostra o texto original
Debug.WriteLine("Texto original : " & source)
' Encripta a string
Dim result As String = Crypto.Encrypt(source)
' Mostra o resultado da encriptação
Debug.WriteLine("Texto encriptado: " & result)
' Decripta e mostra o texto original
Debug.WriteLine("Texto decriptado: " & Crypto.Decrypt(result))
Neste pequeno teste, o resultado é o seguinte (na Immediate Window):
Texto original : vbtuga
Texto encriptado: 6ldtC7GfpGg=
Texto decriptado: vbtuga
Este artigo é um exemplo de encriptação de forma a tornar os dados e as aplicações mais seguras. Brevemente, assim que possível, irei mostra mais dois exemplos de encryptação em AES e Rijndael.
Exemplo do artigo: DOWNLOAD DO FICHEIRO
PS: Como sempre, qualquer dúvida, comentário ou correcção ao artigo é sempre bem vinda!