Visual Basic em Português

Página pessoal de Jorge Paulino sobre o Visual Basic (VB.NET, ASP.NET, VB6, VBA) e algumas noticias de tecnologia

VB.NET: Actualizações Automáticas da Aplicação

As actualizações nos programas são frequentes e obrigam muitas as vezes a um trabalho moroso na actualização dos clientes finais (os utilizadores). Este processo pode e deve ser automatizado efectuando uma actualização directa de um servidor ou via Internet.

Um dos métodos aconselhados para fazer a distribuição e actualização das aplicações é o ClickOnce da Microsoft (mais informações em ClickOnce Deployment).

No entanto muitos programadores preferem não utilizar o ClickOnce por diversos motivos, com por exemplo, apenas permite fazer a actualização do executável, não permite indicar o local de instalação, não cria automaticamente os atalhos, etc.

Mas é possível criar o nosso próprio sistema de actualização da aplicação apenas com um ficheiro. É verdade que não é possível apagar um ficheiro quando este está a ser utilizado mas é possível renomeá-lo. Assim o sistema é simples:
1 - Verificar se existem actualizações
2 - Descarregar o ficheiro de actualização
3 - Renomear o executável para um nome diferente
4 - Renomear o ficheiro de actualização para o nome do executável
5 - Reiniciar a aplicação

É claro que são necessárias mais algumas validações pelo meio mas isto é o essencial!

É possível ler a versão directamente no ficheiro mas se o mesmo for grande então existe um grande tempo de espera para a verificação. Daí a utilizações de um ficheiro de actualização auxiliar (formato txt pela sua simplicidade).

Estrutura do ficheiro txt:
Linha 1 - Versão do ficheiro de actualização
Linha 2 - Ficheiro de actualização com a extensão .update
Linha 3 e restantes - Ficheiros a actualizar

Exemplo:
1.1.0.0
ftp://74.82.141.111/private/exemplo.exe.update
ftp://74.82.141.111/private/exemplo.dll
ftp://74.82.141.111/private/exemplo.xml

Vamos agora ver o código:

Imports System.IO
Imports System.Net

' ------------------------------------------------------
' Informação a alterar
' ------------------------------------------------------
Private updateServer As String = "74.82.141.111"
Private updateFileName As String = "ftp://74.82.141.111/private/demo_update.txt"
Private updateUserName As String = "username"
Private updatePassword As String = "password"
Private msgboxTitle As String = "Actualização da Aplicação"
Private connTimeout As Integer = 8000
' ------------------------------------------------------

' Constantes
Private Const delExtension As String = ".delete"
Private Const uptExtension As String = ".update"

' Variáveis
Private MyWebClient As New WebClient
Private txtInfo As String
Private txtInfoArray() As String
Private appFullName As String
Private appDirectory As String
Private appName As String

''' <summary>
''' Formatação da versão do ficheiro
''' </summary>
''' <param name="Version">
String com a versão a formatar</param>
Private Function GetVersion(ByVal Version As String) As String
    Dim x() As String = Split(Version, ".")
    Return String.Format("{0:00000}{1:00000}{2:00000}{3:00000}", Int(x(0)), Int(x(1)), Int(x(2)), Int(x(3)))
End Function

''' <summary>
'''
Apaga ficheiros antigos (caso existam)
''' </summary>
''' <param name="FileName">
Nome do ficheiro</param>
Private Sub DeleteFile(ByVal FileName As String)
    Try

        Dim sFile As String = Dir(FileName)
        Do While sFile <> ""
            Try
                File.Delete(sFile)
            Catch ex As Exception
            End Try
            sFile = Dir()
        Loop

        Catch ex As Exception
            ' ignora o erro
    End Try
End Sub


