Note that there are some explanatory texts on larger screens.

plurals
  1. PO
    text
    copied!<p>For a more complete answer, one that also illustrates input redirection, I'm posting my code. Thanks to David Heffernan for guidance, without which this would not be possible.</p> <p>The code involves backup and restore of a SQLite database, by calling the Sqlite3.exe executable file using CreateProcess. Obviously input and output needs to be redirected to/from this command and the code below illustrates how to achieve this:</p> <pre><code>function StartProcessWithRedirectedOutput(const ACommandLine: string; const AOutputFile: string; AShowWindow: boolean = True; AWaitForFinish: boolean = False): Integer; var CommandLine: string; StartupInfo: TStartupInfo; ProcessInformation: TProcessInformation; StdOutFileHandle: THandle; begin Result := 0; StdOutFileHandle := CreateFile(PChar(AOutputFile), GENERIC_WRITE, FILE_SHARE_READ, nil, CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, 0); Win32Check(StdOutFileHandle &lt;&gt; INVALID_HANDLE_VALUE); try Win32Check(SetHandleInformation(StdOutFileHandle, HANDLE_FLAG_INHERIT, 1)); 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) then begin StartupInfo.dwFlags := StartupInfo.dwFlags or STARTF_USESHOWWINDOW; StartupInfo.wShowWindow := SW_HIDE; end; CommandLine := ACommandLine; UniqueString(CommandLine); Win32Check(CreateProcess(nil, PChar(CommandLine), nil, nil, True, CREATE_NEW_PROCESS_GROUP + NORMAL_PRIORITY_CLASS, nil, nil, StartupInfo, ProcessInformation)); try Result := ProcessInformation.dwProcessId; if AWaitForFinish then WaitForSingleObject(ProcessInformation.hProcess, INFINITE); finally CloseHandle(ProcessInformation.hProcess); CloseHandle(ProcessInformation.hThread); end; finally CloseHandle(StdOutFileHandle); end; end; function StartProcessWithRedirectedInput(const ACommandLine: string; const AInputFile: string; AShowWindow: boolean = True; AWaitForFinish: boolean = False): Integer; var CommandLine: string; StartupInfo: TStartupInfo; ProcessInformation: TProcessInformation; StdInFileHandle: THandle; begin Result := 0; StdInFileHandle := CreateFile(PChar(AInputFile), GENERIC_READ, FILE_SHARE_READ, nil, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, 0); Win32Check(StdInFileHandle &lt;&gt; INVALID_HANDLE_VALUE); try Win32Check(SetHandleInformation(StdInFileHandle, HANDLE_FLAG_INHERIT, 1)); FillChar(StartupInfo, SizeOf(TStartupInfo), 0); FillChar(ProcessInformation, SizeOf(TProcessInformation), 0); StartupInfo.cb := SizeOf(TStartupInfo); StartupInfo.dwFlags := StartupInfo.dwFlags or STARTF_USESTDHANDLES; StartupInfo.hStdInput := StdInFileHandle; StartupInfo.hStdOutput := GetStdHandle(STD_OUTPUT_HANDLE); StartupInfo.hStdError := GetStdHandle(STD_OUTPUT_HANDLE); if not(AShowWindow) then begin StartupInfo.dwFlags := StartupInfo.dwFlags or STARTF_USESHOWWINDOW; StartupInfo.wShowWindow := SW_HIDE; end; CommandLine := ACommandLine; UniqueString(CommandLine); Win32Check(CreateProcess(nil, PChar(CommandLine), nil, nil, True, CREATE_NEW_PROCESS_GROUP + NORMAL_PRIORITY_CLASS, nil, nil, StartupInfo, ProcessInformation)); try Result := ProcessInformation.dwProcessId; if AWaitForFinish then WaitForSingleObject(ProcessInformation.hProcess, INFINITE); finally CloseHandle(ProcessInformation.hProcess); CloseHandle(ProcessInformation.hThread); end; finally CloseHandle(StdInFileHandle); 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); finally fMain.UniConnection1.Open; end; ZipMaster1.FSpecArgs.Add(b); ZipMaster1.ZipFileName := ADBBackupFile; ZipMaster1.Add; DeleteFile(b); ShowMessage('Backup complete!'); end; procedure TfAdmin.DoDBRestore(ADBBackupFile: String); var b, p, q, q2, r: String; begin b := ExtractFilePath(ParamStr(0)) + 'PPDB.bak'; p := '"' + ExtractFilePath(ParamStr(0)) + 'sqlite3.exe"'; q := '"' + ExtractFilePath(ParamStr(0)) + 'PPDB.db"'; ZipMaster1.ExtrBaseDir := ExtractFilePath(ParamStr(0)); ZipMaster1.ExtrOptions := [ExtrOverWrite]; ZipMaster1.ZipFileName := ADBBackupFile; ZipMaster1.Extract; fMain.UniConnection1.Close; try q2 := StringReplace(q, '"', '', [rfReplaceAll]); r := ChangeFileExt(q2, '.db$'); if FileExists(r) then DeleteFile(r); if not RenameFile(q2, r) then RaiseLastOSError; StartProcessWithRedirectedInput(p + ' ' + q, b, True, True); finally fMain.UniConnection1.Open; end; DeleteFile(b); ShowMessage('Restore complete!'); end; </code></pre>
 

Querying!

 
Guidance

SQuiL has stopped working due to an internal error.

If you are curious you may find further information in the browser console, which is accessible through the devtools (F12).

Reload