delphi - How to redirect large amount of output from command executed by CreateProcess? -


i need run sqlite backup command command line. don't want use "cmd /c". command is:

sqlite3.exe mydb.db .dump > mydb.bak

i not find example on shows how this.

code have far, collected various posts this, incomplete:

function startprocess(const acommandline: string; ashowwindow: boolean = true;   awaitforfinish: boolean = false): integer; var   commandline: string;   startupinfo: tstartupinfo;   processinformation: tprocessinformation;   stdoutpiperead, stdoutpipewrite: thandle;   handle: boolean; begin    result := 0;    fillchar(startupinfo, sizeof(tstartupinfo), 0);    fillchar(processinformation, sizeof(tprocessinformation), 0);    startupinfo.cb := sizeof(tstartupinfo);     startupinfo.hstdinput := getstdhandle(std_input_handle);    startupinfo.hstdoutput := stdoutpipewrite;    startupinfo.hstderror := stdoutpipewrite;     if not(ashowwindow)    begin    startupinfo.dwflags := startf_useshowwindow;    startupinfo.wshowwindow := sw_shownormal;    end;     commandline := acommandline;    uniquestring(commandline);    handle := createprocess(nil, pchar(commandline), nil, nil, false,    create_new_process_group + normal_priority_class, nil, nil, startupinfo, processinformation);     closehandle(stdoutpipewrite);     if handle      result := processinformation.dwprocessid;     if awaitforfinish    waitforsingleobject(processinformation.hprocess, infinite);     closehandle(processinformation.hprocess);    closehandle(processinformation.hthread); end; 

since output dump command large, i'm not sure how capture output stdout , redirect it. redirect what? copy con? or tfilestream.write?

i've seen post, incomplete regard implementing redirection output file. guess should ask "what efficient way implement this?"

if has done before, please post code sample illustrating how can it.

tia.

edit:

based on david heffernan's answer, here revised code indeed works properly:

function startprocesswithredirectedoutput(const acommandline: string; const aoutputfile: string;   ashowwindow: boolean = true; awaitforfinish: boolean = false): integer; var   commandline: string;   startupinfo: tstartupinfo;   processinformation: tprocessinformation;   stdoutfilehandle: thandle;   processresult: boolean; begin   result := 0;    stdoutfilehandle := createfile(pchar(aoutputfile), generic_write, file_share_read, nil, create_always,     file_attribute_normal, 0);   win32check(stdoutfilehandle <> invalid_handle_value);    win32check(sethandleinformation(stdoutfilehandle, handle_flag_inherit, 1));    try     fillchar(startupinfo, sizeof(tstartupinfo), 0);     fillchar(processinformation, sizeof(tprocessinformation), 0);      startupinfo.cb := sizeof(tstartupinfo);     startupinfo.dwflags := startupinfo.dwflags or startf_usestdhandles;     startupinfo.hstdinput := getstdhandle(std_input_handle);     startupinfo.hstdoutput := stdoutfilehandle;     startupinfo.hstderror := stdoutfilehandle;      if not(ashowwindow)     begin       startupinfo.dwflags := startupinfo.dwflags or startf_useshowwindow;       startupinfo.wshowwindow := sw_hide;     end;      commandline := acommandline;     uniquestring(commandline);      processresult := win32check(createprocess(nil, pchar(commandline), nil, nil, true,       create_new_process_group + normal_priority_class, nil, nil, startupinfo, processinformation));      if processresult     begin       try         result := processinformation.dwprocessid;          if awaitforfinish           waitforsingleobject(processinformation.hprocess, infinite);                if processinformation.hprocess <> invalid_handle_value           closehandle(processinformation.hprocess);          if processinformation.hthread <> invalid_handle_value           closehandle(processinformation.hthread);       end;     end;        closehandle(stdoutfilehandle);   end; end;  procedure tfadmin.dodbbackup(adbbackupfile: string); var   b, p, q: string; begin    b := extractfilepath(paramstr(0)) + 'ppdb.bak';   p := extractfilepath(paramstr(0)) + 'sqlite3.exe';   q := extractfilepath(paramstr(0)) + 'ppdb.db .dump';    fmain.uniconnection1.close;   try     startprocesswithredirectedoutput(p + ' ' + q, b, true, true);       fmain.uniconnection1.open;   end;    zipmaster1.fspecargs.add(b);   zipmaster1.zipfilename := adbbackupfile;   zipmaster1.add;    deletefile(b);    showmessage('backup complete!');  end; 

create file handle redirection. that's cmd script does. redirects file named 'mydb.bak'.

so, call createfile create file name, , assign handle returned startupinfo.hstdoutput. when external process has finished, call closehandle on file handle close file. you'll need decide standard error handle. 1 common choice merge standard output. assign same handle both hstdoutput , hstderror.

your code assigning standard handles, not asking external process uses them. need include startf_usestdhandles in startupinfo.dwflags.

the call createfile this:

stdoutfilehandle := createfile(   'mydb.bak',   generic_write,   file_share_read,   nil,   create_always,   file_attribute_normal,   0 ); 

check value returned createfile not equal invalid_handle_value.

as mentioned in previous question, need external process inherit file handle pass it. if don't allow inheritance of handles external process cannot use handle pass it. pass true binherithandles parameter of createprocess.

the file handle created createfile not, default inheritable. can either pass security attributes make inheritable. or can set explicitly after have created. latter looks this:

win32check(sethandleinformation(stdoutfilehandle, handle_flag_inherit, 1)); 

examples of former (in context of pipes) can seen in answer here: how redirect binary gbak output delphi stream?

the code mentions stdoutpipewrite needs deleted. cannot work @ moment because not initializing handle.

you should make use of try/finally ensure don't leak handles in face of exceptions.

finally, code contains lot of errors, , little error checking. suggest read , re-read documentation createprocess. have read of example on msdn: http://msdn.microsoft.com/en-us/library/windows/desktop/ms682499.aspx. although uses pipes, principals same. same, instead of pipes use handle returned call createprocess.


Comments

Popular posts from this blog

java.util.scanner - How to read and add only numbers to array from a text file -

rewrite - Trouble with Wordpress multiple custom querystrings -