Ir al contenido


Foto

Interactuar desde una aplicacion VCL con una en consola


  • Por favor identifícate para responder
9 respuestas en este tema

#1 Dante

Dante

    Advanced Member

  • Miembros
  • PipPipPip
  • 89 mensajes

Escrito 07 abril 2017 - 11:51

Hola, me a surgido un problema, pues tengo una aplicación en modo consola hecha en c# para tirarle fotos a los juegos con la cual necesito interactuar desde una en VCL, ya e visto que hay temas que hablan de obtener el resultado en pantalla de las consolas pero necesito tambien introducirle los datos, este es el ejemplo de su funcionamiento.

 

1- Ejecuto la consola con la ID del Juego

2- Esta lo inyecta y se queda esperando a yo le intrudisca x valor apara tirar la foto

3- Al tirar la foto me da los resultados y la dirccion en la cual la guardo lo cual tengo q obtener desde la app en VCL

4- Buelbe a estar a la espera a q le le intrudisca x valor apara tirar la foto o la mande a cerrar

 

 


  • 0

#2 escafandra

escafandra

    Advanced Member

  • Administrador
  • 4.107 mensajes
  • LocationMadrid - España

Escrito 07 abril 2017 - 12:20

Sigue este hilo, quizás la respuesta que más te interesa está a partir del mensaje 6

 

Saludos.


  • 0

#3 Dante

Dante

    Advanced Member

  • Miembros
  • PipPipPip
  • 89 mensajes

Escrito 07 abril 2017 - 02:51

Eso es lo que nesesito pero no doy pie con el modo de cambiarle que ejecute mi aplicacion en ves de cmd.exe

a mi parecer la cosa es aki


delphi
  1. GetEnvironmentVariableA('COMSPEC', Buffer, BUFFERSIZE - 1);
  2. // Ejecutamos el shell
  3.  
  4. if CreateProcess(nil, pchar(String(Buffer)), nil, nil, TRUE, CREATE_NEW_CONSOLE, nil, nil, si, pi) then
  5. begin
  6. hProcess:= pi.hProcess;
  7. CloseHandle(pi.hThread);
  8. end;

tuve que cambiar las converciones de Buffer porque estoy trabajando con Berlin


  • 0

#4 escafandra

escafandra

    Advanced Member

  • Administrador
  • 4.107 mensajes
  • LocationMadrid - España

Escrito 07 abril 2017 - 04:32

Para ejecutar un programa de consola y capturar el resultado debes ejecutar una consola, aunque sea invisible. la conversación se captura mediante los pipes. He modificado el código para que compile en Berlin:


