Clique para saber mais...
  Home     Download     Produtos / Cursos     Revista     Vídeo Aulas     Fórum     Contato   Clique aqui para logar | 07 de Setembro de 2026
  Login

Codinome
Senha
Salvar informações

 Esqueci minha senha
 Novo Cadastro

  Usuários
96 Usuários Online

  Revista ActiveDelphi
 Assine Já!
 Edições
 Sobre a Revista

  Conteúdo
 Apostilas
 Artigos
 Componentes
 Dicas
 News
 Programas / Exemplos
 Vídeo Aulas

  Serviços
 Active News
 Fórum
 Produtos / Cursos

  Outros
 Colunistas
 Contato
 Top 10

  Publicidade

  [Artigos]  Backup com Firebird e Delphi
Publicado por ActiveDelphi : Segunda, Setembro 14, 2009 - 09:51 GMT-3 (2471 leituras)
Comentários 12 Comentários   Enviar esta notícia a um amigo Enviar para um amigo   Versão para Impressão Versão para impressão
Administrador 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



Comentários Comentários
   Ordem:  
Comentários pertencem aos seus respectivos autores. Não somos responsáveis pelo seus conteúdos.


por: durama (gajsnet@gmail.com) : Set 15, 2009 - 12:18
(Informações sobre o membro | Enviar uma mensagem)
Gostaria de saber se essa rotina salva o conteúdo de campos blob, pois por algum motivo já vi várias rotinas que não salvam o conteúdo de campos blob.


por: EdsonSSantos (essantos@bol.com.br) : Set 15, 2009 - 04:30
(Informações sobre o membro | Enviar uma mensagem) http://http://
Parabéns pela dica.

Muito prática.


por: Onibson (onibson@hotmail.com) : Set 17, 2009 - 10:37
(Informações sobre o membro | Enviar uma mensagem) http://
Muito bom seu artigo...
Fica a pergunta: - Como faço para restaurar o Backup?


por: mor@es (danihb08@hotmail.com) : Out 08, 2009 - 11:48
(Informações sobre o membro | Enviar uma mensagem) http://
Muito boa a dica...vai me ajudar um monte...obrigado e parabéns


por: frandassis (frandassis@yahoo.com.br) : Jan 08, 2010 - 10:47
(Informações sobre o membro | Enviar uma mensagem) http://http://
gera um erro
gbak: ERROR:multiple sources or destinations specified
gbak:Exiting before completion due to errors


por: frcosilva (frcosilva@ibest.com.br) : Fev 06, 2010 - 06:25
(Informações sobre o membro | Enviar uma mensagem)
Kara!
Eu sou totalmente leigo e consegui fazer funcionar.
Ainda não mudei meu BD p/ IB e FB, estou em Access, por isso deu erro, mas todos os processos estão 100%.
Valeeeeeeeuuuu !!!
Abraço e muito grato.
Francisco


por: Jore (jore4ever@hotmail.com) : Mar 13, 2010 - 07:49
(Informações sobre o membro | Enviar uma mensagem)
Aigo estou seguindo seu tutorial que é o melhor que já encontrei....porém estou com uma dúvida.
Onde entre 'o corpo da função'?


por: henriquemoraes (moraes_thebest@hotmail.com) : Jun 23, 2010 - 10:39
(Informações sobre o membro | Enviar uma mensagem)
Muito Bom (y)
  Edição 112

Revista ActiveDelphi

  50 Programas Fontes


  Produtos

Conheça Nossos Produtos

Copyright© 2001-2016 – Active Delphi – Todos os direitos reservados