Foros Club Delphi

Foros Club Delphi (https://www.clubdelphi.com/foros/index.php)
-   API de Windows (https://www.clubdelphi.com/foros/forumdisplay.php?f=7)
-   -   Ejecutando aplicaciones DOS (https://www.clubdelphi.com/foros/showthread.php?t=65010)

aeff 15-11-2009 19:01:59

Ejecutando aplicaciones DOS
 
Saludos colegas:

Sucede que en el Trucomanía existe algún truco para ejecutar una aplicación DOS e imprimir el contexto de este en un TMemo, bueno, he leido este truco y me a servido de mucho pero ahora se me presenta un gran problema, consiste en que en algunas aplicaciones DOS se requieren entradas de datos y con el truco del que hablo no veo forma algua de enviarle al programa DOS la "cadena de caracteres" o los datos que piden.

Espero que me puedan ayudar. Mil gracias de antemano.
Saludos. AEFF!!!

escafandra 15-11-2009 23:47:45

Hola aeff. Imagino que te refieres a GetDosOutput, en el foro existen algunas referencias a ese código.

Supongo que si abres una consola "cmd.exe" y le asignas el parent a tu ventana, la impresión es que se ejecuta desde tu programa. Bueno, la idea es que en el código anterior podemos leer:
Código Delphi [-]
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); // don't redirect std input
      hStdOutput := StdOutPipeWrite;
      hStdError := StdOutPipeWrite;
    end;

Si en lugar de ejecutar la consola oculta la ejecutamos SW_NORMAL, podemos ver la consola, interactuar con ella y recuperar el contenido en un String.

No lo he probado, pero puede ser una línea de investigación a seguir.:D

Saludos.

aeff 16-11-2009 16:21:42

Saludos colega, bueno, no puedo alcanzar el link que me recomiendas: GetDosOutput, por algunas razones, pero he intentando hacer algo y se me ocurrió hacer lo siguiente:

Código Delphi [-]
program Project1;
{$APPTYPE CONSOLE}
uses
  Windows,
  SysUtils;

var
  vSA: TSecurityAttributes;
  vSI: TStartupInfo;
  vPI: TProcessInformation;
begin
  // Imprimimos un texto para adornar el programa...
  SetConsoleTextAttribute(GetStdHandle(STD_OUTPUT_HANDLE), FOREGROUND_GREEN);
  WriteLn('[Consola AEFF]');
  WriteLn('Presione una tecla para ejecutar el comando LABEL en esta consola.');
  SetConsoleTextAttribute(GetStdHandle(STD_OUTPUT_HANDLE), FOREGROUND_INTENSITY);
  ReadLn;

  {*** Aqui comienza la fiesta}

  // Registro para el Atributo de Seguridad
  vSA.nLength               := SizeOf(TSecurityAttributes);
  vSA.lpSecurityDescriptor  := nil;
  vSA.bInheritHandle        := true;

  // Registro para la Información de Inicio del Proceso
  FillChar(vSI, SizeOf(TStartupInfo), #0);
  vSI.cb      := SizeOf(TStartupInfo);
  vSI.dwFlags := STARTF_USESTDHANDLES;
  vSI.hStdInput   := GetStdHandle(STD_INPUT_HANDLE);
  vSI.hStdOutput  := GetStdHandle(STD_OUTPUT_HANDLE);

  // Creamos el proceso
  CreateProcess(Nil, 'help', @vSA, @vSA, true, 0, Nil, Nil, vSI, vPI);

  ReadLn;
end.

pero ahora el problema es ¿como puedo leer los datos de la consola? y en un momento dado como puedo dar entrada de los datos a través de algún codigo sin tener que hacerlo via teclado.

espero que me puedan ayudar, mil gracias nuevamente.
aeff!

escafandra 16-11-2009 17:47:39

Cita:

Empezado por aeff (Mensaje 346664)
...no puedo alcanzar el link que me recomiendas: GetDosOutput, por algunas razones...

Código Delphi [-]
  
unit consoleoutput;

interface

uses
  Controls, Windows, SysUtils, Forms;

function GetDosOutput(CommandLine:string): string;
function ExecuteDOSCommand(CommandLine:string): string;

//---------------------------------------------------------------------------
implementation
//---------------------------------------------------------------------------

//---------------------------------------------------------------------------
// Ejecuta y devuelve el resultado de un comando DOS o de consola
// sin usar la ruta específica del mismo
// No se pueden ejecutar procesos que no sean del S.O.
function ExecuteDOSCommand(CommandLine:string): string;
var
  cmdbuffer: Array [0..MAX_PATH] of Char;

begin
  GetEnvironmentVariable( 'COMSPEC', cmdBUffer, Sizeof(cmdBuffer));
  CommandLine := cmdbuffer + ' /C ' + CommandLine;
//  Result := (CommandLine);
  Result := GetDosOutput(CommandLine);
end;

//---------------------------------------------------------------------------
// Ejecuta y devuelve el resultado de un proceso por linea de comandoso de consola
// Necesita la ruta especifica del proceso
function GetDosOutput(CommandLine:string): string;
var
  SA: TSecurityAttributes;
  SI: TStartupInfo;
  PI: TProcessInformation;
  StdOutPipeRead, StdOutPipeWrite: THandle;
  WasOK: Boolean;
  Buffer: array[0..255] of Char;
  BytesRead: Cardinal;
  WorkDir, Line: String;
begin
  Application.ProcessMessages;
  with SA do
  begin
    nLength := SizeOf(SA);
    bInheritHandle := True;
    lpSecurityDescriptor := nil;
  end;
  // create pipe for standard output redirection
  CreatePipe(StdOutPipeRead,  // read handle
             StdOutPipeWrite, // write handle
             @SA,             // security attributes
             0                // number of bytes reserved for pipe - 0 default
             );
  try
    // Make child process use StdOutPipeWrite as standard out,
    // and make sure it does not show on screen.
    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); // don't redirect std input
      hStdOutput := StdOutPipeWrite;
      hStdError := StdOutPipeWrite;
    end;

    // launch the command line compiler
    WorkDir := ExtractFilePath(CommandLine);
    WasOK := CreateProcess(nil, PChar(CommandLine), nil, nil, True, 0, nil, PChar(WorkDir), SI, PI);

    // Now that the handle has been inherited, close write to be safe.
    // We don't want to read or write to it accidentally.
    CloseHandle(StdOutPipeWrite);
    // if process could be created then handle its output
    if not WasOK then
      raise Exception.Create('Could not execute command line!')
    else
      try
        // get all output until dos app finishes
        Line := '';
        repeat
          // read block of characters (might contain carriage returns and line feeds)
          WasOK := ReadFile(StdOutPipeRead, Buffer, 255, BytesRead, nil);

          // has anything been read?
          if BytesRead > 0 then
          begin
            // finish buffer to PChar
            Buffer[BytesRead] := #0;
            // combine the buffer with the rest of the last run
            Line := Line + Buffer;
          end;
        until not WasOK or (BytesRead = 0);
        // wait for console app to finish (should be already at this point)
        WaitForSingleObject(PI.hProcess, INFINITE);
      finally
        // Close all remaining handles
        CloseHandle(PI.hThread);
        CloseHandle(PI.hProcess);
      end;
  finally
      result:=Line;
      CloseHandle(StdOutPipeRead);
  end;
end;


end.

Cita:

Empezado por aeff (Mensaje 346664)
... pero ahora el problema es ¿como puedo leer los datos de la consola? y en un momento dado como puedo dar entrada de los datos a través de algún codigo sin tener que hacerlo via teclado...

Puedes mandar las teclas a cualquier ventana, por ejemplo puedes utilizar el evento OnKeyPress para aprovechar y mandar un mensaje a la ventana de la consola abierta:

Código Delphi [-]
 PostMessage(Handle_Consloa, WM_CHAR, Key, 0);

Saludos.


La franja horaria es GMT +2. Ahora son las 06:01:28.

Powered by vBulletin® Version 3.6.8
Copyright ©2000 - 2024, Jelsoft Enterprises Ltd.
Traducción al castellano por el equipo de moderadores del Club Delphi