API說到底就是一系列的底層函數(shù),是系統(tǒng)提供給 用戶用于進入操作系統(tǒng)核心,進行高級編程的途徑。通過在Visual Basic應用程序中聲明外部過程就能夠 訪問Windows API(以及其它的外部DLLs)。在聲明了過程之后,調用它的方法與調用Visual Basic自己的過程相同。
Visual Basic (VB)作為一種高效編程環(huán)境,它封裝了部分Windows API函數(shù),但也犧牲了一些API的功能。調用API時稍有不慎就可能導致API編程錯誤,出現(xiàn)難于捕獲或間歇性錯誤,甚至出現(xiàn)程序崩潰。要減少API編程錯誤,提高VB調用API時的安全性,應重點注意下列八個問題:
(1)指定“Option Explicit”
編程前將VB編程環(huán)境中的“Require Variable Declaration(要求變量申明)項選中。如果該項未被指定,任何簡單的錄入錯誤都可能會產(chǎn)生一個“Variant”變量,在調用API時,VB對該變量進行強制轉換以避免沖突,這樣一來,VB就會為字符串、長整數(shù)、整數(shù)、浮點數(shù)等各種類型傳遞NULL值,導致程序無法正常運行。
(2)注意VB整數(shù)和Win32整數(shù)的區(qū)別
在VB環(huán)境下,涉及到的所有integer(整型數(shù)),都是16位,而一旦涉及C/C++Win32文檔時,則是32位,閱讀與Windows API函數(shù)或與32位動態(tài)鏈接庫有關的資料或應用程序時,尤其要注意分析理解環(huán)境背景,以利于分清數(shù)據(jù)類型和數(shù)據(jù)結構,正確地聲明API函數(shù)。
(3)減少和避免使用As Any
雖然用As Any的方法聲明庫,可使Windows API函數(shù)能接受多種類型的參數(shù),但更嚴重的是,即使是一個很小的錯誤,比如遺漏類型標識符或錯誤地使用了ByVal關鍵字,都可能導致系統(tǒng)崩潰或很難發(fā)現(xiàn)的其他數(shù)據(jù)錯誤。
(4)注意檢查參數(shù)類型
API錯誤中,除了因遺漏ByVal關鍵字導致的錯誤外,大約有50%是因為聲明中有不正確的參數(shù)類型。在Win32環(huán)境下,無論是8位、16位,還是32位數(shù)值變量都是以32位傳遞,如果同時使用,則很難發(fā)現(xiàn)其中錯誤。如果聲明的參數(shù)類型不同,被VB視為Variant傳遞給API函數(shù),會出現(xiàn)“錯誤的DLL調用規(guī)范”的消息。
(5)勿忘ByVal,確保函數(shù)聲明的完整性
ByVal是“按值”調用,參數(shù)傳遞時,不將指向DLL的指針傳遞給參數(shù)變量本身,而是將傳遞參數(shù)值的一份拷貝傳遞給DLL。比如傳遞字符串參數(shù)時,VB與DLL之間的接口支持兩種類型的字符串,如未使用ByVal關鍵字,VB將指向DLL的函數(shù)指針傳遞給一個OLE2.0字符串(即BSTR數(shù)據(jù)類型),而Windows API函數(shù)往往不支持這種數(shù)據(jù)類型,導致錯誤。而使用ByVal關鍵字后VB將字符串轉變換成C語言格式的“空終止”串,被API正確使用。
(6)重新檢查函數(shù)名
在Win16環(huán)境下,API函數(shù)的名字不要求區(qū)分大小寫,而在Win32環(huán)境下,則有此要求。在一個DLL函數(shù)里找不到聲明的函數(shù)時,有必要檢查一下函數(shù)名,對于管理字符串的函數(shù),是否遺漏了A和W前綴。
(7)預先初始化字符串,以免造成沖突
如果API函數(shù)要求一個指向緩沖區(qū)的指針,以便從中載入數(shù)據(jù),而此時傳遞的是字符串變量,應該先初始化字符串長度。因為API無法知道字符串的長度——API默認已為其分配有足夠的長度。沒有初始化字符串,分配給字符串的緩沖區(qū)有可能會不足,API函數(shù)將有可能在緩沖區(qū)末尾反復改寫,內存里字符串后面的內容將會改寫得一塌糊涂。程序表現(xiàn)為突然終止或間歇性錯誤。
(8)跟蹤檢查參數(shù)、返回類型和返回值
VB具有立即模式和單步調試功能,利用這個優(yōu)勢,確保函數(shù)聲明的類型明確(API不返回Variant類型),通過跟蹤和檢查參數(shù)的來源及類型,可以排除參數(shù)的錯誤傳遞。許多API函數(shù)都有返回結果,指出自己是否執(zhí)行成功。你若要對返回結果進行測試,用VB的Err對象的LastDllError方法可查閱這些信息,對錯誤可針對API函數(shù)調用,取回API函數(shù)GetlastError的結果,以修改聲明,達到正確調用API函數(shù)之目的。
Visual Basic (VB)作為一種高效編程環(huán)境,它封裝了部分Windows API函數(shù),但也犧牲了一些API的功能。調用API時稍有不慎就可能導致API編程錯誤,出現(xiàn)難于捕獲或間歇性錯誤,甚至出現(xiàn)程序崩潰。要減少API編程錯誤,提高VB調用API時的安全性,應重點注意下列八個問題:
(1)指定“Option Explicit”
編程前將VB編程環(huán)境中的“Require Variable Declaration(要求變量申明)項選中。如果該項未被指定,任何簡單的錄入錯誤都可能會產(chǎn)生一個“Variant”變量,在調用API時,VB對該變量進行強制轉換以避免沖突,這樣一來,VB就會為字符串、長整數(shù)、整數(shù)、浮點數(shù)等各種類型傳遞NULL值,導致程序無法正常運行。
(2)注意VB整數(shù)和Win32整數(shù)的區(qū)別
在VB環(huán)境下,涉及到的所有integer(整型數(shù)),都是16位,而一旦涉及C/C++Win32文檔時,則是32位,閱讀與Windows API函數(shù)或與32位動態(tài)鏈接庫有關的資料或應用程序時,尤其要注意分析理解環(huán)境背景,以利于分清數(shù)據(jù)類型和數(shù)據(jù)結構,正確地聲明API函數(shù)。
(3)減少和避免使用As Any
雖然用As Any的方法聲明庫,可使Windows API函數(shù)能接受多種類型的參數(shù),但更嚴重的是,即使是一個很小的錯誤,比如遺漏類型標識符或錯誤地使用了ByVal關鍵字,都可能導致系統(tǒng)崩潰或很難發(fā)現(xiàn)的其他數(shù)據(jù)錯誤。
(4)注意檢查參數(shù)類型
API錯誤中,除了因遺漏ByVal關鍵字導致的錯誤外,大約有50%是因為聲明中有不正確的參數(shù)類型。在Win32環(huán)境下,無論是8位、16位,還是32位數(shù)值變量都是以32位傳遞,如果同時使用,則很難發(fā)現(xiàn)其中錯誤。如果聲明的參數(shù)類型不同,被VB視為Variant傳遞給API函數(shù),會出現(xiàn)“錯誤的DLL調用規(guī)范”的消息。
(5)勿忘ByVal,確保函數(shù)聲明的完整性
ByVal是“按值”調用,參數(shù)傳遞時,不將指向DLL的指針傳遞給參數(shù)變量本身,而是將傳遞參數(shù)值的一份拷貝傳遞給DLL。比如傳遞字符串參數(shù)時,VB與DLL之間的接口支持兩種類型的字符串,如未使用ByVal關鍵字,VB將指向DLL的函數(shù)指針傳遞給一個OLE2.0字符串(即BSTR數(shù)據(jù)類型),而Windows API函數(shù)往往不支持這種數(shù)據(jù)類型,導致錯誤。而使用ByVal關鍵字后VB將字符串轉變換成C語言格式的“空終止”串,被API正確使用。
(6)重新檢查函數(shù)名
在Win16環(huán)境下,API函數(shù)的名字不要求區(qū)分大小寫,而在Win32環(huán)境下,則有此要求。在一個DLL函數(shù)里找不到聲明的函數(shù)時,有必要檢查一下函數(shù)名,對于管理字符串的函數(shù),是否遺漏了A和W前綴。
(7)預先初始化字符串,以免造成沖突
如果API函數(shù)要求一個指向緩沖區(qū)的指針,以便從中載入數(shù)據(jù),而此時傳遞的是字符串變量,應該先初始化字符串長度。因為API無法知道字符串的長度——API默認已為其分配有足夠的長度。沒有初始化字符串,分配給字符串的緩沖區(qū)有可能會不足,API函數(shù)將有可能在緩沖區(qū)末尾反復改寫,內存里字符串后面的內容將會改寫得一塌糊涂。程序表現(xiàn)為突然終止或間歇性錯誤。
(8)跟蹤檢查參數(shù)、返回類型和返回值
VB具有立即模式和單步調試功能,利用這個優(yōu)勢,確保函數(shù)聲明的類型明確(API不返回Variant類型),通過跟蹤和檢查參數(shù)的來源及類型,可以排除參數(shù)的錯誤傳遞。許多API函數(shù)都有返回結果,指出自己是否執(zhí)行成功。你若要對返回結果進行測試,用VB的Err對象的LastDllError方法可查閱這些信息,對錯誤可針對API函數(shù)調用,取回API函數(shù)GetlastError的結果,以修改聲明,達到正確調用API函數(shù)之目的。