2017-04-19 7 views
-1

私は値を取得してTMemoを送る文字列に設定する方法がわからないので、常に私に値を返すcmdを持っています。 CMDの結果を得るためにスレッド - DOS出力を同期させよう

コード:

function GetDosOutput(CMD: string; Dir: string = 'C:\'): string; 
    var 
    SA: TSecurityAttributes; 
    SI: TStartupInfo; 
    PI: TProcessInformation; 
    StdOutPipeRead, StdOutPipeWrite: THandle; 
    Handle, WasOK: Boolean; 
    Buffer: array[0..255] of AnsiChar; 
    BytesRead: Cardinal; 
    utf8: UTF8String; 
begin 
    Result := ''; 
    SA.nLength := SizeOf(SA); 
    SA.bInheritHandle := True; 
    SA.lpSecurityDescriptor := nil; 
    CreatePipe(StdOutPipeRead, StdOutPipeWrite, @SA, 0); 

    try 
    FillChar(SI, SizeOf(SI), 0); 
    SI.cb := SizeOf(SI); 
    SI.dwFlags := STARTF_USESHOWWINDOW or STARTF_USESTDHANDLES; 
    SI.wShowWindow := SW_HIDE; 
    SI.hStdInput := GetStdHandle(STD_INPUT_HANDLE); 
    SI.hStdOutput := StdOutPipeWrite; 
    SI.hStdError := StdOutPipeWrite; 

    Handle := CreateProcess(nil, PChar('cmd.exe /C ' + CMD), nil, nil, True, 
    0, nil, pchar(Dir), SI, PI); 
    CloseHandle(StdOutPipeWrite); 
    if Handle then 
     try 
     repeat 
      WasOK := ReadFile(StdOutPipeRead, Buffer, 255, BytesRead, nil); 
      if BytesRead > 0 then begin 
      Buffer[BytesRead] := #0; 
      utf8:= Result + String(Buffer); 
      Result:= utf8; 
      end; 
     until not WasOK or (BytesRead = 0); 
     WaitForSingleObject(PI.hProcess, INFINITE); 
     finally 
     CloseHandle(PI.hThread); 
     CloseHandle(PI.hProcess); 
     end; 
    finally 
    CloseHandle(StdOutPipeRead); 
    end; 
end; 

を結果が更新されて停止しないよう、スレッドが終了しませんので、私はちょうどで更新する必要があり、スレッドが終了するまで待つことができませんランタイム。
シンクロナイゼーションを使用しようとしましたが動作しませんでした。どうすればいいですか?

マイコード:

type 
TThread_DOS = class(TThread) 
    private 
    FCmd: string; 
    FResult: string; 
    protected 
    procedure Execute; override; 
    public 
    Constructor Create(const cmd: string; Notify: TNotifyEvent); 
    property Result: string read FResult; 
    property CMD: string read FCmd; 
end; 

constructor TThread_DOS.Create(const cmd: string; Notify: TNotifyEvent); 
begin 
    inherited Create(false); 
    FCmd:= cmd; 
    FreeOnTerminate:= true; 
    OnTerminate:= Notify; 
end; 

procedure TThread_DOS.Execute; 
begin 
    inherited; 
    FResult:= (GetDosOutput(FCmd)); 
end; 
+0

Repeat ... UntilループにResult値を表示しますか?またはループの1回後?あなたのコードは常に(ノンストップ)結果ではありません –

+0

@M ... Mはリアルタイムで結果を得る必要があります。スレッドのOnTerminateイベントを使用することはできません。 – strykerbits

+0

イベントをOnTerminateする必要はなく、私の回答に投稿したユニットを使用してください –

答えて

1

をあなたのためのもの

あなたが検索結果を表示するために必要なすべての時間は、あなたが例えば

を同期してそれを表示することができます:それはによって結果行が表示されます

procedure TForm2.Button1Click(Sender: TObject); 
var 
MyThread : TMyThread; 
begin 
MyThread := TMyThread.Create(Memo1, 'PING 127.0.0.1', ''); 
MyThread.Start; 
end; 

unit ThreadUnit; 

interface 

Uses 
    Winapi.Windows, Winapi.Messages, System.SysUtils, System.Variants, System.Classes, 
    VCL.StdCtrls; 

type 
TMyThread = class(TThread) 
private 
    FMemo : TMemo; 
    FCMD : String; 
    FDir : String; 
public 
    constructor Create(var ResultMemo : TMemo; CMD, Dir : String); 
protected 
    procedure Execute; override; 
end; 

implementation 

{ TMyThread } 

constructor TMyThread.Create(var ResultMemo : TMemo; CMD, Dir : String); 
begin 
Inherited Create(True); 

FreeOnTerminate := True; 

FMemo := ResultMemo; 
FCMD := CMD; 

if Dir = '' then 
    FDir := 'C:\' 
else 
    FDir := Dir; 
end; 

procedure TMyThread.Execute; 
    var 
    SA: TSecurityAttributes; 
    SI: TStartupInfo; 
    PI: TProcessInformation; 
    StdOutPipeRead, StdOutPipeWrite: THandle; 
    Handle, WasOK: Boolean; 
    Buffer: array[0..255] of AnsiChar; 
    BytesRead: Cardinal; 
    utf8: UTF8String; 

    Result : String; 
begin 
    Result := ''; 
    SA.nLength := SizeOf(SA); 
    SA.bInheritHandle := True; 
    SA.lpSecurityDescriptor := nil; 
    CreatePipe(StdOutPipeRead, StdOutPipeWrite, @SA, 0); 

    try 
    FillChar(SI, SizeOf(SI), 0); 
    SI.cb := SizeOf(SI); 
    SI.dwFlags := STARTF_USESHOWWINDOW or STARTF_USESTDHANDLES; 
    SI.wShowWindow := SW_HIDE; 
    SI.hStdInput := GetStdHandle(STD_INPUT_HANDLE); 
    SI.hStdOutput := StdOutPipeWrite; 
    SI.hStdError := StdOutPipeWrite; 

    Handle := CreateProcess(nil, PChar('cmd.exe /C ' + FCMD), nil, nil, True, 
    0, nil, pchar(FDir), SI, PI); 
    CloseHandle(StdOutPipeWrite); 
    if Handle then 
     try 
     repeat 
      WasOK := ReadFile(StdOutPipeRead, Buffer, 255, BytesRead, nil); 
      if BytesRead > 0 then begin 
      Buffer[BytesRead] := #0; 
      utf8:= Result + String(Buffer); 
      Result:= utf8; 

      Synchronize(procedure 
         begin 
          FMemo.Lines.Add(Result); 
         end); 
      end; 
     until not WasOK or (BytesRead = 0); 
     WaitForSingleObject(PI.hProcess, INFINITE); 
     finally 
     CloseHandle(PI.hThread); 
     CloseHandle(PI.hProcess); 
     end; 
    finally 
    CloseHandle(StdOutPipeRead); 
    end; 
end; 

end. 

このように、このスレッドを使用しますメモを凍らせないでメモを書き直してください。

コンストラクタと同期化の仕組み...

0

https://github.com/TurboPack/DOSCommand 使用例メモしてください:のTThreadクラスを作成し、それにTMemoオブジェクトとあなたのパラメータを渡し、それをやらせ

procedure TForm1.DosCommand1NewLine(ASender: TObject; const ANewLine: string; 
    AOutputType: TOutputType); 
begin 
    case AOutputType of 
    otEntireLine: 
     Memo1.Lines.Add(ANewLine); 
    end; 
end; 

http://www.gesource.jp/weblog/?p=7483