powered by simpleCommunicator - 2.0.61     © 2026 Programmizd 02
Целевая тема:
Создать новую тему:
Автор:
Закрыть
Цитировать
Форумы / Delphi [игнор отключен] [закрыт для гостей] / Запустить с Delphi консольное приложение и считать его вывод
25 сообщений из 25, страница 1 из 1
Запустить с Delphi консольное приложение и считать его вывод
    #37482921
Zmiy
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Добрый день.

Столкнулся с непонятной проблемой. Из дельфи вызываю консольное приложение и считываю его вывод. Проблема в том, что в компилированной версии работает не стабильно, случается что программа просто зависает и дальше не идет. Если запускаю напрямую из дельфи, то при работе консольной программы выходит сообщение отладчика в асемблере и после последующего нажати Run все продолжается как и должно.

С консоли читаю так:
Код: pascal
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
18.
19.
20.
21.
22.
23.
24.
25.
26.
27.
28.
29.
30.
31.
32.
33.
34.
35.
36.
37.
38.
39.
40.
41.
42.
43.
44.
45.
46.
47.
48.
49.
50.
51.
52.
53.
54.
55.
56.
57.
class function TIDCard.readData(DosApp: string): string;
const
  ReadBuffer = 2400;
var
  Security : TSecurityAttributes;
  ReadPipe,WritePipe : THandle;
  start : TStartUpInfo;
  ProcessInfo : TProcessInformation;
  Buffer : Pchar;
  BytesRead : DWord;
  Apprunning : DWord;
