2008年7月12日 星期六

Script-Tip012程式的除錯

*寫程式出現錯誤是常發生的事,當您的程式越寫越多,就愈容易犯邏輯錯誤,譬如重覆定義了變數,或符號打錯了,有時為了找一個小錯誤會花上您一天的時間。
AMS提供了很完善的除錯機制,讓您在程式執行錯誤時可以很快地找到錯誤的地方。所有在AMS中的Script都使用同一個除錯技術。
不過有一點是您必須了解的,在有些function,modules或script並不必然能除錯的,尤其是一些外界開發者所寫的用於AMS的程式,可能有它們自己的除錯方式,您必須要自行去讀取這些作者的文件,以了解如何發現錯誤。
※您所寫的程式可能千變萬化(程式語言彈性本來就很大),程式引擎通常只能捕捉明顯的寫法錯誤,其他您就不要太苛求了!

在AMS中,當您執行程式時,程式引擎所能捕捉的錯誤有二類: 語法錯誤和功能性錯誤

*語法錯誤
這類型的錯誤,通常是您的程式寫法有缺損或錯誤,在您預覽或建立(build)您的程式時會被捕捉到。例如:

foo =

上列的程式碼算是很明顯的式子不完整,定義了變數卻沒有指定值給它。
語法錯誤還有一種是您使用內建涵數,但卻沒有傳入規定的參數個數,不過這種錯誤在預覽及建立程式時,不會被捕捉到,直到執行期才會出現錯誤。
例如:

Dialog.Message("大家好");

如上式,使用訊息對話盒的涵數,至少要傳入二個參數(可參閱各action說明),但只傳入一個,在預覽或建立時都不會捕捉錯誤,因為程式引擎檢查了涵數名稱沒有錯,括號也沒少,也有";"當結尾,所以就不認為有錯,不過這行程式在執行時便會出現錯誤訊息說明少了參數。
※如果您參考一下使用手冊中,Dialog.Message的涵數模型如下:


code:--------------------------------------------------------------------------------
number Dialog.Message ( string Title,
string Text,
number Type = MB_OK,
number Icon = MB_ICONINFORMATION,
number DefaultButton = MB_DEFBUTTON1 )
--------------------------------------------------------------------------------

上述的涵數模式是述說Dialog.Message這個內建涵數需要5個參數傳入,前二個要字串,後三個要數字,不過後三個有預設值,所以您不寫的話就用預設值,前二個就不能省了。

*功能性錯誤
有時候您使用內建涵數去執行某些動作,但給的參數錯了(如打錯字),就會出現這類的錯誤,在建立程式時不會捕捉到錯誤(語法沒錯),而且在執行期,AMS預設不會跳出任何錯誤訊息,例如:

filecontents = TextFile.ReadToString("geskdf''' exist.txt");

要讀入某文字檔,但檔名打錯了,在執行期雖出錯,但程式不會有任何動靜,又如下:

Folder.Delete("c:\\temp");

這行程式是要刪掉c:\temp這個目錄,如果這個目錄不存在,那就發生錯誤,但這類錯誤也不會顯現出任何動靜。
想要捕捉這類的錯誤,您可以靠自己寫程式(利用內建的Debug Action)來捕捉,再自行決定要不要出現錯誤警告,或利用程式來避免。

*Debug Action
使用Application.GetLastError這個內建涵數來了解最近的一個Action的執行結果,用以判斷某一行程式的執行是否成功。
它的寫法公式:
last_error_code = Application.GetLastError();
範例:

code:--------------------------------------------------------------------------------
File.Copy("c:\\temp\\test.dat", "c:\\temp\\text2.dat");
error_code = Application.GetLastError(); --這行可以捕捉上一行的copy的結果的傳回代碼
if (error_code ~= 0) then
Dialog.Message("錯誤", "複製檔案錯誤!");
Application.Exit(); --離開程式(內建action)
end
--------------------------------------------------------------------------------

上面的程式很直覺,AMS的程式引擎規定,任一action的執行如果成功就會傳回 0,若出錯就會傳回某特定的數字代碼(像是1182之類的),所以上面的程式去判斷error_code 這個變數如果不是0,那顯然是copy那行出錯了,便跳出個錯誤訊息給使用者看,接著就退出程式。
※如果您想了解程式引擎所捕捉到的程式錯誤說明,可如下:

code:--------------------------------------------------------------------------------
File.Copy("c:\\temp\\test.dat", "c:\\temp\\text2.dat");
error_code = Application.GetLastError(); --這行可以捕捉上一行的copy的結果的傳回代碼
if (error_code ~= 0) then
Dialog.Message("錯誤", "複製檔案錯誤!說明:" .._tblErrorMessage[error_code]);
Application.Exit(); --離開程式(內建action)
end
--------------------------------------------------------------------------------

上面的式子中_tblErrorMessage[錯誤代碼],這是內建讓您查錯誤說明的Tables,這裡所介紹的是很實用的作法,通常都是用Application.GetLastError()搭配Dialog.Message可以讓您在寫程式時,自覺比較容易出錯的地方,在設計期寫進去幫自己除錯,沒問題了再移掉(放著也行)。
※如果您連續執行了幾個action其中一個出錯,但您的Application.GetLastError()寫在一個對的action後面,那便捕捉不到錯誤了,這點應注意!

*使用Debug.ShowWindow
AMS內建了一系統以Debug開頭的Action,可以讓您在程式執行時出現一個報告執行過程的視窗,這也是一個除錯的利器!
使用法:
Debug.ShowWindow(true);
執行這一行後便會跳出一個視窗,接下來用Debug.Print輔助,便可顯示之後所有程式運行的過程,幫自己檢查運用情形。
執行下一行, Debug視窗就會關掉。
Debug.ShowWindow(false);

若您使用Debug.SetTraceMode(true);這個action的話,便會出現詳細的程式運行情形,利用Debug.GetEventContext()這個內建涵數,您可以取得出錯點是在哪個Event,否則物件一多,涵數一多,您可能會找不到。

沒有留言: