求调用外部程序及判断其完成的方法 !急 (10分)

  • 主题发起人 主题发起人 admini
  • 开始时间 开始时间
A

admini

Unregistered / Unconfirmed
GUEST, unregistred user!
我想调用外部程序dat2mpg.exe自动把.DAT转为mpg格式,要等dat2mpg.exe转换完了这个文件后才执行下一条指令。<br><br>请教各位大哥 &nbsp;<br>
 
function WinExecAndWait32(FileName: string; Visibility: Integer): Integer;<br>var<br>&nbsp; zAppName: array[0..512] of Char;<br>&nbsp; zCurDir: array[0..255] of Char;<br>&nbsp; WorkDir: string;<br><br>&nbsp; StartupInfo: TStartupInfo;<br>&nbsp; ProcessInfo: TProcessInformation;<br>&nbsp; Status: DWord;<br>begin<br>&nbsp; StrPCopy(zAppName, FileName);<br>&nbsp; GetDir(0, WorkDir);<br>&nbsp; StrPCopy(zCurDir, WorkDir);<br>&nbsp; FillChar(StartupInfo, Sizeof(StartupInfo), #0);<br>&nbsp; StartupInfo.cb := Sizeof(StartupInfo);<br>&nbsp; StartupInfo.dwFlags := StartF_UseShowWindow;<br>&nbsp; StartupInfo.wShowWindow := Visibility;<br>&nbsp; if not CreateProcess(nil,<br>&nbsp; &nbsp; zAppName, { pointer to command line string }<br>&nbsp; &nbsp; nil, { pointer to process security attributes }<br>&nbsp; &nbsp; nil, { pointer to thread security attributes }<br>&nbsp; &nbsp; False, { handle inheritance flag }<br>&nbsp; &nbsp; Create_New_Console or { creation flags }<br>&nbsp; &nbsp; Normal_Priority_Class,<br>&nbsp; &nbsp; nil, { pointer to new environment block }<br>&nbsp; &nbsp; nil, { pointer to current directory name }<br>&nbsp; &nbsp; StartupInfo, { pointer to STARTUPINFO }<br>&nbsp; &nbsp; ProcessInfo) then<br>&nbsp; &nbsp; Result := -1 { pointer to PROCESS_INF }<br>&nbsp; else<br>&nbsp; begin<br>&nbsp; &nbsp; WaitforSingleObject(ProcessInfo.hProcess, Infinite);<br>&nbsp; &nbsp; GetExitCodeProcess(ProcessInfo.hProcess, Status);<br>&nbsp; &nbsp; Result := Status;<br>&nbsp; end; //else<br>end;
 
Waiting till an application ends<br>WaitForSingleObject<br><br>If we ever need to run an external application and wait until it terminates, then we would have to do without ShellExecute and resort to more basic functions, like CreateProcess, WaitForSingleObject and CloseHandle.<br><br>uses Forms, Windows;<br><br>procedure TForm1.Button1Click(Sender: TObject);<br>var<br>&nbsp; proc_info: TProcessInformation;<br>&nbsp; startinfo: TStartupInfo;<br>&nbsp; ExitCode: longword;<br>begin<br>&nbsp; // Initialize the structures<br>&nbsp; FillChar(proc_info, sizeof(TProcessInformation), 0);<br>&nbsp; FillChar(startinfo, sizeof(TStartupInfo), 0);<br>&nbsp; startinfo.cb := sizeof(TStartupInfo);<br><br>&nbsp; // Attempts to create the process<br>&nbsp; if CreateProcess('c:/windows/notepad.exe', nil, nil,<br>&nbsp; &nbsp; &nbsp; nil, false, NORMAL_PRIORITY_CLASS, nil, nil,<br>&nbsp; &nbsp; &nbsp; &nbsp;startinfo, proc_info) &lt;&gt; False then begin<br>&nbsp; &nbsp; // The process has been successfully created<br>&nbsp; &nbsp; // No let's wait till it ends...<br>&nbsp; &nbsp; WaitForSingleObject(proc_info.hProcess, INFINITE);<br>&nbsp; &nbsp; // Process has finished. Now we should close it.<br>&nbsp; &nbsp; GetExitCodeProcess(proc_info.hProcess, ExitCode); &nbsp;// Optional<br>&nbsp; &nbsp; CloseHandle(proc_info.hThread);<br>&nbsp; &nbsp; CloseHandle(proc_info.hProcess);<br>&nbsp; &nbsp; Application.MessageBox(<br>&nbsp; &nbsp; &nbsp; PChar(Format('Notepad finished! (Exit code=%d)', [ExitCode])),<br>&nbsp; &nbsp; &nbsp; 'Info', MB_ICONINFORMATION);<br>&nbsp; end else begin<br>&nbsp; &nbsp; // Failure creating the process<br>&nbsp; &nbsp; Application.MessageBox('Couldn''t execute the '<br>&nbsp; &nbsp; &nbsp; + 'application', 'Error', MB_ICONEXCLAMATION);<br>&nbsp; end;//if<br>end;<br>Problems<br><br>We have experienced problems with WaitForSingleObject in combination with certain applications and we had to finish them with the task manager. Other applications apparently fail to finish correctly and WaitForSingleObject never returns. Appart from that, an application does not respond to events while it waits and this means that for example the forms won't repaint...<br><br>A possible workaround to these problems is checking the status of the launched application (calling GetExitCodeProcess) at intervals (in a timer event).<br><br>uses Forms, Windows, StdCtrls, ExtCtrls;<br><br>type<br>TForm1 = class(TForm)<br>&nbsp; btnExecute: TButton;<br>&nbsp; btnCancel: TButton;<br>&nbsp; Timer1: TTimer;<br>&nbsp; procedure FormCreate(Sender: TObject);<br>&nbsp; procedure btnExecuteClick(Sender: TObject);<br>&nbsp; procedure Timer1Timer(Sender: TObject);<br>&nbsp; procedure btnCancelClick(Sender: TObject);<br>&nbsp; procedure FormCloseQuery(Sender: TObject;<br>&nbsp; &nbsp; var CanClose: Boolean);<br>private<br>&nbsp; proc_info: TProcessInformation;<br>&nbsp; startinfo: TStartupInfo;<br>&nbsp; ExitCode: LongWord;<br>end;<br><br>implementation<br><br>procedure TForm1.FormCreate(Sender: TObject);<br>begin<br>&nbsp; btnCancel.Enabled := False;<br>&nbsp; Timer1.Enabled := False;<br>&nbsp; Timer1.Interval := 200;<br>end;<br><br>procedure TForm1.btnExecuteClick(Sender: TObject);<br>begin<br>&nbsp; FillChar(proc_info, sizeof(TProcessInformation), 0);<br>&nbsp; FillChar(startinfo, sizeof(TStartupInfo), 0);<br>&nbsp; startinfo.cb := sizeof(TStartupInfo);<br>&nbsp; if CreateProcess(nil, 'c:/windows/notepad.exe', nil,<br>&nbsp; &nbsp; &nbsp; nil, false, CREATE_DEFAULT_ERROR_MODE<br>&nbsp; &nbsp; &nbsp; + NORMAL_PRIORITY_CLASS, nil, nil, startinfo,<br>&nbsp; &nbsp; &nbsp; proc_info) then begin<br>&nbsp; &nbsp; btnExecute.Enabled := False;<br>&nbsp; &nbsp; btnCancel.Enabled := True;<br>&nbsp; &nbsp; Timer1.Enabled := True;<br>&nbsp; end else begin<br>&nbsp; &nbsp; CloseHandle(proc_info.hProcess);<br>&nbsp; &nbsp; Application.MessageBox('Couldn''t execute the '<br>&nbsp; &nbsp; &nbsp; + 'application', 'Error', MB_ICONEXCLAMATION);<br>&nbsp; end;<br>end;<br><br>procedure TForm1.Timer1Timer(Sender: TObject);<br>begin<br>&nbsp; Timer1.Enabled := False;<br>&nbsp; if GetExitCodeProcess(proc_info.hProcess, ExitCode)<br>&nbsp; then<br>&nbsp; &nbsp; if ExitCode = STILL_ACTIVE then<br>&nbsp; &nbsp; &nbsp; Timer1.Enabled := True<br>&nbsp; &nbsp; else begin<br>&nbsp; &nbsp; &nbsp; btnCancel.Enabled := False;<br>&nbsp; &nbsp; &nbsp; btnExecute.Enabled := True;<br>&nbsp; &nbsp; &nbsp; CloseHandle(proc_info.hProcess);<br>&nbsp; &nbsp; end<br>&nbsp; else begin<br>&nbsp; &nbsp; btnCancel.Enabled := False;<br>&nbsp; &nbsp; btnExecute.Enabled := True;<br>&nbsp; &nbsp; TerminateProcess(proc_info.hProcess, 0);<br>&nbsp; &nbsp; CloseHandle(proc_info.hProcess);<br>&nbsp; end;<br>end;<br><br>procedure TForm1.btnCancelClick(Sender: TObject);<br>begin<br>&nbsp; Timer1.Enabled := False;<br>&nbsp; if Application.MessageBox('You should try to finish'<br>&nbsp; + ' the application normally.'#13#13'&amp;iquest;Terminate it '<br>&nbsp; + 'anyway?', 'Warning', MB_YESNO + MB_DEFBUTTON2 +<br>&nbsp; MB_ICONQUESTION + MB_TASKMODAL) = ID_YES then begin<br>&nbsp; &nbsp; TerminateProcess(proc_info.hProcess, 0);<br>&nbsp; &nbsp; CloseHandle(proc_info.hProcess);<br>&nbsp; &nbsp; btnCancel.Enabled := False;<br>&nbsp; &nbsp; btnExecute.Enabled := True;<br>&nbsp; end else begin<br>&nbsp; &nbsp; Timer1.Enabled := True;<br>&nbsp; end;<br>end;<br><br>procedure TForm1.FormCloseQuery(Sender: TObject;<br>&nbsp; var CanClose: Boolean);<br>begin<br>&nbsp; if btnCancel.Enabled then begin<br>&nbsp; &nbsp; btnCancelClick(Sender);<br>&nbsp; &nbsp; if btnCancel.Enabled then CanClose := False;<br>&nbsp; end;<br>end;<br>
 

Similar threads

S
回复
0
查看
3K
SUNSTONE的Delphi笔记
S
S
回复
0
查看
2K
SUNSTONE的Delphi笔记
S
D
回复
0
查看
1K
DelphiTeacher的专栏
D
D
回复
0
查看
1K
DelphiTeacher的专栏
D
后退
顶部