begin
  with Security do begin
   nlength := SizeOf(TSecurityAttributes) ;
   binherithandle := true;
   lpsecuritydescriptor := nil;
  end;
  if Createpipe (ReadPipe, WritePipe, @Security, 0) then begin
    Buffer := AllocMem(ReadBuffer + 1) ;
    FillChar(Start,Sizeof(Start),#0) ;
    start.cb := SizeOf(start) ;
    start.hStdOutput := WritePipe;
    start.hStdInput := ReadPipe;
    start.dwFlags := STARTF_USESTDHANDLES +  STARTF_USESHOWWINDOW;
    start.wShowWindow := SW_HIDE;
    if CreateProcess(nil,                            //Тут окно с ассемблером
              PChar(DosApp),
              @Security,
              @Security,
              true,
              NORMAL_PRIORITY_CLASS,
              nil,
              nil,
              start,
              ProcessInfo)
    then begin
      repeat
       Apprunning := WaitForSingleObject
                    (ProcessInfo.hProcess,100) ;
       Application.ProcessMessages;
      until (Apprunning <> WAIT_TIMEOUT) ;
      Repeat
         BytesRead := 0;
         ReadFile(ReadPipe,Buffer[0],
         ReadBuffer,BytesRead,nil) ;
         Buffer[BytesRead]:= #0;
         OemToAnsi(Buffer,Buffer) ;
         Result := Result + String(Buffer) ;
      until (BytesRead < ReadBuffer) ;
    end;
    FreeMem(Buffer) ;
    CloseHandle(ProcessInfo.hProcess) ;
    CloseHandle(ProcessInfo.hThread) ;
    CloseHandle(ReadPipe) ;
    CloseHandle(WritePipe) ;
  end;
end;


В коде вызываю метод таким образом:
Код: pascal
1.
2.
3.
            Application.ProcessMessages;
            Self.loggedIdCode := TIDCard.getPersonalCode;
            Application.ProcessMessages;



Так же впомогательный методы:
Код: pascal
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
18.
class function TIDCard.getPersonalCode: string;
begin
  Result := getValue('Personal ID code');
end;

class function TIDCard.getValue(name: string): string;
var
  src: string;
  startIdx: integer;
begin
  src := readData('idcard/eidenv.exe');
  startIdx := Pos(name, src);
  if (startIdx > 0) then begin
    Result := Copy(src, startIdx + length(name) + 2, 11);
  end else begin
    Result := '';
  end;
end;



Может кто-нибудь подскажет в какую сторону копать?

Заранее благодарен.
...
Рейтинг: 0 / 0
Запустить с Delphi консольное приложение и считать его вывод
    #37482989
Фотография demian111
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Zmiyслучается что программа просто зависает и дальше не идет
как минимум два места вижу:
1. консольная прога не умирает, и ты в вечном цикле с вечной Application.ProcessMessages.
2. цикл чтения из пайпы, если начитывается не меньше чем размер буфера, то повторное чтение, а там уже нету байтов и висим ...
OemToAnsi - Obsolete.

з.ы.
ну и я бы в потоке начитывал.
...
Рейтинг: 0 / 0
Запустить с Delphi консольное приложение и считать его вывод
    #37483220
bk0010
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Пример из DelphiWorld:
Код: pascal
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
18.
19.
20.
21.
22.
23.
24.
25.
26.
27.
28.
29.
30.
31.
32.
33.
34.
35.
36.
37.
38.
39.
40.
41.
42.
43.
44.
45.
46.
47.
48.
49.
50.
51.
52.
53.
54.
55.
56.
57.
58.
59.
60.
61.
62.
63.
64.
65.
66.
67.
68.
69.
70.
71.
72.
73.
74.
75.
76.
77.
78.
79.
80.
81.
82.
83.
84.
85.
86.
87.
88.
89.
90.
91.
92.
93.
94.
95.
96.
97.
98.
99.
100.
101.
102.
103.
104.
105.
106.
107.
108.
109.
110.
111.
112.
113.
114.
115.
116.
117.
118.
119.
120.
121.
122.
123.
124.
125.
126.
127.
128.
129.
130.
131.
132.
133.
134.
135.
136.
137.
138.
139.
140.
141.
142.
143.
144.
145.
146.
147.
148.
149.
function ExecuteFile(FileName, StdInput: string;
  TimeOut: integer;
  var StdOutput: string): boolean;

label
  Error;

type
  TPipeHandles = (IN_WRITE, IN_READ,
    OUT_WRITE, OUT_READ,
    ERR_WRITE, ERR_READ);

type
  TPipeArray = array[TPipeHandles] of THandle;

var
  i: integer;
  ph: TPipeHandles;
  sa: TSecurityAttributes;
  Pipes: TPipeArray;
  StartInf: TStartupInfo;
  ProcInf: TProcessInformation;
  Buf: array[0..1024] of byte;
  TimeStart: TDateTime;

  function ReadOutput: string;
  var
    i: integer;
    s: string;
    BytesRead: longint;

  begin
    Result := '';
    repeat

      Buf[0] := 26;
      WriteFile(Pipes[OUT_WRITE], Buf, 1, BytesRead, nil);
      if ReadFile(Pipes[OUT_READ], Buf, 1024, BytesRead, nil) then
      begin
        if BytesRead > 0 then
        begin
          buf[BytesRead] := 0;
          s := StrPas(@Buf[0]);
          i := Pos(#26, s);
          if i > 0 then
            s := copy(s, 1, i - 1);
          Result := Result + s;
        end;
      end;

      if BytesRead1024 then
        break;
    until false;
  end;

begin
  Result := false;
  for ph := Low(TPipeHandles) to High(TPipeHandles) do
    Pipes[ph] := INVALID_HANDLE_VALUE;

  // Создаем пайпы
  sa.nLength := sizeof(sa);
  sa.bInheritHandle := TRUE;
  sa.lpSecurityDescriptor := nil;

  if not CreatePipe(Pipes[IN_READ], Pipes[IN_WRITE], @sa, 0) then
    goto Error;
  if not CreatePipe(Pipes[OUT_READ], Pipes[OUT_WRITE], @sa, 0) then
    goto Error;
  if not CreatePipe(Pipes[ERR_READ], Pipes[ERR_WRITE], @sa, 0) then
    goto Error;

  // Пишем StdIn
  StrPCopy(@Buf[0], stdInput + ^Z);
  WriteFile(Pipes[IN_WRITE], Buf, Length(stdInput), i, nil);

  // Хендл записи в StdIn надо закрыть - иначе выполняемая программа
  // может не прочитать или прочитать не весь StdIn.

  CloseHandle(Pipes[IN_WRITE]);

  Pipes[IN_WRITE] := INVALID_HANDLE_VALUE;

  FillChar(StartInf, sizeof(TStartupInfo), 0);
  StartInf.cb := sizeof(TStartupInfo);
  StartInf.dwFlags := STARTF_USESHOWWINDOW or STARTF_USESTDHANDLES;

  StartInf.wShowWindow := SW_SHOW; // SW_HIDE если надо запустить невидимо

  StartInf.hStdInput := Pipes[IN_READ];
  StartInf.hStdOutput := Pipes[OUT_WRITE];
  StartInf.hStdError := Pipes[ERR_WRITE];

  if not CreateProcess(nil, PChar(FileName), nil,
    nil, True, NORMAL_PRIORITY_CLASS,
    nil, nil, StartInf, ProcInf) then
    goto Error;

  TimeStart := Now;

  repeat
    Application.ProcessMessages;
    i := WaitForSingleObject(ProcInf.hProcess, 100);
    if i = WAIT_OBJECT_0 then
      break;
    if (Now - TimeStart) * SecsPerDay > TimeOut then
      break;
  until false;

  if iWAIT_OBJECT_0 then
    goto Error;
  StdOutput := ReadOutput;

  for ph := Low(TPipeHandles) to High(TPipeHandles) do
    if Pipes[ph]INVALID_HANDLE_VALUE then
      CloseHandle(Pipes[ph]);

  CloseHandle(ProcInf.hProcess);
  CloseHandle(ProcInf.hThread);
  Result := true;
  Exit;

  Error:

  if ProcInf.hProcessINVALID_HANDLE_VALUE then

  begin
    CloseHandle(ProcInf.hThread);
    i := WaitForSingleObject(ProcInf.hProcess, 1000);
    CloseHandle(ProcInf.hProcess);
    if iWAIT_OBJECT_0 then

    begin
      ProcInf.hProcess := OpenProcess(PROCESS_TERMINATE,
        FALSE,
        ProcInf.dwProcessId);

      if ProcInf.hProcess 0 then
      begin
        TerminateProcess(ProcInf.hProcess, 0);
        CloseHandle(ProcInf.hProcess);
      end;
    end;
  end;

  for ph := Low(TPipeHandles) to High(TPipeHandles) do
    if Pipes[ph]INVALID_HANDLE_VALUE then
      CloseHandle(Pipes[ph]);
end;

...
Рейтинг: 0 / 0
Запустить с Delphi консольное приложение и считать его вывод
    #37484712
Zmiy
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
demian111,

То есть ее надо самому убивать?
...
Рейтинг: 0 / 0
Запустить с Delphi консольное приложение и считать его вывод
    #37484747
Zmiy
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
bk0010,

В 7й версии дельфи не билдится. Говорит
Types of actual and formal var parameters must be identical

В строке:
Код: plaintext
1.
WriteFile(Pipes[OUT_WRITE], Buf,  1 , BytesRead,  nil );
...
Рейтинг: 0 / 0
Запустить с Delphi консольное приложение и считать его вывод
    #37484765
Фотография Anatoly Podgoretsky
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Разве nil var параметр?
...
Рейтинг: 0 / 0
Запустить с Delphi консольное приложение и считать его вывод
    #37484926
Zmiy
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
В статье по крайней мере такой код. Кажется он не для 7й версии.
...
Рейтинг: 0 / 0
Запустить с Delphi консольное приложение и считать его вывод
    #37485089
Alex Kuznetsov
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Zmiy,

если вызов консольного приложения не требует интерактивной с ней работы, а просто консольная программа что-то выполняет на основании параметров, то я-бы перенаправил её вывод в файл и после завершения считывал-бы весь файл.

Как Вам такой вариантец?
...
Рейтинг: 0 / 0
Запустить с Delphi консольное приложение и считать его вывод
    #37485113
Zmiy
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Можно и в файл, но тогда встает вопрос как определить что запись в файл прошла успешно?
...
Рейтинг: 0 / 0
Запустить с Delphi консольное приложение и считать его вывод
    #37485184
чччД
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Zmiy,

Ну, раз есть возможность выбора вариантов взаимодействия - это ж супер!
:)
Можно задействовать различные варианты ipc, начиная с обмена сообщениями и dde. А если объем данных велик - можно в к-н субд писать. Вопросы синхронизации в последнем случае решаются автоматически, механизмом транзакций.
...
Рейтинг: 0 / 0
Запустить с Delphi консольное приложение и считать его вывод
    #37485188
чччД
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
ZmiyМожно и в файл, но тогда встает вопрос как определить что запись в файл прошла успешно?
Методом попытки открытия файла в режиме эксклюзивного доступа.
...
Рейтинг: 0 / 0
Запустить с Delphi консольное приложение и считать его вывод
    #37485857
bk0010
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Zmiybk0010,

В 7й версии дельфи не билдится. Говорит
Types of actual and formal var parameters must be identical

В строке:
Код: plaintext
1.
WriteFile(Pipes[OUT_WRITE], Buf,  1 , BytesRead,  nil );

Заведите переменную типа POverlapped, присвойте ей nil и замените nil в функции на нее
...
Рейтинг: 0 / 0
Запустить с Delphi консольное приложение и считать его вывод
    #37486014
Alex Kuznetsov
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
ZmiyМожно и в файл, но тогда встает вопрос как определить что запись в файл прошла успешно?
Zmiy, запись в файл пройдёт успешно, не переживайте, потому что не Вы будете писать в файл, а система. Т.е. вывод будет перенаправлен с консоли в файл. Вам-же нужно просто дождаться завершения исполнения консольного приложения и считать полученный файл. Надеюсь Вы знаете КАК нужно написать строку исполнения, чтобы вывод пошёл в файл ;-)
...
Рейтинг: 0 / 0
Запустить с Delphi консольное приложение и считать его вывод
    #37486561
