Olá pessoal! Este artigo tem o intuito de mostrar como realizar a rotina de backup de bancos de dados Firebird, utilizando o gbak, que é conhecidamente a melhor ferramenta de backup, apesar de ser através de linha de comando.
Vocês já devem estar calejados de rotinas e mais rotinas na internet com o mesmo tópico, mas a forma como eu irei mostrar não irá fazer uso de nenhum componente “pronto” ou fórmulas milagrosas.
A inspiração para este artigo surgiu com o artigo de rotina de Backup com o MySQL publicado aqui no site, que utilizava a ferramenta nativa do referido banco, mas usando um arquivo BAT e o WinExec, que no meu entender, torna o processo meio obscuro, já que não sabemos o que esta por trás do processo.
Bom, chega de rodeios e vamos à rotina.
Primeiro, inicie um novo projeto, salve o form como frmBackup e a unit como untBackup e o projeto como Backup.
Na propriedade Caption do form escreva assim: Rotina de Realização de Backup
No form, coloque dois Edits e dois Labels, presentes na aba Standard, ou utilize o componente LabeledEdit, presente na aba Additional (existente no Delphi 7 pra frente); No nosso artigo, estamos usando o Delphi 7, portanto utilizamos dois LabelEdits.
No primeiro, mude o Name dele para edtOrigem, e o segundo como edtDestino.
Quem estiver usando Label, mude o caption do primeiro label para “Informe o caminho de origem”, e o segundo para “Informe o caminho de destino”, e para quem estiver usando LabelEdit altere o Caption da mesma forma que com o uso de Label.
Coloque dois componentes SpeedButon, mude o nome do primeiro para btnOrigem e o segundo para btnDestino. Coloque o btnOrigem na margem direita do edtOrigem, e o btnDestino na margem direita do edtDestino.
Coloque um componente OpenDialog e um SaveDialog presentes na aba Dialogs. No opendialog, mude o name para odOrigem, e no savedialog mude o name para sdDestino.
Coloque um componente Memo e mude o name dele para mmResult.
Coloque um componente BitBtn e mude o name dele para btnInicia. Mude o caption do botão para Inicia.
Adequei o tamanho do form para que ele fique igual a imagem abaixo:

Figura 1 - Layout do formulário
Clique sobre o componente odOrigem, clique na propriedade Filter, depois clique no botão para abrir as opções de filtro, como mostrado na figura abaixo:

