Como eu uso o gbak com WinExec ou ShellExecute no delphi?

Delphi

17/03/2009

Alguém sabe como eu faço para chamar o gbak dentro da minha aplicação de backup/restore no delphi?? Eu vi que existem essas duas funções para chamar aplicativos externos no dephi. Mas eu não sei como elas funcionam e nem como eu chamo o gbak e passo os parâmetros de backup. Eu preciso utilizar o gbak pq é o único jeito de fazer backup no servidor e salvar os dados no meu host. Se alguém souber como eu uso e PRINCIPALMENTE, como eu faço para passar os parâmetros do backup/restore, eu fico muito agradecido. Vlw!!


Junnsouzza

Junnsouzza

Curtidas 0

Respostas

Woinch

Woinch

17/03/2009

Se for utilizar o WinExec basta fazer o seguinte:

WinExec(PChar(´aplicativo.exe -parametros´, SW_SHOWNORMAL));


Já para o ShellExecute:

ShellExecute(Handle, ´open´, PChar(´Aplicacao.exe´), PChar(´-parametros´), ´´, SW_SHOWNORMAL);


*Lembrando que a constante SW_SHOWNORMAL pode ser trocada por outras, por exemplo SW_HIDE que irá executar o programa de forma oculta.


Espero ter ajudado.


GOSTEI 0
Webjoel

Webjoel

17/03/2009

Olá!

Basta você passar um comando para o seu cmd, como você faria na mão, segue um exemplo de uma cópia de arquivo:

WinExec(PChar(´cmd.exe /c copy C:\etiquetas.txt c:\joel\etiquetas.txt´),SW_SHOWNORMAL);



GOSTEI 0
Junnsouzza

Junnsouzza

17/03/2009

O gbak fica dentro da pasta bin do firebird. Eu tenho que colocar ele na pasta do meu projeto??


GOSTEI 0
Woinch

Woinch

17/03/2009

Não, basta você passar o caminho completo dele.


GOSTEI 0
Junnsouzza

Junnsouzza

17/03/2009

Eu sei. É que tipo, se eu instalar minha aplicação dentro de uma máquina onde eu não saiba onde o Firebird esteja instalado. Ai eu queria saber se colocando o gbak.exe dentro da pasta do meu projeto do delphi ele funciona. Tipo, eu ponho o gbak dentro da pasta ProjetoBackup, ai no código do programa eu ponho: WinExec(PChar(´gbak.exe -parametros´, SW_SHOWNORMAL));

Será que isso funciona??


GOSTEI 0
Woinch

Woinch

17/03/2009

Tem que fazer um teste. Mas se não me engano só funciona direto se estiver na pasta System32 ou na pasta Windows. Para fazer dessa maneira experimente utilizar a seguinte função:

ExtractFilePath(Application.FileName);


Ela irá retornar a pasta onde está a aplicação.


GOSTEI 0
Junnsouzza

Junnsouzza

17/03/2009

ExtractFilePath(Application.FileName) nem compilou. Não existe essa condição Applicatio.FileName.


GOSTEI 0
Junnsouzza

Junnsouzza

17/03/2009

caraca. Eu testei as duas e as duas fucionaram!!
Quando eu usava o IBBackupService e IBRestoreService (Usava, não uso mais), eu tinha as seguintes linhas de código dentro do
with IBBackupService do:

Verbose := true; 
ServiceStart;      
While not Eof do 
   mmBackup.Lines.Add(GetNextLine); // mmBackup é um memo 


Isso fazia com que os detalhes do serviço de backup fossem sendo impressos nas linhas do Memo. Esses mesmos detalhes aparecem no console quando eu executo o gbak. Pois bem, tem como fazer essas linhas serem impressas no Memo novamente, já que eu não uso mais os IBServices??


GOSTEI 0
Seven

Seven

17/03/2009

Não sei se vai te ajudar, mas para não ter que colocar o GBAK na pasta do sistema, eu uso assim: (a funcão de execução EXECEXTERNO peguei em um tópico aqui mesmo no forum).

