2009-09-21 37 views
21

Necesito ejecutar un comando "buscar" de Windows desde un software Delphi. Intenté usar el comando ShellExecute, pero parece que no funciona. En C, utilizaría el procedimiento system, pero aquí ... No sé. Me gustaría hacer algo como esto:¿Cómo ejecuto un programa de línea de comandos en Delphi?

System('find "320" in.txt > out.txt'); 

Editar: Gracias por la respuesta :) yo estaba tratando de correr 'Buscar' como un ejecutable, no como argumento para cmd.exe.

+2

ShellExecute debería funcionar. ¿Qué está haciendo, o no está haciendo o lo que sea? –

Respuesta

26

Un ejemplo utilizando ShellExecute():

procedure TForm1.Button1Click(Sender: TObject); 
begin 
    ShellExecute(0, nil, 'cmd.exe', '/C find "320" in.txt > out.txt', nil, SW_HIDE); 
    Sleep(1000); 
    Memo1.Lines.LoadFromFile('out.txt'); 
end; 

Tenga en cuenta que el uso de CreateProcess() en lugar de ShellExecute() permite un mejor control del proceso.

Lo ideal es que también llame a esto en un subproceso secundario y llame al WaitForSingleObject() en el identificador de proceso para esperar a que se complete el proceso. El Sleep() en el ejemplo es solo un truco para esperar un tiempo para que el programa iniciado por ShellExecute() termine - ShellExecute() no hará eso. Si no pudiera, por ejemplo, simplemente abrir una instancia notepad para editar un archivo, ShellExecute() bloquearía su aplicación principal hasta que se cerrara el editor.

+0

¿No debería ser Memo1.Lines.LoadFromFile ('out.txt'); – IanH

+0

De hecho, gracias por detectarlo. – mghie

+0

Er, si las ventanas están ocultas (SW_HIDE), ¿por qué deberíamos poner un reposo (1000) después del ShellExecute? – gramm

12

Variant1:

Esto ejecutará un programa 'DOS' y recuperar su salida:

function GetDosOutput(CommandLine: string; Work: string = 'C:\'): string; { Run a DOS program and retrieve its output dynamically while it is running. } 
var 
    SecAtrrs: TSecurityAttributes; 
    StartupInfo: TStartupInfo; 
    ProcessInfo: TProcessInformation; 
    StdOutPipeRead, StdOutPipeWrite: THandle; 
    WasOK: Boolean; 
    pCommandLine: array[0..255] of AnsiChar; 
    BytesRead: Cardinal; 
    WorkDir: string; 
    Handle: Boolean; 
begin 
    Result := ''; 
    with SecAtrrs do begin 
    nLength := SizeOf(SecAtrrs); 
    bInheritHandle := True; 
    lpSecurityDescriptor := nil; 
    end; 
    CreatePipe(StdOutPipeRead, StdOutPipeWrite, @SecAtrrs, 0); 
    try 
    with StartupInfo do 
    begin 
     FillChar(StartupInfo, SizeOf(StartupInfo), 0); 
     cb := SizeOf(StartupInfo); 
     dwFlags := STARTF_USESHOWWINDOW or STARTF_USESTDHANDLES; 
     wShowWindow := SW_HIDE; 
     hStdInput := GetStdHandle(STD_INPUT_HANDLE); // don't redirect stdin 
     hStdOutput := StdOutPipeWrite; 
     hStdError := StdOutPipeWrite; 
    end; 
    WorkDir := Work; 
    Handle := CreateProcess(nil, PChar('cmd.exe /C ' + CommandLine), 
          nil, nil, True, 0, nil, 
          PChar(WorkDir), StartupInfo, ProcessInfo); 
    CloseHandle(StdOutPipeWrite); 
    if Handle then 
     try 
     repeat 
      WasOK := windows.ReadFile(StdOutPipeRead, pCommandLine, 255, BytesRead, nil); 
      if BytesRead > 0 then 
      begin 
      pCommandLine[BytesRead] := #0; 
      Result := Result + pCommandLine; 
      end; 
     until not WasOK or (BytesRead = 0); 
     WaitForSingleObject(ProcessInfo.hProcess, INFINITE); 
     finally 
     CloseHandle(ProcessInfo.hThread); 
     CloseHandle(ProcessInfo.hProcess); 
     end; 
    finally 
    CloseHandle(StdOutPipeRead); 
    end; 
end; 

Variante 2:

salida de la consola de captura en [en tiempo real] y cómo se en un TMemo:

procedure CaptureConsoleOutput(const ACommand, AParameters: String; AMemo: TMemo); 
const 
    CReadBuffer = 2400; 
var 
    saSecurity: TSecurityAttributes; 
    hRead: THandle; 
    hWrite: THandle; 
    suiStartup: TStartupInfo; 
    piProcess: TProcessInformation; 
    pBuffer: array[0..CReadBuffer] of AnsiChar;  <----- update 
    dRead: DWord; 
    dRunning: DWord; 
begin 
    saSecurity.nLength := SizeOf(TSecurityAttributes); 
    saSecurity.bInheritHandle := True; 
    saSecurity.lpSecurityDescriptor := nil; 

    if CreatePipe(hRead, hWrite, @saSecurity, 0) then 
    begin  
    FillChar(suiStartup, SizeOf(TStartupInfo), #0); 
    suiStartup.cb := SizeOf(TStartupInfo); 
    suiStartup.hStdInput := hRead; 
    suiStartup.hStdOutput := hWrite; 
    suiStartup.hStdError := hWrite; 
    suiStartup.dwFlags := STARTF_USESTDHANDLES or STARTF_USESHOWWINDOW;  
    suiStartup.wShowWindow := SW_HIDE; 

    if CreateProcess(nil, PChar(ACommand + ' ' + AParameters), @saSecurity, 
     @saSecurity, True, NORMAL_PRIORITY_CLASS, nil, nil, suiStartup, piProcess) 
     then 
    begin 
     repeat 
     dRunning := WaitForSingleObject(piProcess.hProcess, 100);   
     Application.ProcessMessages(); 
     repeat 
      dRead := 0; 
      ReadFile(hRead, pBuffer[0], CReadBuffer, dRead, nil);   
      pBuffer[dRead] := #0; 

      OemToAnsi(pBuffer, pBuffer); 
      AMemo.Lines.Add(String(pBuffer)); 
     until (dRead < CReadBuffer);  
     until (dRunning <> WAIT_TIMEOUT); 
     CloseHandle(piProcess.hProcess); 
     CloseHandle(piProcess.hThread);  
    end; 

    CloseHandle(hRead); 
    CloseHandle(hWrite); 
    end; 
end; 

Fuente: delphi.wikia.com

Cuestiones relacionadas