[Delphi/Pipes] Wysyłanie ciągu znaków i pobieranie odpowiedz

0

Witam serdecznie,

Mam dosyć duży problem.
Otóż mam dosyć dużą, konsolową aplikację, której nie można zmodyfikować.

Muszę ją włączyć, pobierać co pewien czas (może być prymitywny timer) co wyświetla w konsoli. Potem muszę odpowiedzieć wpisując odpowiedni ciąg znaków itd...

Od razu mówię, że nie może to być automat, ponieważ tego wymaga projekt. Może być też dosyć duże opóźnienie (np. 5 minutowe) w reakcji aplikacji konsolowej, jeżeli ma to jakieś znaczenie.

Jest napisana w C(++ ?) i raczej standardowo wyświetla to w CMD.

Szukając rozwiązania widziałem takie "brzydkie" - pobieranie uchwytu i symulacja wciskania klawiszy itd...

Najciekawsze na co udało mi się trafić, to wykorzystanie stdin i stdout z poziomu Delphiego poprzez Pipes.

I tu jest pies pogrzebany: w ogóle nie mam pojęcia jak go użyć. W sieci jest wiele przykładów - niestety często wybrakowanych, niekompletnych lub nie działających...

Proszę Was bardzo o pomoc,
pozdrawiam.

0

Jest napisana w C

To dlaczego jest w dziale Delphi ?

Szukając rozwiązania widziałem takie "brzydkie"

Czyli jakie ?

0
Patryk27 napisał(a)

Jest napisana w C

To dlaczego jest w dziale Delphi ?

jakubkrol napisał(a)

Otóż mam dosyć dużą, konsolową aplikację, której nie można zmodyfikować.

(...)

Jest napisana w C(++ ?)

Moja aplikacja jest w Delphi.

Patryk27 napisał(a)

Szukając rozwiązania widziałem takie "brzydkie"

Czyli jakie ?

jakubkrol napisał(a)

Szukając rozwiązania widziałem takie "brzydkie" - pobieranie uchwytu i symulacja wciskania klawiszy itd...

0

w faqu albo artach masz jak w delphi przechwycić standardowe we/wy cmd - poszukaj

0
Misiekd napisał(a)

w faqu albo artach masz jak w delphi przechwycić standardowe we/wy cmd - poszukaj

Wiesz co... Jednak po prostu to zrobię pod Delphi 7... W 2009 za dużo z tym męczenia, a pod siodemką to wszystko działa...

Dzięki Wam jeszcze raz i temat do zamknięcia :P

0

mozesz napisac, ale jak chcesz zaoszczedzic troche czasu to masz do tego gotowy komponent: TUnitedCMD, poszukaj w googlach..

0
cimak napisał(a)

mozesz napisac, ale jak chcesz zaoszczedzic troche czasu to masz do tego gotowy komponent: TUnitedCMD, poszukaj w googlach..

Na prawdę uważacie mnie za tępego :D
Próbowałem, tak samo z TCommand coś tam - oba nie działają (AV na Win 7 po kompilacji w Delphi 2009).

0

Tu masz przykład, który odpala polecenie w konsoli, czeka na zakończenie i zwraca wyjście. Do swojego przykładu musiałbyś przerobić.

function TForm1.ExecuteCommand(ACommand,AParams:WideString; var AOutput:String):DWORD;
var
  SI:TStartupInfo;
  PI:TProcessInformation;
  SA:TSecurityAttributes;
  hReadPipe:THandle;
  hWritePipe:THandle;
  Bufor:array[0..127] of Char;
  BytesRead:Cardinal;
begin
  ZeroMemory(@SI,SizeOf(TStartupInfo));
  ZeroMemory(@SA,SizeOf(TSecurityAttributes));
  SA.nLength:=sizeof(TSecurityAttributes);
  SA.lpSecurityDescriptor:=nil;
  SA.bInheritHandle:=True;
  SI.cb:=SizeOf(TStartupInfo);
  SI.dwFlags:=STARTF_USESTDHANDLES or STARTF_USESHOWWINDOW;
  CreatePipe(hReadPipe,hWritePipe,@SA,300*1024);
  SI.hStdOutput:=hWritePipe;
  SI.hStdInput:=hReadPipe;
  SI.hStdError:=hWritePipe;
  SI.wShowWindow:=SW_HIDE;
  CreateProcessW(nil,PWideChar(ACommand+' '+AParams),nil,nil,True,CREATE_NEW_CONSOLE,nil,nil,SI,PI);
  Repeat
    Application.ProcessMessages;
  until WaitForSingleObject(PI.hProcess,150)<>WAIT_TIMEOUT;
  GetExitCodeProcess(PI.hProcess,Result);
  CloseHandle(PI.hProcess);
  CloseHandle(hWritePipe);
  while ReadFile(hReadPipe,Bufor,SizeOf(Bufor),BytesRead,nil) do begin
    Bufor[BytesRead]:=#0;
    AOutPut:=AOutPut+Copy(Bufor,0,BytesRead);
    FillChar(Bufor,SizeOf(Bufor),0);
    Application.ProcessMessages;
  end;
  CloseHandle(hReadPipe);