GetEnvironmentVariable(´PROGRAMFILES´) pega a pasta arquivos de programas (independente de onde estiver.


execexterno(GetEnvironmentVariable(´PROGRAMFILES´)+´\firebird\firebird_2_0\bin\isql.exe´,´ -extract -quiet -output ´+GetEnvironmentVariable(´TEMP´)+´\bancotemp.tmp ´+endbancoant+´ -user sysdba -password masterkey´,SW_HIDE);


até


function ExecExterno(const FileName, Params: string; const WindowState: Word): boolean;
var
SUInfo: TStartupInfo;
ProcInfo: TProcessInformation;
CmdLine: string;
begin
{ Coloca o nome do arquivo entre aspas. Isto é necessário devido aos espaços contidos em nomes longos }
CmdLine := ´´´ + Filename+´´ ´+ Params ;
FillChar(SUInfo, SizeOf(SUInfo), #0);
with SUInfo do
begin
cb := SizeOf(SUInfo);
dwFlags := STARTF_USESHOWWINDOW;
wShowWindow := WindowState;
end;
Result := CreateProcess(nil, PChar(CmdLine), nil, nil, false,
CREATE_NEW_CONSOLE or NORMAL_PRIORITY_CLASS, nil,
PChar(ExtractFilePath(Filename)), SUInfo, ProcInfo);
{ Aguarda até ser finalizado }
if Result then
begin
WaitForSingleObject(ProcInfo.hProcess, INFINITE);
{ Libera os Handles }
CloseHandle(ProcInfo.hProcess);
CloseHandle(ProcInfo.hThread);
end;
end;


GOSTEI 0
Woinch

Woinch

17/03/2009

ExtractFilePath(Application.FileName) nem compilou. Não existe essa condição Applicatio.FileName.


Desculpe, escrevi errado. O correto é:

ExtractFilePath(Application.ExeName)



GOSTEI 0
Junnsouzza

Junnsouzza

17/03/2009

Olá galera. Eu consegui utilizar o ShellExecute para realizar backup. O problema agora é que o programa chama o ShellExecute e não espera que ele termine. Eu mando imprimir num Message box a mensagem de que o backup foi feito, mas o porgrama nem espera que o backup termina e já exibe o message box.


GOSTEI 0
Igorcb

Igorcb

17/03/2009

vc pode criar um arq .bat e depois executar
pelo shellexecute


GOSTEI 0
Junnsouzza

Junnsouzza

17/03/2009

Bem pessoal. Eu utilizei a função abaixo para fazer o backup com o gbak, pegar as saídas do console e imprimir num Memo. Pena que nada disso funcionou. O backup é feito com sucesso, mas nada é impresso no Memo. Se alguem puder me ajudar. Eu usei tb duas outras funções parecidas com essa, mas elas agem da mesma forma. Fazem o backup porém não imprime a saída no memo.

eu chamo a função desse jeito : CaptureConsoleOutput(´C:\Arquivos de programas\Firebird\Firebird_1_5\bin\gbak.exe´ + ´ -b -v -user SYSDBA -pas masterkey ´ + ArqBackupOrigem + ´ ´ + ArqBackupDestino, mmBackup);

procedure TForm1.CaptureConsoleOutput(DosApp : string;AMemo : TMemo);
const
  ReadBuffer = 1048576;  // 1 MB Buffer
var
  Security            : TSecurityAttributes;
  ReadPipe,WritePipe  : THandle;
  start               : TStartUpInfo;
  ProcessInfo         : TProcessInformation;
  Buffer              : Pchar;
  TotalBytesRead,
  BytesRead           : DWORD;
  Apprunning,n,
  BytesLeftThisMessage,
  TotalBytesAvail : integer;
begin
  with Security do
  begin
    nlength              := SizeOf(TSecurityAttributes);
    binherithandle       := true;
    lpsecuritydescriptor := nil;
  end;

  if CreatePipe (ReadPipe, WritePipe, @Security, 0) then
  begin
    // Redirect In- and Output through STARTUPINFO structure

    Buffer  := AllocMem(ReadBuffer + 1);
    FillChar(Start,Sizeof(Start),#0); 
    start.cb          := SizeOf(start);
    start.hStdOutput  := WritePipe;
    start.hStdInput   := ReadPipe;
    start.dwFlags     := STARTF_USESTDHANDLES + STARTF_USESHOWWINDOW; 
    start.wShowWindow := SW_HIDE;

    // Create a Console Child Process with redirected input and output

    if CreateProcess(nil      ,PChar(DosApp),
                     @Security,@Security, 
                     true     ,CREATE_NO_WINDOW or NORMAL_PRIORITY_CLASS,
                     nil      ,nil, 
                     start    ,ProcessInfo) then
    begin 
      n:=0;
      TotalBytesRead:=0; 
      repeat
        // Increase counter to prevent an endless loop if the process is dead 
        Inc(n,1);
         
        // wait for end of child process
        Apprunning := WaitForSingleObject(ProcessInfo.hProcess,100);
        Application.ProcessMessages;

        // it is important to read from time to time the output information
        // so that the pipe is not blocked by an overflow. New information 
        // can be written from the console app to the pipe only if there is
        // enough buffer space. 

        if not PeekNamedPipe(ReadPipe        ,@Buffer[TotalBytesRead], 
                             ReadBuffer      ,@BytesRead,
                             @TotalBytesAvail,@BytesLeftThisMessage) then break 
        else if BytesRead > 0 then
          ReadFile(ReadPipe,Buffer[TotalBytesRead],BytesRead,BytesRead,nil); 
        TotalBytesRead:=TotalBytesRead+BytesRead;
      until (Apprunning <> WAIT_TIMEOUT) or (n > 150); 

      Buffer[TotalBytesRead]:= 0;
      OemToChar(Buffer,Buffer);
      AMemo.Text := AMemo.Text + (StrPas(Buffer));
    end; 
    FreeMem(Buffer);
    CloseHandle(ProcessInfo.hProcess); 
    CloseHandle(ProcessInfo.hThread); 
    CloseHandle(ReadPipe);
    CloseHandle(WritePipe); 
  end;
end;



GOSTEI 0
Eduardo Silva

Eduardo Silva

17/03/2009

Bem pessoal. Eu utilizei a função abaixo para fazer o backup com o gbak, pegar as saídas do console e imprimir num Memo. Pena que nada disso funcionou. O backup é feito com sucesso, mas nada é impresso no Memo. Se alguem puder me ajudar. Eu usei tb duas outras funções parecidas com essa, mas elas agem da mesma forma. Fazem o backup porém não imprime a saída no memo.

eu chamo a função desse jeito : CaptureConsoleOutput(´C:\\Arquivos de programas\\Firebird\\Firebird_1_5\\bin\\gbak.exe´ + ´ -b -v -user SYSDBA -pas masterkey ´ + ArqBackupOrigem + ´ ´ + ArqBackupDestino, mmBackup);

procedure TForm1.CaptureConsoleOutput(DosApp : string;AMemo : TMemo);
const
  ReadBuffer = 1048576;  // 1 MB Buffer
var
  Security            : TSecurityAttributes;
  ReadPipe,WritePipe  : THandle;
  start               : TStartUpInfo;
  ProcessInfo         : TProcessInformation;
  Buffer              : Pchar;
  TotalBytesRead,
  BytesRead           : DWORD;
  Apprunning,n,
  BytesLeftThisMessage,
  TotalBytesAvail : integer;
begin
  with Security do
  begin
    nlength              := SizeOf(TSecurityAttributes);
    binherithandle       := true;
    lpsecuritydescriptor := nil;
  end;

  if CreatePipe (ReadPipe, WritePipe, @Security, 0) then
  begin
    // Redirect In- and Output through STARTUPINFO structure

    Buffer  := AllocMem(ReadBuffer + 1);
    FillChar(Start,Sizeof(Start),#0); 
    start.cb          := SizeOf(start);
    start.hStdOutput  := WritePipe;
    start.hStdInput   := ReadPipe;
    start.dwFlags     := STARTF_USESTDHANDLES + STARTF_USESHOWWINDOW; 
    start.wShowWindow := SW_HIDE;

    // Create a Console Child Process with redirected input and output

    if CreateProcess(nil      ,PChar(DosApp),
                     @Security,@Security, 
                     true     ,CREATE_NO_WINDOW or NORMAL_PRIORITY_CLASS,
                     nil      ,nil, 
                     start    ,ProcessInfo) then
    begin 
      n:=0;
      TotalBytesRead:=0; 
      repeat
        // Increase counter to prevent an endless loop if the process is dead 
        Inc(n,1);
         
        // wait for end of child process
        Apprunning := WaitForSingleObject(ProcessInfo.hProcess,100);
        Application.ProcessMessages;

        // it is important to read from time to time the output information
        // so that the pipe is not blocked by an overflow. New information 
        // can be written from the console app to the pipe only if there is
        // enough buffer space. 

        if not PeekNamedPipe(ReadPipe        ,@Buffer[TotalBytesRead], 
                             ReadBuffer      ,@BytesRead,
                             @TotalBytesAvail,@BytesLeftThisMessage) then break 
        else if BytesRead > 0 then
          ReadFile(ReadPipe,Buffer[TotalBytesRead],BytesRead,BytesRead,nil); 
        TotalBytesRead:=TotalBytesRead+BytesRead;
      until (Apprunning <> WAIT_TIMEOUT) or (n > 150); 

      Buffer[TotalBytesRead]:= 0;
      OemToChar(Buffer,Buffer);
      AMemo.Text := AMemo.Text + (StrPas(Buffer));
    end; 
    FreeMem(Buffer);
    CloseHandle(ProcessInfo.hProcess); 
    CloseHandle(ProcessInfo.hThread); 
    CloseHandle(ReadPipe);
    CloseHandle(WritePipe); 
  end;
end;



esse comando é só para o backup e o restore fica como?
GOSTEI 0
POSTAR