Firebird GBAK dos pipe

Firebird ve Interbase veritabanları ve SQL komutlarıyla ilgli sorularınızı sorabilirsiniz. Delphi tarafındaki sorularınızı lütfen Programlama forumunda sorunuz.
Cevapla
Kullanıcı avatarı
veliadiguzel
Üye
Mesajlar: 197
Kayıt: 09 Tem 2003 02:11
Konum: Gebze/Kocaeli
İletişim:

Firebird GBAK dos pipe

Mesaj gönderen veliadiguzel »

Kod: Tümünü seç

{$APPTYPE CONSOLE}

uses
  SysUtils, Classes, Windows;

procedure ReadOutputFromExternalProcess(const ApplicationName, CommandLine: string; Stream: TStream);
const
  PipeSecurityAttributes: TSecurityAttributes = (
    nLength: SizeOf(PipeSecurityAttributes);
    bInheritHandle: True
  );
var
  hstdoutr, hstdoutw: THandle;
  StartupInfo: TStartupInfo;
  ProcessInfo: TProcessInformation;
  lpApplicationName: PChar;
  ModfiableCommandLine: string;
  Buffer: array [0..4096-1] of Byte;
  BytesRead: DWORD;
begin
  if ApplicationName='' then begin
    lpApplicationName := nil;
  end else begin
    lpApplicationName := PChar(ApplicationName);
  end;

  ModfiableCommandLine := CommandLine;
  UniqueString(ModfiableCommandLine);

  Win32Check(CreatePipe(hstdoutr, hstdoutw, @PipeSecurityAttributes, 0));
  Try
    Win32Check(SetHandleInformation(hstdoutr, HANDLE_FLAG_INHERIT, 0));//don't inherit read handle of pipe
    ZeroMemory(@StartupInfo, SizeOf(StartupInfo));
    StartupInfo.cb := SizeOf(StartupInfo);
    StartupInfo.dwFlags := STARTF_USESHOWWINDOW or STARTF_USESTDHANDLES;
    StartupInfo.wShowWindow := SW_HIDE;
    StartupInfo.hStdOutput := hstdoutw;
    StartupInfo.hStdError := hstdoutw;
    if not CreateProcess(
      lpApplicationName,
      PChar(ModfiableCommandLine),
      nil,
      nil,
      True,
      CREATE_NO_WINDOW or NORMAL_PRIORITY_CLASS,
      nil,
      nil,
      StartupInfo,
      ProcessInfo
    ) then begin
      RaiseLastOSError;
    end;
    CloseHandle(ProcessInfo.hProcess);
    CloseHandle(ProcessInfo.hThread);
    CloseHandle(hstdoutw);//close the write end of the pipe so that the process is able to terminate
    hstdoutw := 0;
    while ReadFile(hstdoutr, Buffer, SizeOf(Buffer), BytesRead, nil) and (BytesRead<>0) do begin
      Stream.WriteBuffer(Buffer, BytesRead);
    end;
  Finally
    CloseHandle(hstdoutr);
    if hstdoutw<>0 then begin
      CloseHandle(hstdoutw);
    end;
  End;
end;

procedure Test;
var
  Stream: TFileStream;
begin
  Stream := TFileStream.Create('C:\out.txt', fmCreate);
  Try
    ReadOutputFromExternalProcess('', 'gbak.exe -b -v 176.16.0.2:imalat c:\imalat.fbk -user sysdba -pass ******', Stream);
  Finally
    Stream.Free;
  End;
end;

begin
  Test;
end.
out.txt son kısmı.
gbak:writing constraint PK_MALZEMELER
gbak:writing constraint FK_MALZEMELER_DATA_MALZEMELER
gbak:writing constraint INTEG_32
gbak:writing constraint FK_KONTROLLER_DATA_KONTROLLER
gbak:writing constraint INTEG_13
gbak:writing constraint PK_MALIYETLER_DATA
gbak:writing constraint FK_IMALAT_YERLERI_DT_IMLT_YERI
gbak:writing constraint FK_MALIYETLER_DATA_IMALATLAR
gbak:writing constraint INTEG_23
gbak:writing constraint PK_OPERATORLER
gbak:writing constraint INTEG_24
gbak:writing constraint PK_ISCILIK_DATA
gbak:writing constraint FK_ISCILIK_DATA_IMALATLAR
gbak:writing constraint PK_FIRMALAR
gbak:writing constraint INTEG_16
gbak:writing constraint INTEG_17
gbak:writing constraint INTEG_18
gbak:writing constraint INTEG_19
gbak:writing constraint PK_FIB$FIELDS_INFO
gbak:writing constraint FK_ISCILIK_DATA_OPERATORLER
gbak:writing constraint INTEG_25
gbak:writing constraint INTEG_26
gbak:writing constraint PK_TEZGAHLAR
gbak:writing constraint FK_ISCILIK_DATA_TEZGAHLAR
gbak:writing constraint INTEG_33
gbak:writing constraint PK_KONTROL_HATA
gbak:writing constraint INTEG_31
gbak:writing constraint PK_SQL_TXT
gbak:writing referential constraints
gbak:writing check constraints
gbak:writing SQL roles
gbak:closing file, committing, and finishing. 4088320 bytes written
Bu şekilde bir kod buldum ama dosya ya yazarken okuyup kontrol edemiyoruz bunu memory stream le yapmayı dendim ama beceremedim. Ustaların ellerinden öper. Eğer kod çalışırken akan bilgiye bir şekilde alabilirsek iyi bir iş olur diye düşünüyorum.
Veli ADIGÜZEL
Kullanıcı avatarı
veliadiguzel
Üye
Mesajlar: 197
Kayıt: 09 Tem 2003 02:11
Konum: Gebze/Kocaeli
İletişim:

