2009-09-21 4 views
21

Muszę wykonać polecenie "Znajdź" Windows z oprogramowania Delphi. Próbowałem użyć polecenia ShellExecute, ale wydaje się, że nie działa. W języku C użyłbym procedury system, ale tutaj ... Nie wiem. Chciałbym zrobić coś takiego:Jak uruchomić program wiersza poleceń w Delphi?

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

Edit: Dzięki za odpowiedź :) starałem się uruchomić „Znajdź” jako plik wykonywalny, a nie jako argumentu dla cmd.exe.

+2

Powłoka ShellExecute powinna działać. Co to jest, a czego nie robić? –

Odpowiedz

26

Przykładem korzystania 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; 

Należy pamiętać, że stosując CreateProcess() zamiast ShellExecute() pozwala na dużo lepszą kontrolę procesu.

Idealnie byłoby również wywołać to w wątku dodatkowym i wywołać WaitForSingleObject() na uchwycie procesu, aby czekać na zakończenie procesu. Sleep() w tym przykładzie jest po prostu hackem, aby poczekać, aż program zostanie uruchomiony przez ShellExecute(), aby zakończyć - ShellExecute() tego nie zrobi. Jeśli tak, nie możesz na przykład po prostu otworzyć instancji notepad do edycji pliku, zablokuje ona twoją aplikację nadrzędną do czasu zamknięcia edytora.

+0

Nie powinien to być Memo1.Lines.LoadFromFile ("out.txt"); – IanH

+0

Rzeczywiście, dzięki za spostrzeżenie. – mghie

+0

Er, jeśli okna są ukryte (SW_HIDE), dlaczego powinniśmy umieścić Sleep (1000) po ShellExecute? – gramm

12

Variant1:

Spowoduje to uruchomienie programu 'DOS' i odzyskać swoją moc:

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; 

Wariant 2:

wyjście konsola fotografowania w trybie [Realtime] i jak go w 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; 

Źródło: delphi.wikia.com