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

[Delphi/Pipes] Wysyłanie ciągu znaków i pobieranie odpowiedz
jakubkrol
  • Rejestracja: dni
  • Ostatnio: dni
  • Postów: 81
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.

Patryk27
  • Rejestracja: dni
  • Ostatnio: dni
  • Lokalizacja: Wrocław
  • Postów: 13042
0

Jest napisana w C

To dlaczego jest w dziale Delphi ?

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

Czyli jakie ?

jakubkrol
  • Rejestracja: dni
  • Ostatnio: dni
  • Postów: 81
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...

Misiekd
  • Rejestracja: dni
  • Ostatnio: dni
  • Postów: 7923
0

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

jakubkrol
  • Rejestracja: dni
  • Ostatnio: dni
  • Postów: 81
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

cimak
  • Rejestracja: dni
  • Ostatnio: dni
  • Postów: 1668
0

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

jakubkrol
  • Rejestracja: dni
  • Ostatnio: dni
  • Postów: 81
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).

Azarien
  • Rejestracja: dni
  • Ostatnio: dni
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ć.

Kopiuj
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.

jakubkrol
  • Rejestracja: dni
  • Ostatnio: dni
  • Postów: 81
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ć.

Kopiuj
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 ;]

  • Rejestracja: dni
  • Ostatnio: dni
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.

jakubkrol
  • Rejestracja: dni
  • Ostatnio: dni
  • Postów: 81
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...

Zarejestruj się i dołącz do największej społeczności programistów w Polsce.

Otrzymaj wsparcie, dziel się wiedzą i rozwijaj swoje umiejętności z najlepszymi.