Re: Firebird GBAK dos pipe

Mesaj gönderen veliadiguzel »

Kod: Tümünü seç

procedure ReadOutputFromExternalProcess(const ApplicationName, CommandLine:
  string; Stream: TStream; iMemo: TMemo);
const
  PipeSecurityAttributes: TSecurityAttributes = (
    nLength: SizeOf(PipeSecurityAttributes);
    bInheritHandle: True
    );
var
  hstdoutr, hstdoutw: THandle;
  StartupInfo: TStartupInfo;
  ProcessInfo: TProcessInformation;
  lpApplicationName: PChar;
  ModfiableCommandLine: string;
  Buffer: array[0..4096 - 1] of Byte;
  BytesRead: DWORD;
  i: integer;
  tmpStr: string;
begin
  if ApplicationName = '' then
  begin
    lpApplicationName := nil;
  end
  else
  begin
    lpApplicationName := PChar(ApplicationName);
  end;

  ModfiableCommandLine := CommandLine;
  UniqueString(ModfiableCommandLine);

  Win32Check(CreatePipe(hstdoutr, hstdoutw, @PipeSecurityAttributes, 0));
  try
    Win32Check(SetHandleInformation(hstdoutr, HANDLE_FLAG_INHERIT, 0));
    //don't inherit read handle of pipe
    ZeroMemory(@StartupInfo, SizeOf(StartupInfo));
    StartupInfo.cb := SizeOf(StartupInfo);
    StartupInfo.dwFlags := STARTF_USESHOWWINDOW or STARTF_USESTDHANDLES;
    StartupInfo.wShowWindow := SW_HIDE;
    StartupInfo.hStdOutput := hstdoutw;
    StartupInfo.hStdError := hstdoutw;
    if not CreateProcess(
      lpApplicationName,
      PChar(ModfiableCommandLine),
      nil,
      nil,
      True,
      CREATE_NO_WINDOW or NORMAL_PRIORITY_CLASS,
      nil,
      nil,
      StartupInfo,
      ProcessInfo
      ) then
    begin
      RaiseLastOSError;
    end;
    CloseHandle(ProcessInfo.hProcess);
    CloseHandle(ProcessInfo.hThread);
    CloseHandle(hstdoutw);
    //close the write end of the pipe so that the process is able to terminate
    hstdoutw := 0;
    iMemo.Lines.Clear;
    while ReadFile(hstdoutr, Buffer, SizeOf(Buffer), BytesRead, nil) and
      (BytesRead <> 0) do
    begin
      Stream.WriteBuffer(Buffer, BytesRead);
      for i := 0 to BytesRead-1 do
      begin
        if char(Buffer[i]) <> #13 then
        begin
          tmpStr := tmpStr + Char(Buffer[i]);
        end
        else
        begin
          iMemo.Lines.Add(Trim(tmpStr));
          tmpStr := '';
        end;
      end;
    end;
  finally
    CloseHandle(hstdoutr);
    if hstdoutw <> 0 then
    begin
      CloseHandle(hstdoutw);
    end;
  end;
end;
Bu şekilde çalışıyor önerile açığım böyle de iş görür gibi.

Kullanımı..

Kod: Tümünü seç

procedure TForm1.Button1Click(Sender: TObject);
var
  Stream: TMemoryStream;
  cmd: string;
begin
  cmd := 'C:\Program Files\Firebird\Firebird_2_5\bin\gbak.exe';
  Stream := TMemoryStream.Create;
  try
    ReadOutputFromExternalProcess('',
      cmd +
      ' -b -v 127.0.0.1:D:\Risk\DB\RISK.FDB c:\yedek.fbk -user sysdba -pass masterkey',
      Stream, Memo1);
  finally
    Stream.Free;
  end;
end;

Streami kaldırabilirz herhalde.
Veli ADIGÜZEL
anemos
Üye
Mesajlar: 110
Kayıt: 02 Nis 2007 07:51
Konum: Sakarya / Hendek

Re: Firebird GBAK dos pipe

Mesaj gönderen anemos »

Bu işlem eş zamanlı olarak API ile olabilir. Veya .net için yapılan provideri de kullanabilirsiniz.
omurolmez
Üye
Mesajlar: 187
Kayıt: 31 Eki 2012 11:41

Re: Firebird GBAK dos pipe

Mesaj gönderen omurolmez »

BackupServise bileşenini (Ibx veya diğer) kullanarak aynı hedefe ulaşabilirsiniz ve gbak.exe konumu UAC vs ayrıntılardan kurtulabilirsiniz. Zaten yedekleme servisi aslında Firebird 'dedir ve gbak sadece bu servisi başlatır.
Ömür Ölmez
Kullanıcı avatarı
veliadiguzel
Üye
Mesajlar: 197
Kayıt: 09 Tem 2003 02:11
Konum: Gebze/Kocaeli
İletişim:

Re: Firebird GBAK dos pipe

Mesaj gönderen veliadiguzel »

Uzak makinadan yerele almıyor diye biliyorum. IBX backup beleşeni bi denerim alıyorsa dediğiniz gibi sıkıntı olmaz.
Veli ADIGÜZEL
omurolmez
Üye
Mesajlar: 187
Kayıt: 31 Eki 2012 11:41

Re: Firebird GBAK dos pipe

Mesaj gönderen omurolmez »

Yanlış hatırlamıyorsam Firebird gbak ile de uzak makineden yerel e alamıyor (Interbase 'de 6.5 den sonra bunu değiştirdiler).
Ömür Ölmez
Cevapla