Форум по Delphi программированию

Delphi Sources



Вернуться   Форум по Delphi программированию > Все о Delphi > [ "Начинающим" ]
Ник
Пароль
Регистрация <<         Правила форума         >> FAQ Пользователи Календарь Поиск Сообщения за сегодня Все разделы прочитаны

Ответ
 
Опции темы Поиск в этой теме Опции просмотра
  #1  
Старый 25.04.2012, 04:20
JackRu JackRu вне форума
Прохожий
 
Регистрация: 08.07.2009
Сообщения: 46
Репутация: 10
Вопрос перехват вывода консольного приложения

Всем доброго времени суток. Столкнулся с такой задачей, программа( уже готовая) запускается в консоли ( командная строка win )... я запускаю через батник при помощи команды

Код:
java -Xmx1536M -Xms1536M -Dfile.encoding=UTF-8 -jar program.jar

Задача следующая, перехватить все данные, которые выводятся в консоли.

Нашёл уже готовый код программы для перехвата

Код:
unit Unit1;

interface

uses
  Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
  Dialogs, StdCtrls;

type
  TForm1 = class(TForm)
    Button1: TButton;
    Memo1: TMemo;
    procedure Button1Click(Sender: TObject);
  private
    { Private declarations }
  public
    { Public declarations }
  end;

var
  Form1: TForm1;

implementation

{$R *.dfm}

procedure ExecConsoleApp(CommandLine: AnsiString; Output: TStringList; Errors:   
  TStringList);
var  
  sa: TSECURITYATTRIBUTES;   
  si: TSTARTUPINFO;   
  pi: TPROCESSINFORMATION;   
  hPipeOutputRead: THANDLE;   
  hPipeOutputWrite: THANDLE;   
  hPipeErrorsRead: THANDLE;   
  hPipeErrorsWrite: THANDLE;   
  Res, bTest: Boolean;   
  env: array[0..100] of Char;   
  szBuffer: array[0..256] of Char;
  dwNumberOfBytesRead: DWORD;   
  Stream: TMemoryStream;   
begin  
  sa.nLength := sizeof(sa);   
  sa.bInheritHandle := true;   
  sa.lpSecurityDescriptor := nil;   
  CreatePipe(hPipeOutputRead, hPipeOutputWrite, @sa, 0);   
  CreatePipe(hPipeErrorsRead, hPipeErrorsWrite, @sa, 0);   
  ZeroMemory(@env, SizeOf(env));   
  ZeroMemory(@si, SizeOf(si));   
  ZeroMemory(@pi, SizeOf(pi));   
  si.cb := SizeOf(si);   
  si.dwFlags := STARTF_USESHOWWINDOW or STARTF_USESTDHANDLES;   
  si.wShowWindow := SW_HIDE;
  si.hStdInput := 0;   
  si.hStdOutput := hPipeOutputWrite;   
  si.hStdError := hPipeErrorsWrite;   
    
  (* Remember that if you want to execute an app with no parameters you nil the  
     second parameter and use the first, you can also leave it as is with no  
     problems.                                                                 *)  
  Res := CreateProcess(nil, pchar(CommandLine), nil, nil, true,   
    CREATE_NEW_CONSOLE or NORMAL_PRIORITY_CLASS, @env, nil, si, pi);   
    
  // Procedure will exit if CreateProcess fail   
  if not Res then  
  begin  
    CloseHandle(hPipeOutputRead);
    CloseHandle(hPipeOutputWrite);   
    CloseHandle(hPipeErrorsRead);   
    CloseHandle(hPipeErrorsWrite);   
    Exit;   
  end;   
  CloseHandle(hPipeOutputWrite);   
  CloseHandle(hPipeErrorsWrite);   
    
  //Read output pipe   
  Stream := TMemoryStream.Create;   
  try  
    while true do  
    begin  
      bTest := ReadFile(hPipeOutputRead, szBuffer, 256, dwNumberOfBytesRead,
        nil);   
      if not bTest then  
      begin  
        break;   
      end;   
      Stream.Write(szBuffer, dwNumberOfBytesRead);   
    end;   
    Stream.Position := 0;   
    Output.LoadFromStream(Stream);   
  finally  
    Stream.Free;   
  end;   
    
  //Read error pipe
  Stream := TMemoryStream.Create;   
  try  
    while true do  
    begin  
      bTest := ReadFile(hPipeErrorsRead, szBuffer, 256, dwNumberOfBytesRead,   
        nil);   
      if not bTest then  
      begin  
        break;   
      end;   
      Stream.Write(szBuffer, dwNumberOfBytesRead);   
    end;   
    Stream.Position := 0;   
    Errors.LoadFromStream(Stream);
  finally
    Stream.Free;
  end;

  WaitForSingleObject(pi.hProcess, INFINITE);
  CloseHandle(pi.hProcess);
  CloseHandle(hPipeOutputRead);
  CloseHandle(hPipeErrorsRead);