Човайохоя
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
А можно ли получить вывод из программы с псевдографическим интерфейсом, таких как FAR Manager ?
...
Рейтинг: 0 / 0
Запустить с Delphi консольное приложение и считать его вывод
    #37486609
Човайохоя
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
ЧовайохояА можно ли получить вывод из программы с псевдографическим интерфейсом, таких как FAR Manager ?Если просто перенаправить вывод в файл, то файл создается пустой
...
Рейтинг: 0 / 0
Запустить с Delphi консольное приложение и считать его вывод
    #37486747
Zmiy
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Спасибо всем, в итоге заработал такой вариант:
Код: pascal
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
18.
19.
20.
21.
22.
23.
24.
25.
26.
27.
28.
29.
30.
31.
32.
33.
34.
35.
36.
37.
38.
39.
40.
41.
42.
43.
44.
45.
46.
47.
48.
49.
50.
51.
52.
53.
54.
55.
56.
57.
58.
59.
60.
61.
62.
63.
64.
65.
66.
67.
68.
69.
70.
71.
72.
73.
74.
75.
76.
class procedure TIDCard.CaptureConsoleOutput(DosApp : string; cpt : TCaption);
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;
begin
  with Security do
  begin
    nlength              := SizeOf(TSecurityAttributes);
    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(Start,Sizeof(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_CLASS,
                     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(ReadPipe        ,@Buffer[TotalBytesRead],
                             ReadBuffer      ,@BytesRead,
                             @TotalBytesAvail,@BytesLeftThisMessage) then break
        else if BytesRead > 0 then
          ReadFile(ReadPipe,Buffer[TotalBytesRead],BytesRead,BytesRead,nil);
        TotalBytesRead:=TotalBytesRead+BytesRead;
      until (Apprunning <> WAIT_TIMEOUT) or (n > 150);

      Buffer[TotalBytesRead]:= #0;
      OemToChar(Buffer,Buffer);
      cpt := cpt + StrPas(Buffer);
    end;
    FreeMem(Buffer);
    CloseHandle(ProcessInfo.hProcess);
    CloseHandle(ProcessInfo.hThread);
    CloseHandle(ReadPipe);
    CloseHandle(WritePipe);
  end;
end;

...
Рейтинг: 0 / 0
Период между сообщениями больше года.
Запустить с Delphi консольное приложение и считать его вывод
    #38515759
dima70
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
Код: pascal
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
18.
19.
20.
21.
22.
23.
24.
25.
26.
27.
28.
29.
30.
31.
32.
33.
34.
35.
36.
37.
38.
39.
40.
41.
42.
43.
44.
45.
46.
47.
48.
49.
50.
51.
52.
53.
54.
55.
56.
57.
58.
59.
60.
61.
62.
63.
64.
65.
66.
67.
68.
69.
70.
71.
72.
73.
74.
75.
76.
function CaptureConsoleOutput(DosApp : string):AnsiString;
const
  ReadBuffer = 1048576;  // 1 MB Buffer
var
  Security            : TSecurityAttributes;
  ReadPipe,WritePipe  : THandle;
  start               : TStartUpInfo;
  ProcessInfo         : TProcessInformation;
  Buffer              : PAnsiChar;
  TotalBytesRead,
  BytesRead           : DWORD;
  Apprunning,n,
  BytesLeftThisMessage,
  TotalBytesAvail : integer;
begin
  with Security do
  begin
    nlength              := SizeOf(TSecurityAttributes);
    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(Start,Sizeof(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_CLASS,
                     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(ReadPipe        ,@Buffer[TotalBytesRead],
                             ReadBuffer      ,@BytesRead,
                             @TotalBytesAvail,@BytesLeftThisMessage) then break
        else if BytesRead > 0 then
          ReadFile(ReadPipe,Buffer[TotalBytesRead],BytesRead,BytesRead,nil);
        TotalBytesRead:=TotalBytesRead+BytesRead;
      until (Apprunning <> WAIT_TIMEOUT) or (n > 150);

      Buffer[TotalBytesRead]:= #0;
     // OemToChar(Buffer,Buffer);
      Result := Result + StrPas(Buffer);
    end;
    FreeMem(Buffer);
    CloseHandle(ProcessInfo.hProcess);
    CloseHandle(ProcessInfo.hThread);
    CloseHandle(ReadPipe);
    CloseHandle(WritePipe);
  end;
end;



Подправит чуток для XE3...
...
Рейтинг: 0 / 0
Период между сообщениями больше года.
Запустить с Delphi консольное приложение и считать его вывод
    #39706418
avlaxoft
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
dima70,

Последний пример не работает на Delphi Tokyo 10.2, валится на "if CreateProcess..."
...
Рейтинг: 0 / 0
Запустить с Delphi консольное приложение и считать его вывод
    #39706476
asutp2
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
avlaxoft,

естественно падает. Ведь DosApp объявлен как string, т.е. в Delphi 10.2 это unicode-строка (1 символ - 2 байта).
А в строке "if CreateProcess" идет приведение DosApp к PChar (1 символ - 1 байт).

Доработайте немного код и он заработает :-)
...
Рейтинг: 0 / 0
Запустить с Delphi консольное приложение и считать его вывод
    #39706478
asutp2
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Хотя конечно я погорячился, не подумав. pchar это же PWideChar)))
...
Рейтинг: 0 / 0
Запустить с Delphi консольное приложение и считать его вывод
    #39706480
