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!
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!
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!
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!














