Wolfgang Chien's Homepage | Delphi學習筆記 - 問答篇 |
達智附註: 本題有一錯誤, 請參閱「如何執行外部程式, 更正 CreateProcess 用法」
I get a component EXECFILE.DCU from SUNSITE.ICM.EDU.PL . They say this component can execute DOS/Win EXE file and wait till it finished. I want it. But I cannot install it. When I install it, I met a message : 'Cannot find module "FXMUTILS.DCU"' But they don't provide me a DCU named that.
Does anyone ever met same condition like me? I use Delphi 1.0
使用這個元件發生的問題, 找元件附的文件或直接去信問原作者可能比較容易得到解答(因為他是最清楚的人), 不是嗎?
不清楚您提到的元件, 因此我直接回答您使用這個元件的用意好了,5/6 時曾經在 tw.bbs.comp.language 中寫過以下的程式段, 應該是您要的東西:
procedure TForm1.Button1Click(Sender: TObject); var hExeHandle : THandle; begin hExeHandle := WinExec('arj.exe /?', SW_SHOWNORMAL); while GetModuleUsage(hExeHandle) <> 0 do Application.ProcessMessages; (* 您其他的程式 *) end;
這麼作事實上仍然不能'真正的'等待另一個應用程式的結束, 雖然Button 的 OnClick 事件是暫停了, 可是使用者仍然可以點其他按鈕或者在其他的控制項作任何他(她)想作的事, 因此, 上述的程式可以考慮修改成類似下列的作法:
procedure TForm1.Button1Click(Sender: TObject); var pWindowsList: pointer; hActiveWindow: HWnd; hExeHandle: THandle; begin pWindowsList := DisableTaskWindows(0); hActiveWindow := GetActiveWindow; try hExeHandle := WinExec('arj.exe /?', SW_SHOWNORMAL); while GetModuleUsage(hExeHandle) <> 0 do Application.ProcessMessages; finally EnableTaskWindows(pWindowsList); SetActiveWindow(hActiveWindow); end; (* 您其他的程式 *) end;
Hi! 各位朋友,
對不起, 小弟疏忽了一件事, 特此更正:
![]() |
1. 上述的程式, 在 Delphi 1.0 是正確的, 不管是 Windows 3.1 或 95 都可以編譯執行. |
![]() |
2. 如果您的環境是 Delphi 2.0 + Windows 95, 那麼請改用以下的程式寫 法: (因為 GetModuleUsage 已經從 Win32 API 中刪除了) |
這是我的疏忽, 以下是適用於 Delphi 2.0 的程式, 希望幫得上忙 :)
procedure TForm1.Button1Click(Sender: TObject); var sCommandLine: string; bCreateProcess: boolean; lpStartupInfo: TStartupInfo; lpProcessInformation: TProcessInformation; begin sCommandLine := 'Arj /?'; bCreateProcess := CreateProcessA(nil, PChar(sCommandLine), nil, nil, True, NORMAL_PRIORITY_CLASS, nil, nil, lpStartupInfo, lpProcessInformation); if bCreateProcess then WaitForSingleObject(lpProcessInformation.hProcess, INFINITE); end;
如果我把上述的 sCommandLine := 'Arj /?' 改為
sCommandLine := 'xcopy c:\*.* b:';
如何能讓dos的視窗隱藏 不要顯示出來呢?
TStartupInfo 這個結構中有一個 sShowWindow 欄位, 將之設為 SW_HIDE即可, 同時, dwFlags 旗標中至少需含有 STARTF_USESHOWWINDOW, 否則CreateProcess 時, sShowWindow 欄位的設定會無效, 以下是修改過的程式:
procedure TForm1.Button1Click(Sender: TObject); var sCommandLine: string; bCreateProcess: boolean; lpStartupInfo: TStartupInfo; lpProcessInformation: TProcessInformation; begin (* sCommandLine 的內容請視您的情況修改 *) sCommandLine := 'Xcopy d:\temp\temp1\*.* d:\temp\temp2 /v/y'; lpStartupInfo.dwFlags := STARTF_USESHOWWINDOW; lpStartupInfo.wShowWindow := SW_HIDE; { lpStartupInfo.wShowWindow := SW_SHOWMINIMIZED; } bCreateProcess := CreateProcess(nil, PChar(sCommandLine), nil, nil, True, HIGH_PRIORITY_CLASS, nil, nil, lpStartupInfo, lpProcessInformation); if bCreateProcess then WaitForSingleObject(lpProcessInformation.hProcess, INFINITE); end;
另外, 我也發現一個問題: 如果上述程式的 lpStartupInfo.wShowWindow;改成 lpStartupInfo.wShowWindow := SW_SHOWMINIMIZED; 即使以HIGH_PRIORITY_CLASS CreateProcess, 這個極小化的DOS視窗是幾乎不作事的, 需要點一下它(讓它還原視窗大小), 才會開始作 Xcopy 的工作, 請問有人知道原因嗎?
首頁 | 學習筆記 | 主題公園 | 軟體下載 | 關於本站 | 討論信群 | 相約下次 |