Dimitry Sibiryakov
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
asutp2PChar (1 символ - 1 байт).

Не хочу тебя разочаровывать, но PChar там тоже юникодский, 1 символ = 2 байта. И что хуже
всего: CreateProcess должен бы использоваться в юникодной версии (АКА CreateProcessW), так
что проблема не в нём.
Posted via ActualForum NNTP Server 1.5
...
Рейтинг: 0 / 0
Запустить с Delphi консольное приложение и считать его вывод
    #39706485
asutp2
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Dimitry Sibiryakov,

это я понял через минуту после написания своего поста)))) прочитай пост выше своего)))
...
Рейтинг: 0 / 0
Запустить с Delphi консольное приложение и считать его вывод
    #39706521
Dimitry Sibiryakov
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
asutp2это я понял через минуту после написания своего поста)))) прочитай пост выше своего)))

Да, да, видел. Я тоже не чемпион мира по скоростному набору текста.
Posted via ActualForum NNTP Server 1.5
...
Рейтинг: 0 / 0
Запустить с Delphi консольное приложение и считать его вывод
    #39706534
schi
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Обработку ошибок в примерах Пушкин конечно же выполняет.
...
Рейтинг: 0 / 0
Запустить с Delphi консольное приложение и считать его вывод
    #39727189
