2013-06-27 33 views
7

Vì vậy, tôi đã tạo một biểu mẫu trong Delphi cho phép tôi chạy các tập lệnh sikuli khác nhau với các cấu hình khác nhau. Những gì tôi đang làm bây giờ là làm cho nó có thể cho một ai đó sử dụng biểu mẫu, để thiết lập các tập lệnh sikuli khác nhau để chạy trên một tập lệnh khác. Như trong:Làm cách nào để đợi cho đến khi quá trình bên ngoài hoàn tất?

Bước 1: SikuliScript1 với ConfigFile1. Bước 2: SikuliScript2 với ConfigFile2. vv ... Đây là mã của tôi cho đến nay:

procedure TSikRunForm.btnRunClick(Sender: TObject); 
begin 
    DirCombo:= '/C '+DirSik+'\sikuli-script.cmd' +' -r ' + DirScript + ' --args '+DirConfig; 
    if SikFound then begin 
     ShellExecute(Handle, nil, 'cmd.exe', pChar(DirCombo), nil, SW_SHOWNORMAL); 
     Application.minimize; 
    end else begin 
     ShowMessage('Select the correct folder for your Sikuli installation folder'); 
    end; 
end; 

Và điều này làm việc hoàn hảo, kịch bản sikuli chạy một cách hoàn hảo, và trong khi chạy, dòng cmd có thể nhìn thấy với những hành động khác nhau chỉ ra rằng đang được thực hiện. Sau khi tập lệnh sikuli được thực hiện, dòng cmd tự đóng lại. Vì vậy, trình xử lý shell biết khi nào tắt quá trình chạy. Vì vậy, câu hỏi của tôi là: Có thể nói với delphi: Sau khi xử lý đã đóng cửa quá trình, chạy quá trình tiếp theo (Sikuli Script)? Bây giờ tôi biết tôi có thể đi với toàn bộ createProcess trong delphi, nhưng nó chỉ có vẻ quá mức cần thiết. Đã có một cách để làm điều này nhanh hơn và dễ dàng hơn. Bất cứ ai cũng có một đầu mối?

Trả lời

19

Với CreateProcess, bạn có thể xử lý quy trình và với WaitForSingleObject bạn có thể kiểm tra khi quá trình hoàn tất. tôi sử dụng hàm sau, này chạy lệnh ở chế độ nền:

procedure ExecuteAndWait(const aCommando: string); 
var 
    tmpStartupInfo: TStartupInfo; 
    tmpProcessInformation: TProcessInformation; 
    tmpProgram: String; 
begin 
    tmpProgram := trim(aCommando); 
    FillChar(tmpStartupInfo, SizeOf(tmpStartupInfo), 0); 
    with tmpStartupInfo do 
    begin 
    cb := SizeOf(TStartupInfo); 
    wShowWindow := SW_HIDE; 
    end; 

    if CreateProcess(nil, pchar(tmpProgram), nil, nil, true, CREATE_NO_WINDOW, 
    nil, nil, tmpStartupInfo, tmpProcessInformation) then 
    begin 
    // loop every 10 ms 
    while WaitForSingleObject(tmpProcessInformation.hProcess, 10) > 0 do 
    begin 
     Application.ProcessMessages; 
    end; 
    CloseHandle(tmpProcessInformation.hProcess); 
    CloseHandle(tmpProcessInformation.hThread); 
    end 
    else 
    begin 
    RaiseLastOSError; 
    end; 
end; 
+0

Nếu bạn muốn bơm hàng đợi, hãy sử dụng 'MsgWaitForMultipleObjects' tốt hơn. Ngoài ra, bạn đang bị rò rỉ xử lý. Hai cho mọi cuộc gọi đến hàm đó. –

+0

Tại sao lại là downvote? – OnTheFly

+0

@DavidHeffernan Tại sao lại là downvote? Bạn đúng về các tay cầm (xấu của tôi) nhưng nó đưa ra một giải pháp cho câu hỏi, chạy một tiến trình sau cái kia. –

5

Bạn cần phải chờ cho đến khi xử lý xử lý được báo hiệu. Ví dụ bằng một cuộc gọi đến WaitForSingleObject. Rõ ràng CreateProcess trả về cho bạn một quá trình xử lý mà bạn có thể chờ đợi. Bạn không thể thuyết phục ShellExecute trả về một trình xử lý, nhưng người anh em ShellExecuteEx có khả năng hơn sẽ làm như vậy.

Tuy nhiên, cá nhân tôi sẽ chọn CreateProcess tại đây. Bạn sẽ nhận được sự linh hoạt và kiểm soát nhiều hơn, và nó không phức tạp. Ví dụ: bạn có thể chặn hiển thị cửa sổ bảng điều khiển nếu muốn.

0

Đây là một hack và cách ít phức tạp, nhưng có lẽ bạn chỉ có thể tạo ra một file * .bat chứa các cuộc gọi đến các kịch bản, nếu cần thiết bằng cách sử dụng "start/wait" trên mỗi dòng.

1

Ok tôi đã xem xét kỹ hơn điều này và đã giải quyết nó, giống như David đã đề xuất. Tôi sẽ hiển thị những gì tôi đã làm, nếu bất kỳ ai khác có một số câu hỏi hoặc bất cứ điều gì:

procedure TSikRunForm.btnRunClick(Sender: TObject); 
begin 
CmdLine:= 'C:\\windows\\system32\\cmd.exe'; 
uniqueString(CmdLine); 
if SikFound then begin 
    //----------For loop--------------- 
    DirScript:= TScriptEdit.Text; 
    DirConfig:= TConfEdit.Text; 
    DirCombo:= '/C '+DirSik+'\sikuli-script.cmd' +' -r ' + DirScript + ' --args '+DirConfig; 
    CreateProcess(PChar(CmdLine),PChar(DirCombo),Nil,Nil,False,CREATE_NO_WINDOW,nil,nil,StartInfo,ProcInfo); 
    procHandle:= ProcInfo.hProcess; 
    Application.minimize; 
    WaitForSingleObject(procHandle, INFINITE); 

    DirScript:= TScriptEdit2.Text; 
    DirConfig:= TConfEdit2.Text; 
    DirCombo:= '/C '+DirSik+'\sikuli-script.cmd' +' -r ' + DirScript + ' --args '+DirConfig; 
    CreateProcess(PChar(CmdLine),PChar(DirCombo),Nil,Nil,False,CREATE_NO_WINDOW,nil,nil,StartInfo,ProcInfo); 
    procHandle:= ProcInfo.hProcess; 
    Application.minimize; 
    WaitForSingleObject(procHandle, INFINITE); 
    //---------------------------------------- 
    showMessage('Gedoan'); 
end else begin 
    ShowMessage('Select the correct folder for your Sikuli installation folder'); 
end; 
end; 

Hoạt động chính xác như tôi muốn. Hai script sikuli sẽ chạy cái khác.

Các vấn đề liên quan