Delphi 7: как выполнить команду оболочки и проверить результат? - PullRequest
2 голосов
/ 25 мая 2010

Я использую Delphi 7 и не могу предсказать целевую версию Windows.

Мне нужно создать базу данных (возможно, MySql, но может быть что-то еще) и определить некоторые структуры таблиц. Мне не нужно заполнять какие-либо данные. К сожалению, все компоненты ADO ожидают, что база данных уже существует, и тогда они позволят вам манипулировать ею.

Итак, поскольку это всего лишь несколько простых команд, я подумал, что я мог бы также использовать ShellExectute ().

Согласен? Не согласен?

Может кто-нибудь дать мне пример кода, который попытается запустить «MySql --version» и позволить мне проверить результат? После этого я смогу понять это для себя. Спасибо.


[править]

Не в обиду, но я знаю, как гуглить. Просто я не нахожу полезных результатов. Я сам виноват в том, что не задал этот вопрос явно, поэтому примите мои извинения - мне нужен пример кода, а не только имя компонента.

Извините (и спасибо за ответы до сих пор (все +1))


[править]

Ссылки, которые дает Роберт, выполняют свою работу (процедура RunDosInMemo () делает свое дело) ... НО Вы должны помнить, что нужно включать расширение .exe (то есть, notepad.exe, а не «Блокнот» и получить полный путь, если ваша команда не находится на пути.

Ответы [ 6 ]

7 голосов
/ 25 мая 2010

Вот статья, которая объясняет это подробно

Захват вывода из окна DOS (команда / консоль)

Но вкратце вам нужно создать два канала для чтения и записи вывода. Затем необходимо установить StdInput и StdOutput в структуре TStartUpInfo , а затем передать эту структуру в вызов CreateProcess () .

Вот еще одна статья , в которой показано, как ждать завершения процесса.

5 голосов
/ 25 мая 2010

Использовать DSiExecuteAndCapture из 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;
3 голосов
/ 25 мая 2010

Вероятно, вы ищете встроенную базу данных. Некоторые варианты:

  • Firebird Embedded
  • MySQL Embedded
  • SQLite

С любой из баз данных и с соответствующими компонентами доступа к данным (не уверен в поддержке ADO для встроенных FB и MySQL), вы сможете:

  • прикрепить без БД
  • создать БД
  • затем создайте таблицы
3 голосов
/ 25 мая 2010

Интересно, почему все, кто хочет запустить новый процесс, вместо этого стремятся использовать ShellExecute, которая предназначена для открытия файла в связанном приложении?

Вам нужен новый процесс?Затем используйте CreateProcess.Конец истории.

CreateProcess позволяет вам ждать процесса, получить код его завершения, прочитать вывод его консоли и многое другое.

2 голосов
/ 25 мая 2010

Я сохранил это из сообщения группы новостей давным-давно; Хотя я не знаю, кто это написал.

Этот код позволяет вам запускать приложение DOS и записывать его вывод в TMemo. Затем вы можете извлечь из заметки то, что вам нужно, с помощью небольшой процедуры проб и ошибок при анализе строк.

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;
1 голос
/ 26 мая 2010

Я написал модуль и набор компонентов для обработки перенаправления консоли в Delphi довольно давно:

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

Но кроме того, вам не нужно проходить через это: используйте компонент подключения ADO просто для подключения к каталогу базы данных по умолчанию, а затем используйте метод execute для создания любой базы данных и схемы, которые вам нужны. СЕРВЕР базы данных должен быть правильно установлен и запущен, чтобы это работало, но, по крайней мере, с MSSQL, нет проблем с созданием новых баз данных таким способом. однако точная строка подключения может меняться в зависимости от целевой БД.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...