end;

Delphi 2009 i następne nie są do końca zgodne z poprzednimi ze względu na obsługę unicode. Powyższy przykład działał na D7.

0
Azarien napisał(a)

Tu masz przykład, który odpala polecenie w konsoli, czeka na zakończenie i zwraca wyjście. Do swojego przykładu musiałbyś przerobić.

function TForm1.ExecuteCommand(ACommand,AParams:WideString; var AOutput:String):DWORD;
var
  SI:TStartupInfo;
  PI:TProcessInformation;
  SA:TSecurityAttributes;
  hReadPipe:THandle;
  hWritePipe:THandle;
  Bufor:array[0..127] of Char;
  BytesRead:Cardinal;
begin
  ZeroMemory(@SI,SizeOf(TStartupInfo));
  ZeroMemory(@SA,SizeOf(TSecurityAttributes));
  SA.nLength:=sizeof(TSecurityAttributes);
  SA.lpSecurityDescriptor:=nil;
  SA.bInheritHandle:=True;
  SI.cb:=SizeOf(TStartupInfo);
  SI.dwFlags:=STARTF_USESTDHANDLES or STARTF_USESHOWWINDOW;
  CreatePipe(hReadPipe,hWritePipe,@SA,300*1024);
  SI.hStdOutput:=hWritePipe;
  SI.hStdInput:=hReadPipe;
  SI.hStdError:=hWritePipe;
  SI.wShowWindow:=SW_HIDE;
  CreateProcessW(nil,PWideChar(ACommand+' '+AParams),nil,nil,True,CREATE_NEW_CONSOLE,nil,nil,SI,PI);
  Repeat
    Application.ProcessMessages;
  until WaitForSingleObject(PI.hProcess,150)<>WAIT_TIMEOUT;
  GetExitCodeProcess(PI.hProcess,Result);
  CloseHandle(PI.hProcess);
  CloseHandle(hWritePipe);
  while ReadFile(hReadPipe,Bufor,SizeOf(Bufor),BytesRead,nil) do begin
    Bufor[BytesRead]:=#0;
    AOutPut:=AOutPut+Copy(Bufor,0,BytesRead);
    FillChar(Bufor,SizeOf(Bufor),0);
    Application.ProcessMessages;
  end;
  CloseHandle(hReadPipe);
end;

Delphi 2009 i następne nie są do końca zgodne z poprzednimi ze względu na obsługę unicode. Powyższy przykład działał na D7.

Tak kod znam. I bardzo słuszne spostrzeżenie ze zgodnością, właśnie o to chodzi.

Już mam pomysł: po prostu w Delphi 7 zrobie malutkę aplikację do portowania tego, co potrzebuje :PO Thx ;]

0
jakubkrol napisał(a)

Już mam pomysł: po prostu w Delphi 7 zrobie malutkę aplikację do portowania tego, co potrzebuje :PO Thx ;]

Spróbuj w powyższym kodzie używać ansichar wszędzie tam gdzie jest char i ansistring wszędzie tam gdzie jest string. widestringi zostaw jak są.
Powinno pomóc.

0
Azarien_ napisał(a)
jakubkrol napisał(a)

Już mam pomysł: po prostu w Delphi 7 zrobie malutkę aplikację do portowania tego, co potrzebuje :PO Thx ;]

Spróbuj w powyższym kodzie używać ansichar wszędzie tam gdzie jest char i ansistring wszędzie tam gdzie jest string. widestringi zostaw jak są.
Powinno pomóc.

Jakby to było takie proste to bym sobie poradził :D

Pojawiają się zapętlenia, brak odpowiedzi programu konsolowego lub AV...

1 użytkowników online, w tym zalogowanych: 0, gości: 1