¿Cómo ejecuto un progtwig de línea de comandos en Delphi?

Necesito ejecutar un comando “find” de Windows desde un software Delphi. Intenté usar el comando ShellExecute , pero parece que no funciona. En C, usaría el procedimiento del system , pero aquí … no sé. Me gustaría hacer algo como esto:

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

Editar: Gracias por la respuesta 🙂 Estaba intentando ejecutar ‘Buscar’ como un archivo ejecutable, no como un argumento para cmd.exe.

Un ejemplo usando 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() lugar de ShellExecute() permite un mejor control del proceso.

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

Variante1:

Esto ejecutará un progtwig ‘DOS’ y recuperará su resultado:

 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:

Capture la salida de la consola en [Realtime] y cómo 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