Figura 2 - Opções de Filtro do OpenDialog
No campo FilterName coloque assim (*.fdb) e na mesma linha, em filter, coloque assim *.fdb
Faça a mesma operação no componente sdDestino, mas coloque (*.gbk) e *.gbk nos campos FilterName e filter.
No evento OnClick do botão edOrigem, coloque o código abaixo:
odOrigem.Execute;
edtOrigem.Text := odOrigem.FileName;
Esse código irá abrir a janela para que seja escolhido o arquivo de origem, e irá jogar o caminho do arquivo para o edOrigem.
Agora no evento OnClick do botão edDestino, coloque o seguinte código:
sdDestino.Execute;
edtDestino.Text := sdDestino.FileName;
Esse código alimenta o edtDestino com o nome do arquivo de destino, que será um .gbk
Para que possamos “ver” o progresso do processo de backup exatamente como ocorre no IBExpert, iremos utilizar uma rotina que eu encontrei na internet que é responsável pela mágica de recuperar o que está em execução no DOS. No “Private” do form, declare a seguinte função:
function GetDosOutput(const CommandLine, work: string): string;
O corpo da função esta descrito abaixo:
function TfrmBackup.GetDosOutput(const CommandLine, work: string): string;
var
SA: TSecurityAttributes;
SI: TStartupInfo;
PI: TProcessInformation;
StdOutPipeRead, StdOutPipeWrite: THandle;
WasOK: Boolean;
Buffer: array[0..255] of Char;
BytesRead: Cardinal;
WorkDir, Line, l: string;
begin
mmResult.Lines.Clear;
Application.ProcessMessages;
with SA do
begin
nLength := SizeOf(SA);
bInheritHandle := True;
lpSecurityDescriptor := nil;
end;
//create pipe for standard output redirection
CreatePipe(StdOutPipeRead, // read handle
StdOutPipeWrite, // write handle
@SA, // security attributes
0); //, // number of bytes reserved for pipe - 0 default
//);
try
// Make child process use StdOutPipeWrite as standard out,
// and make sure it does not show on screen.
with SI do
begin
FillChar(SI, SizeOf(SI), 0);
cb := SizeOf(SI);
dwFlags := STARTF_USESHOWWINDOW or STARTF_USESTDHANDLES;
wShowWindow := SW_HIDE;
hStdInput := GetStdHandle(STD_INPUT_HANDLE); // don't redirect std input
hStdOutput := StdOutPipeWrite;
hStdError := StdOutPipeWrite;
end;
// launch the command line compiler
WorkDir := work; //ExtractFilePath(CommandLine);
// showmessage(workdir);
WasOK := CreateProcess(nil, PChar(CommandLine), nil, nil, True, 0, nil,
PChar(WorkDir), SI, PI);
// Now that the handle has been inherited, close write to be safe.
// We don't want to read or write to it accidentally.
CloseHandle(StdOutPipeWrite);
// if process could be created then handle its output
if not WasOK then
raise Exception.Create('Could not execute command line!')
else
try
// get all output until dos app finishes
{panel2.caption := 'Aguarde...';
Panel2.Update;}
if not Showing then
show;
Line := '';
repeat
// read block of characters (might contain carriage returns and line feeds)
WasOK := ReadFile(StdOutPipeRead, Buffer, 255, BytesRead, nil);
// has anything been read?
if BytesRead > 0 then
begin
// finish buffer to PChar
Buffer[BytesRead] := #0;
// combine the buffer with the rest of the last run
Line := Line + Buffer;
mmResult.text := mmResult.text + buffer;
mmResult.SelStart := length(mmResult.Text);
mmResult.SelLength := 1;
end;
until not WasOK or (BytesRead = 0);
// wait for console app to finish (should be already at this point)
WaitForSingleObject(PI.hProcess, INFINITE);
finally
// Close all remaining handles
CloseHandle(PI.hThread);
CloseHandle(PI.hProcess);
{panel2.caption := 'Backup Terminado!';}
end;
finally
result := Line;
CloseHandle(StdOutPipeRead);
end;
end;
No evento onClick do botão Inicia, declare uma variável do tipo String, chamada LC, e coloque o seguinte código:
lc := 'gbak -g -b -v -t ' + edOrigem.text + ' ' + edDestino.text +
' -user SYSDBA -password masterkey';
GetDosOutput(lc, ExtractFilePath(Application.ExeName));
MessageDlg('Processo de backup efetuado com sucesso', mtInformation, [mbOk], 0);
Antes de ver o resultado, há a necessidade de se copiar o arquivo GBAK.EXE para dentro da pasta de destino no executável. Esse arquivo está dentro da pasta BIN da instalação do firebird. A pasta padrão do firebird é C:\arquivos de programas\firebird\firebird_X_X\bin.
Também é necessário na seção Uses do form, declarar a unit ShellApi.
Salve, compile e execute o código, lembrando que deverá ser escolhido o arquivo de origem e o de destino para que a função funcione corretamente.
Algumas considerações
- Existem partes de código comentadas na rotina de execução do comando em DOS. Essa rotina eu tirei do meu fonte, e depois do processo de backup eu compacto e salvo o arquivo compactado para dentro de uma pasta de destino, que pode ser qualquer unidade da máquina ou mesmo um pen drive.
- Quem tiver algum problema com a rotina ou quiser mais informações a respeito pode entrar em contato comigo por e-mail.
Abraço a todos!
Por: Osmar (Ghost_Rider)
Contato: osmar.mfe@hotmail.com
|