Delphi 7: how to execute shell command and check the result?

前端 未结 6 385
一整个雨季
一整个雨季 2021-01-01 08:28

I\'m using Delphi 7 and can\'t predict the target version of Windows.

I need to create a database (probably MySql, but might be something else) and define some table

相关标签:
6条回答
  • 2021-01-01 08:39

    Use DSiExecuteAndCapture from DSiWin32:

    var
      exitCode: integer;
      output  : TStringList;
    begin
      output := TStringList.Create;
      try
        if DSiExecuteAndCapture('mysql --version', output, '', exitCode) = 0 then
          Log(Format('error %d, cannot start', [GetLastError])) 
        else begin
          // check exitCode and output
        end;
      finally FreeAndNil(output); end;
    end;
    
    0 讨论(0)
  • 2021-01-01 08:39

    I wrote a unit and set of components to handle console redirection in delphi quite a long time ago:

    http://www.fulgan.com/delphi/dospipes15.zip

    But beyond that, you shouldn't have to go through that: use the ADO connection component just to connect to the database's default catalog and then use the "execute" method to create whatever database and schema you need. The database SERVER need to be properly installed and running for this to work but, at least with MSSQL, there is no problem with creating new databases this way. the exact connection string to use might change depending on the target DB, though.

    0 讨论(0)
  • 2021-01-01 08:42

    What you are looking for, probably, is an embedded database. Some options:

    • Firebird Embedded
    • MySQL Embedded
    • SQLite

    With either of databases and with appropriate data access components (not sure about ADO support for embedded FB and MySQL), you will be able to:

    • attach without a DB
    • create a DB
    • then create the tables
    0 讨论(0)
  • 2021-01-01 08:47

    Here is an article that explains it detail

    Capture the output from a DOS (command/console) Window

    But in short you need to Create two pipes to read and write the output. Then you need to set StdInput and StdOutput in the TStartUpInfo structure, then pass this structure to the CreateProcess() call.

    Here is another article that shows how to Wait for the process to finish.

    0 讨论(0)
  • 2021-01-01 08:47

    I wonder why everybody who wants launch a new process tends to use ShellExecute instead, which is designed to open file in associated application?

    You want new process? Then use CreateProcess. End of story.

    CreateProcess allows you to wait for process, to get its exit code, to read its console output and many more.

    0 讨论(0)
  • 2021-01-01 08:55

    I saved this from a newsgroup post a long time ago; I don't know who originall wrote it, though.

    This code allows you to run a DOS application and capture it's output in a TMemo. You can then pull what you need out of the memo with a little trial and error parsing the lines.

    procedure TFMainForm.RunDosInMemo(const DosApp: String; AMemo: TRichEdit);
    const
      ReadBuffer = 2400;
    var
      Security : TSecurityAttributes;
      StdInPipeR, StdInPipeW : THandle;
      StdOutPipeR, StdOutPipeW : THandle;
      StartInfo : TStartUpInfo;
      ProcessInfo : TProcessInformation;
      Buffer : PByte;
      BytesAvailable, BytesRead : DWord;
      sDosApp: String;
      sData: RawByteString;
    begin
      sDosApp := DosApp;
      UniqueString(sDosApp);
    
      with Security do begin
        nLength := SizeOf(TSecurityAttributes);
        bInheritHandle := True;
        lpSecurityDescriptor := nil;
      end;
    
      if CreatePipe(StdInPipeR, StdInPipeW, @Security, 0) then
      try
    
        SetHandleInformation(StdInPipeW, HANDLE_FLAG_INHERIT, 0);
        if CreatePipe(StdOutPipeR, StdOutPipeW, @Security, 0) then
        try
          SetHandleInformation(StdOutPipeR, HANDLE_FLAG_INHERIT, 0);
          GetMem(Buffer, ReadBuffer);
          try
            ZeroMemory(@StartInfo, SizeOf(StartInfo));
            StartInfo.cb := SizeOf(StartInfo);
            StartInfo.hStdOutput := StdOutPipeW;
            StartInfo.hStdInput := StdInPipeR;
            StartInfo.dwFlags := STARTF_USESTDHANDLES or STARTF_USESHOWWINDOW;
            StartInfo.wShowWindow := SW_HIDE;
    
            if CreateProcess(nil, 
                             PChar(sDosApp), 
                             nil, 
                             nil, 
                             True, 
                             NORMAL_PRIORITY_CLASS, 
                             nil, 
                             nil, 
                             StartInfo, 
                             ProcessInfo) then
              try
                while WaitForSingleObject(ProcessInfo.hProcess, 500) <> WAIT_TIMEOUT do
                  Application.ProcessMessages;
                while PeekNamedPipe(StdOutPipeR, nil, 0, nil, BytesAvailable, nil) do 
                begin
                  if BytesAvailable < 1 then 
                    Break;
                  if BytesAvailable > ReadBuffer then 
                    BytesAvailable := ReadBuffer;
                  if not ReadFile(StdOutPipeR, 
                                  Buffer[0], 
                                  BytesAvailable, 
                                  BytesRead, 
                                  nil) then 
                    Break;
                  SetString(sData, PAnsiChar(Buffer), BytesRead);
                  // assign an appropriate codepage for the output data:
                  // 0 for default Ansi, 1252 or 20157 for ASCII, 1200 for 
                  // Unicode, etc...
                  SetCodePage(sData, ...);
                  // this is faster and more efficient than reading/writing the 
                  // Text property directly...
                  AMemo.SelStart := AMemo.GetTextLen;
                  AMemo.SelLength := 0;
                  AMemo.SelText := sData;
                end;
              finally
                CloseHandle(ProcessInfo.hThread);
                CloseHandle(ProcessInfo.hProcess);
              end;
          finally
            FreeMem(Buffer);
          end;
        finally
          CloseHandle(StdOutPipeR);
          CloseHandle(StdOutPipeW);
        end;
      finally
        CloseHandle(StdInPipeR);
        CloseHandle(StdInPipeW);
      end;
    end;
    
    0 讨论(0)
提交回复
热议问题