avlaxoft
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Если кому ещё интересно: вот работающий пример (сорри за лишние комментарии, некогда было код причёсывать...):

Код: pascal
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
18.
19.
20.
21.
22.
23.
24.
25.
26.
27.
28.
29.
30.
31.
32.
33.
34.
35.
36.
37.
38.
39.
40.
41.
42.
43.
44.
45.
46.
47.
48.
49.
50.
51.
52.
53.
54.
55.
56.
57.
58.
59.
60.
61.
62.
63.
64.
65.
66.
67.
68.
69.
70.
71.
72.
73.
74.
75.
76.
77.
78.
79.
80.
81.
82.
83.
84.
85.
86.
87.
88.
89.
90.
91.
92.
93.
94.
95.
96.
97.
98.
99.
100.
101.
102.
103.
104.
105.
106.
107.
108.
109.
110.
111.
112.
113.
114.
115.
116.
117.
118.
119.
120.
121.
122.
123.
124.
125.
126.
127.
128.
129.
130.
131.
132.
133.
134.
135.
136.
137.
138.
139.
140.
141.
142.
143.
144.
145.
146.
147.
148.
149.
150.
151.
152.
153.
154.
155.
156.
157.
158.
159.
160.
161.
162.
163.
164.
unit uMain;

interface