''' <summary>
''' Inicia a verificação/update do ficheiro caso esteja disponível
''' </summary>
Public Sub CheckUpdate()

    ' Informação da aplicação
    appFullName = Application.ExecutablePath.ToString
    appDirectory = Application.StartupPath.ToString + "\"
    appName = Application.ProductName.ToString

    ' Elimina os ficheiros antigos
    Call DeleteFile(appFullName + delExtension)

    ' Apaga updates antigos
    Call DeleteFile(appFullName + uptExtension)

    Try

       ' Verifica a existência do servidor onde está o ficheiro txt
        If Not My.Computer.Network.Ping(updateServer) Then Exit Sub

     ' Descarrega o ficheiro TXT para uma variável
       Dim networkCredentials As New Net.NetworkCredential()
        With networkCredentials
          .UserName = updateUserName
          .Password = updatePassword
       End With
      MyWebClient.Credentials = networkCredentials
       txtInfo = MyWebClient.DownloadString(updateFileName.ToString)

      ' Separa a variável em linhas
      txtInfoArray = txtInfo.Split(vbNewLine)

     ' Verifica a versão do ficheiros (original e update)
      Dim fInfo As FileVersionInfo = FileVersionInfo.GetVersionInfo(appFullName)
     Dim appVersion As String = GetVersion(fInfo.FileMajorPart + "." + fInfo.FileMinorPart + "." + fInfo.FileBuildPart + "." + fInfo.FilePrivatePart)
      Dim UpdateVersion As String = GetVersion(txtInfoArray(0))

     ' Verifica se é necessário fazer a actualização
      Dim UpgradeRequired As Boolean = UpdateVersion > appVersion

     ' Caso seja necessário actualizar
     If UpgradeRequired Then

         ' Confirma a intenção de actualizara aplicação
          Dim msgStart As String = "Existe uma nova actualização do programa." + vbCrLf + vbCrLf + "Deseja efectuar a actualização agora ?"
         Dim resultStart As DialogResult = MessageBox.Show(msgStart, msgboxTitle, MessageBoxButtons.YesNo, MessageBoxIcon.Exclamation)
         If resultStart <> Forms.DialogResult.Yes Then
             Exit Sub
         End If


          Application.DoEvents()

          ' Descarrega o ficheiro principal
          Dim updateName As String = txtInfoArray(1).Substring(txtInfoArray(1).LastIndexOf("/") + 1)
          My.Computer.Network.DownloadFile(txtInfoArray(1).ToString, appDirectory + updateName, _
              updateUserName, updatePassword, False, connTimeout, True)

          ' Caso existam mais ficheiros
          If txtInfoArray.Length - 1 >= 2 Then

               ' Descarrega o(s) ficheiro(s) que estão na lista
               For x As Byte = 2 To txtInfoArray.Length - 1
       
                  Try
                      ' Caso a linha não esteja em branco
                      If Not String.IsNullOrEmpty(txtInfoArray(x).Trim) Then

                          ' Nome e localização dos ficheiro
                          Dim updateFile As String = txtInfoArray(x).Trim
                          Dim updateFiles As String = txtInfoArray(x).Substring(txtInfoArray(x).LastIndexOf("/") + 1)

                         ' Inicia o Download do ficheiro
                          My.Computer.Network.DownloadFile(updateFile, appDirectory + updateFiles, _
                                               updateUserName, updatePassword, False, connTimeout, True)

                    End If
                Catch
ex As Exception
                    ' Ignora os erro ...
                End Try
            Next

       End If

        ' Verifica se está disponível o novo ficheiro
        If File.Exists(appDirectory + updateName) Then

            ' Renomeia o principal e depois o ficheiro a actualizar
            With My.Computer.FileSystem
                .RenameFile(appFullName, appName + ".exe" + delExtension)
                .RenameFile(appDirectory + updateName, appName + ".exe")
            End With

            ' Mensagem final de actualização
            Dim msgFinish As String = "Terminou a actualização da aplicação." + vbCrLf + vbCrLf + "Deseja reiniciar o programa agora ?"
            Dim resultFinish As DialogResult = MessageBox.Show(msgFinish, msgboxTitle, MessageBoxButtons.YesNo, MessageBoxIcon.Information)
            If resultFinish = MsgBoxResult.Yes Then
                Application.DoEvents()
                Application.Restart()
            End If

        End If

     End If

    Catch
ex As Exception
        MessageBox.Show("Ocorreu um erro na actualização do ficheiro. Mensagem original: " + ex.Message, msgboxTitle, MessageBoxButtons.OK, MessageBoxIcon.Error)
    End Try
End Sub



PS: Como sempre, qualquer dúvida, comentário ou correcção ao artigo é sempre bem vinda!

SQL: Meses abreviados usando UDF's

Das operações efectuadas na aplicação o acesso a dados numa base de dados é normalmente uma das operações mais demoradas. Daí que a manipulação da informação é bastante importante de modo a reduzir ao máximo o tempo de resposta. As operações efectuadas no servidor são em regra mais rápidas e a correcta definição das tabelas e vistas é bastante importante. Outro dos pontos importantes quando se trabalha com um servidor é o espaço que cada tabela ocupa. Devem ser utilizados os mínimos de recursos de modo a que a nossa base de dados não aumente/ocupe o espaço ocupado desnecessariamente. Assim sendo é normal utilizar números ao invés de texto por estes ocuparem mesmos espaço.

O seguinte exemplo mostra como utilizar funções no servidor de modo a preparar uma vista para utilizar no VB. O objectivo é substituir os números dos meses (1 a 12) pela descrição abreviada. Esta operação pode ser efectuada usando UDF's (user defined function) que são adicionadas no SQL server.

Para adicionarmos uma nova UDF só temos de clicar com o botão direito sobre a pasta Functions e seleccionar Add New - Inline Function. De seguida adicionamos a seguinte função:

ALTER FUNCTION dbo.strMonth(@MonthNumber int)
RETURNS varchar(3)
AS
BEGIN
     /* Declaração da variável */
     DECLARE @myMonth varchar(3)
     Set @myMonth = ''

     /* Verificação da qual é o resultado */
     Select @myMonth = CASE
          WHEN @MonthNumber = 1 THEN 'Jan'
          WHEN @MonthNumber = 2 THEN 'Fev'
          WHEN @MonthNumber = 3 THEN 'Mar'
          WHEN @MonthNumber = 4 THEN 'Abr'
          WHEN @MonthNumber = 5 THEN 'Mai'
          WHEN @MonthNumber = 6 THEN 'Jun'
          WHEN @MonthNumber = 7 THEN 'Jul'
          WHEN @MonthNumber = 8 THEN 'Ago'
          WHEN @MonthNumber = 9 THEN 'Set'
          WHEN @MonthNumber = 10 THEN 'Out'
          WHEN @MonthNumber = 11 THEN 'Nov'
          WHEN @MonthNumber = 12 THEN 'Dez'
          ELSE '' END

     /* Retorna o resultado */
     RETURN @myMonth
END

Para a utilizar na nossa view (no servidor) é apenas necessário:

     SELECT id, mes, strMonth(mes) AS MesAbreviado FROM Tabela

Este é um pequeno exemplo de utilização de UDF's. Estas funções simplificam bastante o trabalho do programador uma vez que são feitas no próprio servidor e não no código da aplicação. Para alterar as letra para maiúsculas, por exemplo, era apenas necessário alterar esta pequena função sem que seja necessário alterar o código.


PS: Como sempre, qualquer dúvida, comentário ou correcção ao artigo é sempre bem vinda!

VB.NET: Validar e-mails usando o Regex

Quando criamos fichas pessoais ou empresariais, o e-mail é hoje em dia, um campo obrigatório. No entanto existem formas simples de validar todos os campos, quer sejam eles numéricos, datas, números, etc, mas para o e-mail não existe nada específico.

Uma das formas de validar o e-mail é recorrer às expressões regulares de modo a verificar se a string inserida cumpre os requisitos necessários de um e-mail. É claro que existem outras formas de o fazer!

As expressões regulares ou regular expressions (regex) são mascaras especiais que validam num texto uma ou mais condições. Por exemplo todos conhecemos a expressão *.exe que nos indica todos os ficheiros com a extensão EXE (executáveis). Existem diversas máscaras para diversos objectivos e para quem não conhece e que saber mais sobre o regex pode-se ler mais em Regular Expression Library ou Regular-Expressions Info

Para a validação do e-mail vamos usar a seguinte função:

Imports System.Text.RegularExpressions
''' <summary>
''' Verifica se o e-mail é válido
''' </summary>
''' <param name="emailAddress">Endereço de e-mail</param>

Function EmailAddressCheck(ByVal emailAddress As String) As Boolean

    ' Pattern ou mascara de verificação
    Dim pattern As String = "^[a-zA-Z][\w\.-]*[a-zA-Z0-9]@[a-zA-Z0-9][\w\.-]*[a-zA-Z0-9]\.[a-zA-Z][a-zA-Z\.]*[a-zA-Z]$"

    ' Verifica se o email corresponde a pattern/mascara
    Dim emailAddressMatch As Match = Regex.Match(emailAddress, pattern)

    ' Caso corresponda
    If emailAddressMatch.Success Then
        Return True
    Else
        Return False
    End If

End Function



' Botão que irá verificar se o e-mail inserido é válido
Private Sub btnCheck_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles btnCheck.Click
    Debug.Print(EmailAddressCheck("omeu.email@servidor.com"))
End Sub


PS: Como sempre, qualquer dúvida, comentário ou correcção ao artigo é sempre bem vinda!

Excel: Formatação Condicional Expandida

A formatação condicional permite-nos formatar uma ou mais células de acordo com um critério predefinido. Uma das limitações do Microsoft Excel é que a formatação condicional permite-nos apenas utilizar 3 condições e muitas vezes existe a necessidade de criar diversas formatações de acordo com diversos critérios.

No entanto é possível, com recurso ao VBA, criar a nossa própria formatação condicional aumentando o número de critérios de 3 para os que necessitarmos (sem limite definido).

Para efectuar esta formatação condicional deve-se fazer o seguinte:

1 - Seleccionar o menu Tools - Macro - Visual Basic Editor ou carregar em ALT+F11.

2 - No Editor, mais precisamente na janela de projecto, podemos seleccionar uma das Worksheets para que o código apenas funcione nela ou ThisWorkbook para que funcione em todas. Neste exemplo vamos seleccionar apenas uma Worksheet (Sheet1)
3 - Colocar o seguinte código no editor de código:


' Procedimento executado quando existe alguma alteração no valor da célula
Private Sub Worksheet_Change(ByVal Target As Range)

    ' Desabilita outros eventos para tornar mais rápido
    Application.EnableEvents = False

    ' Verifica se a célula está dentro da área escolhida
    If Not Intersect(Target, Me.[C2:C65536]) Is Nothing Then

        ' Verifica qual o valor e aplica uma formatação
        Select Case Target.Value
            Case 1
                Target.Interior.Color = vbRed
            Case 2
                Target.Interior.Color = vbYellow
            Case 3
                Target.Interior.Color = vbGreen
            Case 4
                Target.Interior.Color = vbBlue
            Case 5 To 10
                Target.Interior.Color = vbBlack
                Target.Font.Color = vbWhite
            Case "OK"
                Target.Interior.Color = vbMagenta
                Target.Font.Color = vbYellow
                Target.Font.Bold = True
            Case Else
                Target.Interior.Color = xlNone
                Target.Font.Color = vbBlack
                Target.Font.Bold = False
        End Select

    End If

    ' Reabilita os eventos
    Application.EnableEvents = True

End Sub


Neste exemplo vamos colocar algumas cores de fundo, mudar a cor de texto e estilo de texto para bolt (negrito) de acordo com diferentes critérios na coluna C.


PS: Como sempre, qualquer dúvida, comentário ou correcção ao artigo é sempre bem vinda!




Microsoft Office Especialist

Membro da Comunidade
Experts-Exchange


Administ. da Comunidade
Portugal-a-Programar



Twitter

Artigos no CodeProject

Artigos no CodeProject

Subscrever Novidades

Endereço de Email:

Delivered by FeedBurner

Seguidores

Histórico