Home > Archive > SQL Anywhere database > July 2005 > Retreive dbbackup output dynamically









You are viewing an archived Text-only version of the thread. To view this thread in it's original format and/or if you want to reply to this thread please [click here]

 

Author Retreive dbbackup output dynamically
Luis

2005-07-20, 9:23 am

Hi,

I'm trying to retreive the out of the dbbackup command line... because of
one of the parameters is a -l (for live backup) I can't rely on -o (output
to file)...

What I'm currently doing is to call a CreateProcess (Windows API) and try to
retreive the stdout (standard output of the created process) however, i got
nothing...

any help!

Luis Ortega


Luis

2005-07-20, 11:23 am

What I'm trying to do is a live backup from a delphi application (pascal
code). I have no problem loading dbbackup with the proper parameters...
however I can't catch the console output (Page XX of XX)

Note: I tried issung the NativeDB components, however those components does
not support live backup....

thanks,
Luis

"Luis" <Luis@noemail.com> wrote in message news:42de5d01$1@foru
ms-2-dub...
> Hi,
>
> I'm trying to retreive the out of the dbbackup command line... because of
> one of the parameters is a -l (for live backup) I can't rely on -o (output
> to file)...
>
> What I'm currently doing is to call a CreateProcess (Windows API) and try
> to retreive the stdout (standard output of the created process) however, i
> got nothing...
>
> any help!
>
> Luis Ortega
>



Scott Holman

2005-07-20, 1:23 pm

If you are expecting that the output from the CreateProcess() be redirected
via the delphi applications console then you will need to redirect stdout
during the CreateProcess(). The function below will hook stdin and stdout
of the current process to the process being created. You can then redirect
: MyBackupWrapper.exe > result.txt.

function ExecAndWait(
Path: PChar; Visibility: Word; Timeout : DWORD; errFile: string;
var exitCode: cardinal): integer;
var
WaitResult : integer;
StartupInfo: TStartupInfo;
ProcessInfo: TProcessInformation;

iResult : integer;
hErr, hProcess: THandle;
pEnvironment: pointer;
begin
Result := 0;
hErr := 0;
if errFile <> '' then begin
hErr := CreateStdErrorFile(e
rrFile);
if hErr = INVALID_HANDLE_VALUE
then
hErr := 0;
end;

pEnvironment := GetEnvironmentString
s;
FillChar(StartupInfo
, SizeOf(TStartupInfo)
, 0);
with StartupInfo do
begin
cb := SizeOf(TStartupInfo)
;
dwFlags := STARTF_USESTDHANDLES
or STARTF_USESHOWWINDOW
or
STARTF_FORCEONFEEDBA
CK;
{ you could pass sw_show or sw_hide as parameter: }
wShowWindow := visibility;
hStdError := hErr;
hStdInput := GetStdHandle(STD_INP
UT_HANDLE);
hStdOutput := GetStdHandle(STD_OUT
PUT_HANDLE);
end;
if CreateProcess(nil,pa
th,nil, nil, True,
NORMAL_PRIORITY_CLAS
S or CREATE_NEW_CONSOLE or CREATE_DEFAULT_ERROR
_MODE,
pEnvironment, nil,
StartupInfo, ProcessInfo) then
begin
hProcess := ProcessInfo.hProcess;
WaitResult := WaitForSingleObject(
hProcess, timeout);
{ timeout is in miliseconds or INFINITE if
you want to wait forever }
GetExitCodeProcess(h
Process, exitCode);
CloseHandle(hProcess
);
result := WaitResult;
end
else
{ error occurs during CreateProcess see help for details }
result:=GetLastError
;

if (hErr <> INVALID_HANDLE_VALUE
) and (hErr <> 0) then begin
FlushFileBuffers(hEr
r);
CloseHandle(hErr);
end;
end;


"Luis" <Luis@noemail.com> wrote in message news:42de7308$1@foru
ms-1-dub...
> What I'm trying to do is a live backup from a delphi application (pascal
> code). I have no problem loading dbbackup with the proper parameters...
> however I can't catch the console output (Page XX of XX)
>
> Note: I tried issung the NativeDB components, however those components
> does not support live backup....
>
> thanks,
> Luis
>
> "Luis" <Luis@noemail.com> wrote in message news:42de5d01$1@foru
ms-2-dub...
>
>



