ADSENSE
ADSENSE
quinta-feira, 23 de fevereiro de 2012
Atualizações de sistemas
A atualização de aplicativos sempre causa um pouco de dor de cabeça especialmente se você possui um parque grande de clientes instalados.
O quanto mais fácil seria este processo se ao invés de ir máquina a máquina trocando os arquivos você pudesse disponibilizar os arquivos em uma pasta compartilhada e ao abrir sua aplicação ela automaticamente se atualizasse.
Passo 0 – Sempre antes de realizar qualquer alteração em suas aplicações crie uma cópia de backup para sua própria segurança.
Passo 1 – Abra sua aplicação e no menu “Project>>Options” abra as opções do seu projeto. Na aba “Version Info” habilite as opções “include version information in project” e “Auto-increment buid number”.
Ao habilitar estas duas opções sua aplicação passará a ser versionada e número será automaticamente incrementado toda vez que você fizer um novo build no seu projeto. Estas opções serão úteis mais adiante no nosso projeto.
Passo 2 – Vamos incluir duas functions a sua aplicação:
//Retorna o build de um arquivo
function GetBuildInfo(prog: String): String;
var
VerInfoSize: DWORD;
VerInfo: Pointer;
VerValueSize: DWORD;
VerValue: PVSFixedFileInfo;
Dummy: DWORD;
V1, V2, V3, V4: Word;
begin
VerInfoSize := GetFileVersionInfoSize(PChar(prog),Dummy);
GetMem(VerInfo,VerInfoSize);
GetFileVersionInfo(PChar(prog),0,VerInfoSize,VerInfo);
VerQueryValue(VerInfo,'',Pointer(VerValue),VerValueSize);
with VerValue^ do begin
V1 := dwFileVersionMS shr 16;
V2 := dwFileVersionMS and $FFFF;
V3 := dwFileVersionLS shr 16;
V4 := dwFileVersionLS and $FFFF;
end;
FreeMem(VerInfo,VerInfoSize);
result := Copy(IntToStr(100 + v1),3,2) + '.' + Copy(IntToStr(100 + V2),3,2) + '.' + Copy(IntToStr(100 + V3),3,2) + '.' + Copy(IntToStr(100 + V4),3,2);
end;
//Retorna o tamanho de um arquivo em bytes
function DSiFileSize(const fileName: string): int64;
var
fHandle: DWORD;
begin
fHandle := CreateFile(PChar(fileName), 0, 0, nil, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, 0);
if fHandle = INVALID_HANDLE_VALUE then
Result := -1
else try
Int64Rec(Result).Lo := GetFileSize(fHandle, @Int64Rec(Result).Hi);
finally
CloseHandle(fHandle);
end;
end;
Passo 3 – Vamos declarar em uses ShellAPI
Passo 4 – Vamos precisar armazenar o local onde o arquivo atualizado estará disponível. Neste exemplo estaremos salvando a informação em um arquivo de configuração (arquivo ini). Mas você pode salvar esta informação no registro do Windows ou onde achar mais apropriado.
Passo 5 – Agora vamos criar a procedure que vai realmente atualizar a aplicação:
procedure Atualiza_Versao_Aplicacao;
var
versao_local, versao_servidor : string;
tamanho_original, tamanho_recebido : integer;
local_arquivo_servidor : string;
iArq : Tinifile;
begin
//Verifico onde esta armazenado o arquivo a ser atualizado
if FileExists(GetCurrentDir + '\CONFIG.INI') then begin
try
iArq := TInifile.Create(GetCurrentDir + '\CONFIG.INI');
local_arquivo_servidor := iArq.ReadString('UPDATE','LOCAL','\\SERVIDOR\PASTA\ARQUIVO.EXE');
finally
iArq.Free;
end;
end;
//Armazeno a versão da aplicação atualmente em uso
versao_local := GetBuildInfo(GetCurrentDir + '\ARQUIVO.EXE');
//Armazeno a versão do aplicação que esta disponivel no servidor
versao_servidor := GetBuildInfo(local_arquivo_servidor);
//Comparo as versões
if versao_local <> versao_servidor then begin
//Guardo na váriavel o tamanho do arquivo que esta no servidor
tamanho_original := DSiFileSize(local_arquivo_servidor);
//Copio a versão que esta no servidor para o computador atual
CopyFile(PChar(local_arquivo_servidor),PChar(GetCurrentDir+'\ARQUIVO.NEW'),False);
//Guardo na váriavel o tamanho do arquivo copiado
tamanho_recebido := DSiFileSize(GetCurrentDir+'\ARQUIVO.NEW');
//Verifico se o arquivo copiado chegou intacto
if tamanho_original = tamanho_recebido then begin
//Apago se existir versão antiga
DeleteFile('ARQUIVO.OLD');
//Renomeio o arquivo atual
RenameFile('ARQUIVO.EXE', 'ARQUIVO.OLD');
//Renomeio o arquivo novo para poder usa-lo
RenameFile('ARQUIVO.NEW', 'ARQUIVO.EXE');
//Informo que a aplicação foi atualizado com sucesso
ShowMessage('Aplicação atualizada com sucesso!');
//Mando abrir a nova versão do teclado
ShellExecute(0,Nil,PChar(GetCurrentDir+'\ARQUIVO.EXE'),'', Nil, SW_SHOWNORMAL);
//Fecho a aberta
Close;
end else begin
//Caso o arquivo copiado não seja copiado com sucesso
ShowMessage('Copia de arquivo falhou! Tente novamente!');
end;
end else begin
//Se a aplicação já estiver atualizada
ShowMessage('Aplicativo já possui a ultima atualização disponível!');
end;
end;
Passo 6 – Você pode chamar a procedure de atualização no onClick de um Botão, criar uma tecla de atalho, adiciona-la no activate do form. Na maneira que lhe for mais conveniente.
Passo 7 – Lembre-se de que o usuário que estiver logado no computador na hora em que for ser atualizada a aplicação deve ter permissões administrativas na pasta onde a aplicação esta instalada e que também ter permissões de acesso a pasta onde a nova versão foi armazenada.
Com esta rotina você pode atualizar não só o executável da sua aplicação, mas todos os arquivos que precisar. Basta usar sua imaginação.
Assinar:
Postar comentários (Atom)
olá!
ResponderExcluirtestei a função e não consegui atualizar não!
ele não compila, da erro depois do shellexecute
na parte //fecho a aberta
close;
pra compilar eu alterei para apllication.termined ai foi de boa..
utilizo o delphi 2010 e estou executando no formshow da tela de splash, o q estou fazendo de errado?
obrigado abraços
diego
diegosaopaulino@hotmail.com
Desculpe pela demora Diego.
ExcluirMas esta função foi escrita em Delphi 7 vou testar no Delphi 2010 e corrigir o erro dela.Ai eu posto a versão corrigida.
Eu consigo renomear o arquivo enquanto ele está sendo executado!? Estranho isso...
ResponderExcluir