uses
   Vcl.Forms, Vcl.Controls, Vcl.StdCtrls, System.Classes, Vcl.ExtCtrls,
   Windows, StrUtils, SysUtils;

type
  //TAttachConsole = function (dwProcessId: DWORD): LongBOOL stdcall;

  TfmMain = class(TForm)
    btMyButton: TButton;
    edText: TEdit;
    btClear: TButton;
    memOut: TMemo;
    procedure btMyButtonClick(Sender: TObject);
    procedure btClearClick(Sender: TObject);
  private
    { Private declarations }
    function GetDosOutput(const CommandLine: string): string;
  public
    { Public declarations }
  end;

var
  fmMain: TfmMain;

const
  C_EXE_CMD = 'c:\Program Files\SlikSvn\bin\svn.exe log -r '; //'c:\Program Files\SlikSvn\bin\svn.exe';
  C_WORKING_DIR = 'c:\Users\ALEX\Documents\MxLib\';
  C_BUF_SIZE = 1024;
  //Вова "c:\Program Files\SlikSvn\bin\svn.exe"

implementation

{$R *.dfm}

var stopfunc: Integer;

function DosToWin(ASource: AnsiString): AnsiString;
 var
   Ch: PAnsiChar;
 begin
   Ch := AnsiStrAlloc(Length(ASource) + 1);
   OemToAnsi(PAnsiChar(ASource), Ch);
   Result := StrPas(Ch);
   StrDispose(Ch);
 end;

procedure TfmMain.btClearClick(Sender: TObject);
begin
  edText.Clear;
  memOut.Clear;
end;