Luis

2005-07-20, 8:23 pm

thanks Scott,

unfortunately that code execute and does not return until the backup is
finished... therefore I have no responce to the front end about backedup
pages... what I'm looking for is very similar to your code, however I'm
looking to read the output as it goes out, and not at the end...

here is another modified sample... (this one actually output to a memo file
what the result on the backup, however it does it when the backup is done...


procedure 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;
outputstring : String;


procedure AddLine(Data :String);
begin
AMemo.Lines. Add(FormatDateTime('
mmddyyyy hh:nn:ss --------------------
',Now));
AMemo.Lines.Add(Data);
end;
begin

AddLine('Excecuting(
'+DosApp +')');
with Security do
begin
nlength := SizeOf(TSecurityAttr
ibutes);
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(Buffer[0],ReadBuffer-1,#0);
FillChar(Start,Sizeo
f(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_CLAS
S,
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(ReadPi
pe ,@Buffer[0],
ReadBuffer ,@BytesRead,
@TotalBytesAvail,@By
tesLeftThisMessage) then
AddLine('PeekNamedPi
pe : False : ' + IntToStr(GetLastErro
r))
else if BytesRead > 0 then
ReadFile(ReadPipe,Bu
ffer& #91;0],BytesRead,Byt
esRead,nil);
TotalBytesRead:=Tota
lBytesRead+BytesRead
;

Buffer[BytesRead]:= #0;
OemToChar(Buffer,Buf
fer);
outputstring := StrPas(Buffer);
if outputstring <> '' then begin
beep;
AddLine(outputstring
); // output to memo
FillChar(Buffer[0],ReadBuffer-1,#0); //reset buffer
end;

until (Apprunning <> WAIT_TIMEOUT);// or (n > 150);


end;
FreeMem(Buffer);
CloseHandle(ProcessI
nfo.hProcess);
CloseHandle(ProcessI
nfo.hThread);
CloseHandle(ReadPipe
);
CloseHandle(WritePip
e);
AddLine('out of process!');
end;
end;





"Scott Holman" <sholman@micros.com> wrote in message
news:42de91d8@forums
-2-dub...
> If you are expecting that the output from the CreateProcess() be
> redirected via the delphi applications console then you will need to
> redirect stdout during the CreateProcess(). The function below will hook
> stdin and stdout of the current process to the process being created. You
> can then redirect : MyBackupWrapper.exe > result.txt.
>
> function ExecAndWait(
> Path: PChar; Visibility: Word; Timeout : DWORD; errFile: string;
> var exitCode: cardinal): integer;
> var
> WaitResult : integer;
> StartupInfo: TStartupInfo;
> ProcessInfo: TProcessInformation;

> iResult : integer;
> hErr, hProcess: THandle;
> pEnvironment: pointer;
> begin
> Result := 0;
> hErr := 0;
> if errFile <> '' then begin
> hErr := CreateStdErrorFile(e
rrFile);
> if hErr = INVALID_HANDLE_VALUE
then
> hErr := 0;
> end;
>
> pEnvironment := GetEnvironmentString
s;
> FillChar(StartupInfo
, SizeOf(TStartupInfo)
, 0);
> with StartupInfo do
> begin
> cb := SizeOf(TStartupInfo)
;
> dwFlags := STARTF_USESTDHANDLES
or STARTF_USESHOWWINDOW
or
> STARTF_FORCEONFEEDBA
CK;
> { you could pass sw_show or sw_hide as parameter: }
> wShowWindow := visibility;
> hStdError := hErr;
> hStdInput := GetStdHandle(STD_INP
UT_HANDLE);
> hStdOutput := GetStdHandle(STD_OUT
PUT_HANDLE);
> end;
> if CreateProcess(nil,pa
th,nil, nil, True,
> NORMAL_PRIORITY_CLAS
S or CREATE_NEW_CONSOLE or CREATE_DEFAULT_ERROR
_MODE,
> pEnvironment, nil,
> StartupInfo, ProcessInfo) then
> begin
> hProcess := ProcessInfo.hProcess;
> WaitResult := WaitForSingleObject(
hProcess, timeout);
> { timeout is in miliseconds or INFINITE if
> you want to wait forever }
> GetExitCodeProcess(h
Process, exitCode);
> CloseHandle(hProcess
);
> result := WaitResult;
> end
> else
> { error occurs during CreateProcess see help for details }
> result:=GetLastError
;
>
> if (hErr <> INVALID_HANDLE_VALUE
) and (hErr <> 0) then begin
> FlushFileBuffers(hEr
r);
> CloseHandle(hErr);
> end;
> end;
>
>
> "Luis" <Luis@noemail.com> wrote in message news:42de7308$1@foru
ms-1-dub...
>
>



Martin Baur

2005-07-20, 8:23 pm

In article <42dea188$1@forums-2-dub>, Luis@noemail.com says...
> thanks Scott,
>
> unfortunately that code execute and does not return until the backup is
> finished... therefore I have no responce to the front end about backedup
> pages... what I'm looking for is very similar to your code, however I'm
> looking to read the output as it goes out, and not at the end...
>
> here is another modified sample... (this one actually output to a memo file
> what the result on the backup, however it does it when the backup is done...



Why not forking the ExecAndWait for the backup to another thread? Arm a thread to receive the end of the backup and then you can display / use it.

Martin
Luis

2005-07-20, 8:23 pm

If I do that I can't have any input until is done...

something interesting from Sybase help file.... unfortunately Delphi does
not support Embedded SQL...

************* from help file *************
db_backup( ... DB_BACKUP_START ... )
allocate page buffer based on page size in SQLCODE
sqlda = alloc_sqlda( 1 )
sqlda->sqld = 1;
sqlda->sqlvar[0].sqltype = DT_BINARY
sqlda->sqlvar[0].sqldata = allocated buffer
for file_num = 0 to DB_BACKUP_MAX_FILE
db_backup( ... DB_BACKUP_OPEN_FILE,
file_num ... )
if SQLCODE == SQLE_NO_ERROR
/* The file exists */
num_pages = SQLCOUNT
file_time = SQLE_IO_ESTIMATE
open backup file with name from sqlca.sqlerrmc
for page_num = 0 to num_pages - 1
db_backup( ... DB_BACKUP_READ_PAGE,

file_num, page_num, sqlda )
write page buffer out to backup file
next page_num
close backup file
db_backup( ... DB_BACKUP_CLOSE_FILE
, file_num ... )
end if
next file_num
backup up file DB_BACKUP_WRITE_FILE
as above
backup up file DB_BACKUP_TRANS_LOG_
FILE as above
free page buffer
db_backup( ... DB_BACKUP_END ... )

************* from help file *************


"Martin Baur" <tinu@mindpower.com> wrote in message
news:MPG. 1d48c1cf508deb6f9898
1c@forums.sybase.com...
> In article <42dea188$1@forums-2-dub>, Luis@noemail.com says...
>
>
> Why not forking the ExecAndWait for the backup to another thread? Arm a
> thread to receive the end of the backup and then you can display / use it.
>
> Martin



Martin Baur

2005-07-20, 8:23 pm

In article <42deba14$1@forums-2-dub>, Luis@noemail.com says...
> If I do that I can't have any input until is done...
>
> something interesting from Sybase help file.... unfortunately Delphi does
> not support Embedded SQL...



Sorry, I seem to understand only now .. you want to have kinda progress indicator. Right?

Martin
Luis

2005-07-21, 9:23 am

yep :-)


"Martin Baur" <tinu@mindpower.com> wrote in message
news:MPG. 1d49174cea4e89929898
1d@forums.sybase.com...
> In article <42deba14$1@forums-2-dub>, Luis@noemail.com says...
>
>
> Sorry, I seem to understand only now .. you want to have kinda progress
> indicator. Right?
>
> Martin



Luis

2005-07-21, 9:23 am

I'm fairly sure that dbtools allows me to do a live backup (based on one of
the parameters).... so let's try that route...

I'm trying to do the conversion to pascal, but I'm having an access
violation (probably beccause the conversion is not right yet...)

-- out of dbtools.h
typedef struct a_backup_db {
unsigned short version; // set this to DBTOOLS_VERSION_NUMB
ER
const char * output_dir; // set this to folder for backup files
const char * connectparms; // userid,password,data
base
const char * startline; // (obsolete)
MSG_CALLBACK confirmrtn;
MSG_CALLBACK errorrtn;
MSG_CALLBACK msgrtn;
MSG_CALLBACK statusrtn;
a_bit_field backup_database : 1; // dbbackup -d sets TRUE
a_bit_field backup_logfile : 1; // dbbackup -t sets TRUE
a_bit_field backup_writefile: 1;
a_bit_field no_confirm : 1; // dbbackup -y sets TRUE
a_bit_field quiet : 1; // dbbackup -q sets TRUE
a_bit_field rename_log : 1; // dbbackup -r sets TRUE
a_bit_field truncate_log : 1; // dbbackup -x sets TRUE
a_bit_field rename_local_log: 1; // dbbackup -n sets TRUE
const char * hotlog_filename; // dbbackup -l sets name
char backup_interrupted; // backup interrupted if non-zero
// Following field is new with 9.0.1:
a_bit_field server_backup : 1; // dbbackup -s sets TRUE
} a_backup_db;

extern _crtn short _entry DBBackup( const a_backup_db * );

-- so far mi conversion to pascal...


A_BIT_FIELD = Byte;

MSG_CALLBACK = function (Info: PChar) : word; stdcall;

PTa_backup_db = ^Ta_backup_db;
Ta_backup_db = record
version: Word;
output_dir: PCHAR;
connectparms: PCHAR;
startline: PCHAR;
confirmrtn: MSG_CALLBACK;
errorrtn: MSG_CALLBACK;
msgrtn: MSG_CALLBACK;
statusrtn: MSG_CALLBACK;
BACKUP_DATABASE : A_BIT_FIELD;
BACKUP_LOGFILE : A_BIT_FIELD;
BACKUP_WRITEFILE : A_BIT_FIELD;
NO_CONFIRM : A_BIT_FIELD;
QUIET : A_BIT_FIELD;
RENAME_LOG : A_BIT_FIELD;
TRUNCATE_LOG : A_BIT_FIELD;
RENAME_LOCAL_LOG : A_BIT_FIELD;
hotlog_filename : PCHAR;
backup_interrupted: Char;
{/// Following field is new with 9.0.1: }
SERVER_BACKUP : A_BIT_FIELD;
end {a_backup_db};

function DBBackup(a_backup_db
: PTa_backup_db ) : Word ; stdcall; external
'dbtool9.dll';





"Luis" <Luis@noemail.com> wrote in message news:42de5d01$1@foru
ms-2-dub...
> Hi,
>
> I'm trying to retreive the out of the dbbackup command line... because of
> one of the parameters is a -l (for live backup) I can't rely on -o (output
> to file)...
>
> What I'm currently doing is to call a CreateProcess (Windows API) and try
> to retreive the stdout (standard output of the created process) however, i
> got nothing...
>
> any help!
>
> Luis Ortega
>



Martin Baur

2005-07-21, 8:23 pm

In article <42dfb362$1@forums-1-dub>, Luis@noemail.com says...
> I'm fairly sure that dbtools allows me to do a live backup (based on one of
> the parameters).... so let's try that route...
>
> I'm trying to do the conversion to pascal, but I'm having an access
> violation (probably beccause the conversion is not right yet...)



What is a_bit_field in C? Is it only a byte as you translated? Or is it a macro which should be translated to pascal as bitset?

Curious to see this working .. I could also use this because I also have lots of D7 apps which run with ASA using NativeDB.

Regards

Martin
Sponsored Links





Also available: Server administration forum archive | Web Design forum archive | Software forum archive | Hardware reviews archive | Programming forum archive

Copyright 2008 droptable.com