end;


procedure TForm1.Button1Click(Sender: TObject);
var
  OutP: TStringList;
  ErrorP: TStringList;
begin
  OutP := TStringList.Create;
  ErrorP := TstringList.Create;

  ExecConsoleApp('cmd.exe', OutP, ErrorP);
  Memo1.Lines.Assign(OutP);

  OutP.Free;
  ErrorP.Free;
end;

end.
Админ: Учимся пользоваться тегами грамотно!

Но загвоздка вот в чём, каким образом так скажем связать программу по перехвату и ту, данные которой нужно перехватить ?

Последний раз редактировалось Admin, 25.04.2012 в 09:56.
Ответить с цитированием
  #2  
Старый 25.04.2012, 04:26
Аватар для angvelem
angvelem angvelem вне форума
.
 
Регистрация: 18.05.2011
Адрес: Омск
Сообщения: 3,970
Версия Delphi: 3,5,7,10,12,XE2
Репутация: выкл
По умолчанию

Куда вывести перехват нужно?
__________________
Je venus de nulle part
55.026263 с.ш., 73.397636 в.д.
Ответить с цитированием
Этот пользователь сказал Спасибо angvelem за это полезное сообщение:
JackRu (26.04.2012)
  #3  
Старый 25.04.2012, 04:33
JackRu JackRu вне форума
Прохожий
 
Регистрация: 08.07.2009
Сообщения: 46
Репутация: 10
По умолчанию

в Мемо не плохо было бы )
Ответить с цитированием
  #4  
Старый 25.04.2012, 04:38
Аватар для angvelem
angvelem angvelem вне форума
.
 
Регистрация: 18.05.2011
Адрес: Омск
Сообщения: 3,970
Версия Delphi: 3,5,7,10,12,XE2
Репутация: выкл
По умолчанию

Посмотри эту и эту ссылки.
__________________
Je venus de nulle part
55.026263 с.ш., 73.397636 в.д.
Ответить с цитированием
Этот пользователь сказал Спасибо angvelem за это полезное сообщение:
JackRu (26.04.2012)
  #5  
Старый 25.04.2012, 05:02
JackRu JackRu вне форума
Прохожий
 
Регистрация: 08.07.2009
Сообщения: 46
Репутация: 10
По умолчанию

Спасибо большое, воспользовался этим кодом
Код:
procedure RunDosInMemo(CmdLine: string; AMemo: TMemo);
const
  ReadBuffer = 2400;
var
  Security: TSecurityAttributes;
  ReadPipe, WritePipe: THandle;
  start: TStartUpInfo;
  ProcessInfo: TProcessInformation;
  Buffer: Pchar;
  BytesRead: DWord;
  Apprunning: DWord;
begin
  Screen.Cursor := CrHourGlass;
  Form1.Button1.Enabled := False;
  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(CmdLine),
      @Security,
      @Security,
      true,
      NORMAL_PRIORITY_CLASS,
      nil,
      nil,
      start,
      ProcessInfo) then
    begin
      repeat
        Apprunning := WaitForSingleObject
          (ProcessInfo.hProcess, 100);
        ReadFile(ReadPipe, Buffer[0],
          ReadBuffer, BytesRead, nil);
        Buffer[BytesRead] := #0;
        OemToAnsi(Buffer, Buffer);
        AMemo.Text := AMemo.text + string(Buffer);

        Application.ProcessMessages;
      until (Apprunning <> WAIT_TIMEOUT);
    end;
    FreeMem(Buffer);
    CloseHandle(ProcessInfo.hProcess);
    CloseHandle(ProcessInfo.hThread);
    CloseHandle(ReadPipe);
    CloseHandle(WritePipe);
  end;
  Screen.Cursor := CrDefault;
  Form1.Button1.Enabled := True;
end;

procedure TForm1.Button1Click(Sender: TObject);
begin
  Memo1.Clear;
  RunDosInMemo('ping -t 192.168.28.200', Memo1);
end;

Но появился ещё 1 вопрос
- После начала перехвата данных, программа жутко зависает и невозможно использовать другие элементы. Возможно ли как нибудь решить этот вопрос ?
Ответить с цитированием
  #6  
Старый 25.04.2012, 21:11
Аватар для angvelem
angvelem angvelem вне форума
.
 
Регистрация: 18.05.2011
Адрес: Омск
Сообщения: 3,970
Версия Delphi: 3,5,7,10,12,XE2
Репутация: выкл
По умолчанию

Использовать
1. ProcessMessages
2. Thread
__________________
Je venus de nulle part
55.026263 с.ш., 73.397636 в.д.
Ответить с цитированием
Этот пользователь сказал Спасибо angvelem за это полезное сообщение:
JackRu (26.04.2012)
  #7  
Старый 26.04.2012, 15:41
JackRu JackRu вне форума
Прохожий
 