delphi
  1. unit PipeShell3;
  2.  
  3.  
  4. interface
  5.  
  6. uses
  7. Windows, Messages, SysUtils, Classes;
  8.  
  9. const
  10. BUFFERSIZE = 4*1024;
  11.  
  12. type
  13. TPipeShell = class
  14. private
  15. PipeIn, PipeOut, PipeWrite, PipeRead: THANDLE;
  16. hProcess: THANDLE;
  17. Buffer: PAnsiChar;
  18. protected
  19. public
  20. constructor Create;
  21. destructor Destroy; override;
  22. function Write(S: AnsiString): DWORD;
  23. function Read: AnsiString;
  24. end;
  25.  
  26. implementation
  27.  
  28. constructor TPipeShell.Create;
  29. var
  30. sd: SECURITY_DESCRIPTOR;
  31. sa: SECURITY_ATTRIBUTES;
  32. si: STARTUPINFOA;
  33. pi: PROCESS_INFORMATION;
  34. begin
  35. PipeIn:= 0;
  36. PipeOut:= 0;
  37. PipeWrite:= 0;
  38. PipeRead:= 0;
  39. hProcess:= 0;
  40.  
  41. GetMem(Buffer, BUFFERSIZE);
  42. InitializeSecurityDescriptor(@sd, SECURITY_DESCRIPTOR_REVISION);
  43. sa.lpSecurityDescriptor:= @sd;
  44. // sa.lpSecurityDescriptor:= nil;
  45. sa.nLength:= sizeof(SECURITY_ATTRIBUTES);
  46. sa.bInheritHandle:= TRUE;
  47. // Tuberia de entrada
  48. if CreatePipe(PipeIn, PipeWrite, @sa, 0) then
  49. begin
  50. // Tuberia de salida
  51. if CreatePipe(PipeRead, PipeOut, @sa, 0) then
  52. begin
  53. GetStartupInfoA(Si);
  54. // Indicamos tuberias del proceso
  55. si.hStdOutput:= PipeOut;
  56. si.hStdError:= PipeOut;
  57. si.hStdInput:= PipeIn;
  58. si.dwFlags:= STARTF_USESTDHANDLES or STARTF_USESHOWWINDOW;
  59. si.wShowWindow:= SW_HIDE;
  60. //si.wShowWindow:= SW_SHOW;
  61. // Ruta del shell
  62. ZeroMemory(Buffer, BUFFERSIZE);
  63. GetEnvironmentVariableA('COMSPEC', Buffer, BUFFERSIZE - 1);
  64. // Ejecutamos el shell
  65. if CreateProcessA(nil, Buffer, nil, nil, TRUE, CREATE_NEW_CONSOLE, nil, nil, si, pi) then
  66. begin
  67. hProcess:= pi.hProcess;
  68. CloseHandle(pi.hThread);
  69. end;
  70. end;
  71. end;
  72. end;
  73.  
  74. destructor TPipeShell.Destroy;
  75. var
  76. ExitCode: DWORD;
  77. begin
  78. // Tratamos de terminar el shell
  79. repeat
  80. Write('quit'); Read;
  81. Write('q'); Read;
  82. Write('exit'); Read;
  83. GetExitCodeProcess(hProcess, ExitCode);
  84. until ExitCode <> STILL_ACTIVE;
  85.  
  86. if PipeIn <> 0 then CloseHandle(PipeIn);
  87. if PipeOut <> 0 then CloseHandle(PipeOut);
  88. if PipeWrite <> 0 then CloseHandle(PipeWrite);
  89. if PipeRead <> 0 then CloseHandle(PipeRead);
  90. if hProcess <> 0 then CloseHandle(hProcess);
  91. if Buffer <> nil then FreeMem(Buffer);
  92. if WaitForSingleObject(hProcess, 9000) <> WAIT_OBJECT_0 then
  93. TerminateProcess(hProcess, DWORD(-1));
  94. //GetExitCodeProcess(hProcess, ExitCode);
  95. //inherited;
  96. end;
  97.  
  98. function TPipeShell.Write(S: AnsiString): DWORD;
  99. begin
  100. if PipeWrite = 0 then exit;
  101. lstrcpyA(Buffer, PAnsiCHAR(S + #10));
  102. WriteFile(PipeWrite, Buffer^, lstrlenA(Buffer), Result, nil);
  103. end;
  104.  
  105. function TPipeShell.Read: AnsiString;
  106. var
  107. dwRead, dwBytesAvail: DWORD;
  108. begin
  109. if PipeRead = 0 then exit;
  110.  
  111. dwRead:= 0;
  112. // Esperamos a que tengamos algo que leer en PipeRead
  113. repeat
  114. sleep(100);
  115. PeekNamedPipe(PipeRead, Buffer, BUFFERSIZE, @dwRead, @dwBytesAvail, nil);
  116. if dwRead > 0 then
  117. begin
  118. // Leemos y vaciamos el PipeRead
  119. ZeroMemory(Buffer, BUFFERSIZE);
  120. ReadFile(PipeRead, Buffer^, dwRead, PDWORD(0)^, nil);
  121. OemToCharBuffA(Buffer, Buffer, dwRead);
  122. Result:= Result + AnsiString(Buffer);
  123. end;
  124. until dwBytesAvail = 0;
  125. end;
  126.  
  127. end.

He elegido la versión no unicode porque simplifica el uso de la API OemToCharBuff.

 

El ejemplo que ponía en el hilo original muestra como capturar la salida mientras el programa se ejecuta en una consola que no se destruye hasta el final, con lo que el programa original continua vivo. La captura se realizaba en un TMemo pero se puede prescindir de él.

 

 

Saludos.


  • 0

#5 egostar

egostar

    missing my father, I love my mother.

  • Administrador
  • 14.446 mensajes
  • LocationMéxico

Escrito 03 septiembre 2019 - 04:59

Hola amigo Escafandra,

 

Éste código es únicamente para comandos DOS ¿verdad?, intenté ejecutar una aplicación de consola y no obtiene nada. :(

 

Saludos


  • 0

#6 egostar

egostar

    missing my father, I love my mother.

  • Administrador
  • 14.446 mensajes
  • LocationMéxico

Escrito 03 septiembre 2019 - 05:35

Bruto de mi, ya vi que si funciona cualquier comando, programa que se ejecute en la consola  :)
 
Me faltaba lo principal :D
 

 

delphi
  1.   PipeShell.Write('MiApp.exe "ALGO" D:\Migraciones\ic2000_test\reposito\*.bak');
  2.   Memo1.Text:= StringReplace(PipeShell.Read, #10, #13+#10, [rfReplaceAll]);

 

 
Excelente proceso (y)
 
Saludos
  • 0

#7 escafandra

escafandra

    Advanced Member

  • Administrador
  • 4.107 mensajes
  • LocationMadrid - España

Escrito 04 septiembre 2019 - 09:33

Bruto de mi, ya vi que si funciona cualquier comando, programa que se ejecute en la consola  :)
 
Me faltaba lo principal :D
 

 


delphi
  1.   PipeShell.Write('MiApp.exe "ALGO" D:\Migraciones\ic2000_test\reposito\*.bak');
  2.   Memo1.Text:= StringReplace(PipeShell.Read, #10, #13+#10, [rfReplaceAll]);

 

 
Excelente proceso (y)
 
Saludos

 

 

 

Efectivamente, la explicación del uso la daba en otro hilo, en concreto en este mensaje. Aquel hilo fue el origen de este código y su primera versión.

 

 

Saludos.


  • 0

#8 egostar

egostar

    missing my father, I love my mother.

  • Administrador
  • 14.446 mensajes
  • LocationMéxico

Escrito 04 septiembre 2019 - 09:50

Hola amigo, estoy creando una aplicación para obtener la salida de un programa de consola pero a veces el buffer no contiene toda la salida y se corta. He cambiado de 4x104 a 8x1024 el buffer pero es lo mismo...
 
 


delphi
  1. const
  2. BUFFERSIZE = 4*1024;

 

 


delphi
  1. D:\Migraciones\ic2000\proy\ic2\pro\PagarRec.dfm:301     
  2.  
  3.  
  4.   object CtasCont
  5.  
  6.  
  7. D:\Migraciones\ic2000\proy\ic2\pro\ParamProGasEmp.dfm:453       object paramtr

 

No importa cuanto asigne siempre se queda en esa linea y después continúa...
 
Saludos


  • 0

#9 escafandra

escafandra

    Advanced Member

  • Administrador
  • 4.107 mensajes
  • LocationMadrid - España

Escrito 04 septiembre 2019 - 12:59

Hola amigo, estoy creando una aplicación para obtener la salida de un programa de consola pero a veces el buffer no contiene toda la salida y se corta. He cambiado de 4x104 a 8x1024 el buffer pero es lo mismo...
 
 


delphi
  1. const
  2. BUFFERSIZE = 4*1024;

 

 


delphi
  1. D:\Migraciones\ic2000\proy\ic2\pro\PagarRec.dfm:301     
  2.  
  3.  
  4.   object CtasCont
  5.  
  6.  
  7. D:\Migraciones\ic2000\proy\ic2\pro\ParamProGasEmp.dfm:453       object paramtr

 

No importa cuanto asigne siempre se queda en esa linea y después continúa...
 
Saludos

Mira a ver si con este cambio te funciona como deseas:


delphi
  1. function TPipeShell.Read: AnsiString;
  2. var
  3.   dwRead, dwBytesAvail: DWORD;
  4. begin
  5.   if PipeRead = 0 then exit;
  6.  
  7.   dwRead:= 0;
  8.   // Esperamos a que tengamos algo que leer en PipeRead
  9.   repeat
  10.     sleep(100);
  11.     PeekNamedPipe(PipeRead, Buffer, BUFFERSIZE-1, @dwRead, @dwBytesAvail, nil); // <<<<
  12.     if dwRead > 0 then
  13.     begin
  14.       // Leemos y vaciamos el PipeRead
  15.       ZeroMemory(Buffer, BUFFERSIZE);
  16.       ReadFile(PipeRead, Buffer^, dwRead, PDWORD(0)^, nil);
  17.       OemToCharBuffA(Buffer, Buffer, dwRead);
  18.       Result:= Result + AnsiString(Buffer);
  19.     end;
  20.   until dwBytesAvail = 0;
  21. end;

Sólo cambia en la linea marcada para usar BUFFERSIZE-1 en lugar de BUFFERSIZE. El tamaño del buffer no importa.

 

Saludos.


  • 1

#10 egostar

egostar

    missing my father, I love my mother.

  • Administrador
  • 14.446 mensajes
  • LocationMéxico

Escrito 04 septiembre 2019 - 02:33

Ya lo reviso (y)

 

Saludos


  • 0




IP.Board spam blocked by CleanTalk.