當你使用Shell函數的時候,在VB程式裡運行另一個可執行程式是很容易的。在本篇文章裡,我將向你示範如何通過一種簡單的方式來改進Shell的功能。
Shell接受兩個自變數。第一個是將要啟動並執行EXE檔案的名稱,包括其路徑。第二個自變數用來指定程式的視窗樣式。這個自變數是可選的;如果省略掉的話,程式就會以最小化的形式運行。這裡所展現的技術在工作的時候不會理會程式的視窗樣式,甚至程式沒有視窗都可以。(關於視窗樣式自變數的更多資訊,請參考VB的協助。)
Shell會非同步地運行目標程式,這就意味著執行可以在第二個程式執行完之前就返回VB程式。在很多情況下,這沒有問題;但是在有的情況下,這可能就是問題了。一個例子是,當你的VB程式在某種程度上要依靠外殼程式完成其操作的結果。在這種情況下,你就需要某種方式來暫停VB程式,直到另一個程式結束。
第一步是取得外殼程式的控制代碼。Shell函數會返回其程式的ID,或者PID。一旦有了這個,你就可以使用OpenProcess API函數來取得控制代碼:
Public Declare Function OpenProcess Lib "kernel32" _
(ByValdwDesiredAccess As Long, _
ByValbInheritHandle As Long, _
ByValdwProcessId As Long) As Long
將&H100000(通常由常量SYNCHRONIZE來表示)這個值傳遞給第一個自變數,將0(作為一個長型)傳遞給第二個自變數。第三個自變數是Shell函數返回的PID。函數所返回的值是代表外殼程式的Windows進程的控制代碼。有了這個控制代碼,你可以使用WaitForSingleObject API函數來暫停VB程式,直到外殼程式被終止。聲明是:
Private Declare Function WaitForSingleObject Lib _
"kernel32" (ByValhHandle As Long, _
ByValdwMilliseconds As Long) As Long
第一個自變數是程式所等待的控制代碼,它從OpenProcess函數獲得。第二個自變數是等待時間。如果你傳遞了一個毫秒值,那麼函數就會在外殼程式結束的時候,或者在指定的時間間隔用完的時候返回,這取決於哪一種情況先發生。如果你想要函數一直等到外殼程式結束,那麼就要傳遞&HFFFF(常常由常數INFINITE表示)這個值。
下面的範例程式碼顯示了如何使用這些API來給程式設定外殼,並等待其完成。
Const SYNCHRONIZE = &H100000
Const INFINITE = &HFFFF
Private Sub ShellProgramAndWait(ProgramName As String)
Dim hHandle As Long, pid As Long
txtStatus.Text = "Processing"
txtStatus.Refresh
pid = Shell(ProgramName, vbNormalFocus)
If pid <> 0 Then
hHandle = OpenProcess(SYNCHRONIZE, 0&, pid)
WaitForSingleObjecthHandle, INFINITE
txtStatus.Text = "Finished"
Else
txtStatus.Text = "Error shelling " & ProgramName
End If
End Sub
WaitForSingleObject函數會有效地凍結你的VB程式,這是你需要注意的事情,這樣使用者就不會認為出了問題。例如在這段代碼裡,一個Text Box(文字框)控制項向使用者顯示了一條訊息。要注意,Refresh(重新整理)方法的使用確保了該訊息在程式進入等待狀態之前被顯示出來。然後,當外殼程式終止的時候,一個“已完成(Finished)”的訊息就顯示出來了。
本文作者Peter Aitken:自從Visual Basic 1.0版以來,Peter Aitken就一直使用VB編程。他已經編寫過很多關於VisualBasic以及其 他電腦和編程的書以及雜誌文章了。