Регистрация: 08.07.2009
Сообщения: 46
Репутация: 10
По умолчанию

Сделал через Thread, но при выводе информации в memo1, выдаётся только
Цитата:
>
>
>
>
>
>
>
>
И ничего другого

Последний раз редактировалось JackRu, 26.04.2012 в 21:14.
Ответить с цитированием
  #8  
Старый 26.04.2012, 21:27
Аватар для angvelem
angvelem angvelem вне форума
.
 
Регистрация: 18.05.2011
Адрес: Омск
Сообщения: 3,970
Версия Delphi: 3,5,7,10,12,XE2
Репутация: выкл
По умолчанию

Процитировать справку или написать код?
__________________
Je venus de nulle part
55.026263 с.ш., 73.397636 в.д.
Ответить с цитированием
  #9  
Старый 26.04.2012, 21:33
JackRu JackRu вне форума
Прохожий
 
Регистрация: 08.07.2009
Сообщения: 46
Репутация: 10
По умолчанию

Если сможете написать код, буду очень благодарен
Ответить с цитированием
  #10  
Старый 27.04.2012, 13:38
JackRu JackRu вне форума
Прохожий
 
Регистрация: 08.07.2009
Сообщения: 46
Репутация: 10
По умолчанию

А можно и справку, хотя б узнаю в чём дело ... может самому получится подправить
Ответить с цитированием
  #11  
Старый 27.04.2012, 14:08
Аватар для NumLock
NumLock NumLock вне форума
Let Me Show You
 
Регистрация: 30.04.2010
Адрес: Северодвинск
Сообщения: 5,426
Версия Delphi: 7, XE5
Репутация: 59586
По умолчанию

пример командной строки в Memo
Вложения
Тип файла: rar Console.rar (2.3 Кбайт, 237 просмотров)
__________________
Пишу программы за еду.
__________________
Ответить с цитированием
Этот пользователь сказал Спасибо NumLock за это полезное сообщение:
JackRu (27.04.2012)
  #12  
Старый 27.04.2012, 17:09
JackRu JackRu вне форума
Прохожий
 
Регистрация: 08.07.2009
Сообщения: 46
Репутация: 10
По умолчанию

У меня какя цель - сделать программу напоминающую батник, но
1. С дальнейшей обработкой данных, которые отображаются в консоли
2. С возможностью отправки команд

Так что этот вариант не особо подходит ... (
Ответить с цитированием
  #13  
Старый 27.04.2012, 17:25
Аватар для NumLock
NumLock NumLock вне форума
Let Me Show You
 
Регистрация: 30.04.2010
Адрес: Северодвинск
Сообщения: 5,426
Версия Delphi: 7, XE5
Репутация: 59586
По умолчанию

Цитата:
Сообщение от JackRu
1. С дальнейшей обработкой данных, которые отображаются в консоли
2. С возможностью отправки команд
этот пример отправляеет команды в cmd и получает данные от его в Memo, которые, естественно, можно обрабатывать. а переделать отправку не из поля, а из bat проще простого.
__________________
Пишу программы за еду.
__________________
Ответить с цитированием
Этот пользователь сказал Спасибо NumLock за это полезное сообщение:
JackRu (28.04.2012)
  #14  
Старый 27.04.2012, 20:55
JackRu JackRu вне форума
Прохожий
 
Регистрация: 08.07.2009
Сообщения: 46
Репутация: 10
По умолчанию

По сути дела всё работает шикарно, как и хотел, вся информация перехватывается на ура ... Но вот только отправка команды для приложения, которое уже запущено, не совсем работает
Изображения
Тип файла: jpg скрин 1111.JPG (97.5 Кбайт, 44 просмотров)
Ответить с цитированием
  #15  
Старый 28.04.2012, 09:02
Аватар для NumLock
NumLock NumLock вне форума
Let Me Show You
 
Регистрация: 30.04.2010
Адрес: Северодвинск
Сообщения: 5,426
Версия Delphi: 7, XE5
Репутация: 59586
По умолчанию

приложение должно получать ввод с консоли?
__________________
Пишу программы за еду.
__________________
Ответить с цитированием
Этот пользователь сказал Спасибо NumLock за это полезное сообщение:
JackRu (28.04.2012)
Ответ


Delphi Sources

Опции темы Поиск в этой теме
Поиск в этой теме:

Расширенный поиск
Опции просмотра

Ваши права в разделе
Вы не можете создавать темы
Вы не можете отвечать на сообщения
Вы не можете прикреплять файлы
Вы не можете редактировать сообщения

BB-коды Вкл.
Смайлы Вкл.
[IMG] код Вкл.
HTML код Выкл.
Быстрый переход


Часовой пояс GMT +3, время: 02:38.


 

Сайт

Форум

FAQ

Соглашения

Прочее

 

Copyright © Форум "Delphi Sources" by BrokenByte Software, 2004-2025