function TfmMain.GetDosOutput(const CommandLine: string): string;
var
  SA: TSecurityAttributes;
  SI: TStartupInfoA;
  PI: TProcessInformation;
  StdOutPipeRead, StdOutPipeWrite: THandle;
  WasOK: Boolean;
  Buffer: array[0..C_BUF_SIZE - 1] of AnsiChar;
  BytesRead: Cardinal;
  WorkDir, Line: AnsiString;
  i:Integer;
begin
//stopfunc:=0;
  Application.ProcessMessages;
  with SA do
  begin
    nLength := SizeOf(SA);
    bInheritHandle := True;
    lpSecurityDescriptor := nil;
  end;

  CreatePipe(StdOutPipeRead,
             StdOutPipeWrite,
             @SA,
             0
             );
  try

    with SI do
    begin
      FillChar(SI, SizeOf(SI), 0);
      cb := SizeOf(SI);
      dwFlags := STARTF_USESHOWWINDOW or STARTF_USESTDHANDLES;
      wShowWindow := SW_HIDE;
      hStdInput := GetStdHandle(STD_INPUT_HANDLE);
      hStdOutput := StdOutPipeWrite;
      hStdError := StdOutPipeWrite;
    end;

    WorkDir := C_WORKING_DIR; //ExtractFilePath(CommandLine);

    WasOK := CreateProcessA(nil, PAnsiChar(AnsiString(CommandLine)), nil, nil, True, 0, nil, PAnsiChar(WorkDir{'C:\WINDOWS\system32\'}), SI, PI);
    //WasOK := CreateProcess(nil, PChar('C:\WINDOWS\system32\cmd.exe'), nil, nil, True, 0, nil, PChar(WorkDir), SI, PI);

    CloseHandle(StdOutPipeWrite);

    if not WasOK then
      raise Exception.Create('Could not execute command line!')
    else
      try

        Line := '';
        repeat

          WasOK := ReadFile(StdOutPipeRead, Buffer, C_BUF_SIZE, BytesRead, nil);
          if BytesRead > 0 then

          begin

            Buffer[BytesRead] := #0;
            Line := Line + Buffer;
            {if (Copy(Form1.Edit1.text,1,4) = 'ping') then
            begin
            }
             //Memo1.text := DosToWin(Line); // конвертим вывод в мемо, с ОЕМ в Анси
             //Perform(EM_LINESCROLL,0,Memo1.Lines.Count-1); // автопрокрутка мемо вниз
               //////////////////////////  пауза, чтоб не висло окно при пинге и множественных выводов консоли

              {i := 0;
               while i<100 do begin
              sleep(12);
              Application.ProcessMessages;
              inc(i);
              end;
              }
              Application.ProcessMessages;

                //// убиваем процессы
              if stopfunc = 1 then
               begin
               CloseHandle(PI.hThread);
               CloseHandle(PI.hProcess);
               //shellexecute(0,'Open',Pchar('taskkill'),'/im cmd.exe /f',0,SW_HIDE);
               //shellexecute(0,'Open',Pchar('taskkill'),'/im ping.exe /f',0,SW_HIDE);
              Exit;
             end;
            //end;


          end;
        until not WasOK or (BytesRead = 0);
        WaitForSingleObject(PI.hProcess, INFINITE);
      finally
        CloseHandle(PI.hThread);
        CloseHandle(PI.hProcess);
      end;
  finally
      result:=Line;
      CloseHandle(StdOutPipeRead);
  end;
end;

procedure TfmMain.btMyButtonClick(Sender: TObject);
begin
  memOut.Lines.Text := GetDosOutput(C_EXE_CMD + Trim(edText.Text));
end;

end. 

...
Рейтинг: 0 / 0
25 сообщений из 25, страница 1 из 1
Форумы / Delphi [игнор отключен] [закрыт для гостей] / Запустить с Delphi консольное приложение и считать его вывод
Найденые пользователи ...
Разблокировать пользователей ...
Читали форум (0):
Пользователи онлайн (0):
x
x
Закрыть


Просмотр
0 / 0
Close
Debug Console [Select Text]