直播中
圖7-17 Custom Errors選項卡
現在Chapter07子目錄中的頁面出現一個ASP錯誤時,就會打開定制的錯誤頁面。
2. 使用定制的錯誤頁面
在瀏覽器中打開Chapter07目錄并選擇到“Using a Custom Error Page”的鏈接,這個頁面顯示了一系列用于產生各種類型的錯誤的按鈕,點擊標有“Load a Page with a Syntax error”的按鈕,如圖7-18所示:
圖7-18 演示定制錯誤頁面的屏幕1
這將載入一個名為syntax_error.asp的簡單頁面。然而看不到這個頁面,因為這個頁面包含了一個語法錯誤。ASP終止這個頁面的編譯/執(zhí)行,并把執(zhí)行轉到定制錯誤頁面,這個頁面展示了錯誤的細節(jié)和兩個按鈕,這兩個按鈕用以返回上個頁面(主菜單)或返回Web站點的缺省主頁,如圖7-19所示:
圖7-19 演示定制錯誤頁面的屏幕2
這個頁面也把錯誤報告追加到服務器磁盤C:\temp文件夾中名為custom_error.log的日志文件中,可以在文件編輯器中打開并查看它,圖7-20所示的日志文件已經記錄了幾個錯誤。
圖7-20 日志文件
如果在頁面中得到了一個信息,指明日志文件不能寫入信息,可能是因為IUSR_machinename(IUSR_計算機名)帳號沒有訪問C:\temp目錄的權限。當測試這個頁面時,應該給予IUSR_machinename帳號對這個目錄的全部控制權,或者改變custom_error.asp頁面的程序代碼以指向一個IUSR有全部控制權的文件夾
錯誤消息出現在頁面中的唯一原因,是因為在cause_error.asp頁面中我們選擇了相應的復選框。如果關閉該選項并再次點擊按鈕,便看不到錯誤的詳細情況,然而錯誤信息仍然記錄在服務器磁盤上的custom_error.log錯誤日志文件中。
“Display debugging information”復選框給定制錯誤頁面(而不是日志文件)提供了更多的信息,有助于調試那些使用ASP內置對象集合值的頁面,如圖7-21所示:
圖7-21 cause_error.asp頁面的選擇框
在本章下面部分,將再討論這一問題,同時也可以了解“Cause An Error”頁面上的其他按鈕所提供的其他種類的錯誤信息。注意有一些按鈕能夠比其他的按鈕能夠提供更多信息。特別是只有最后一個按鈕給出ASP錯誤代碼的值(這里是ASP 0177)。
(1) “Cause An Error”頁面的功能
與先前討論的示例頁面一樣,引起錯誤的頁面使用同樣的技術,用<Form>把值提交給同一個頁面。然后ASP程序查看窗口上點擊的是那個SUBMIT按鈕,然后運行代碼的相應部分。同時查看是否頁面上兩個復選框是否選中,如果是這樣,程序首先設置一個或兩個會話級的變量以指明這一點。
<%
'see if we are displaying error and debug information
'set session variables to retrieve in the custom error page
If Len(Request.Form("chkShowError")) Then
Session("ShowError") = "Yes"
Else
Session("ShowError") = ""
End If
If Len(Request.Form("chkShowDebug")) Then
Session("ShowDebug") = "Yes"
Else
Session("ShowDebug") = ""
End If
...
%>
由于使用了Server.Transfer,當錯誤發(fā)生時,正在運行的網頁的整個ASP環(huán)境由IIS傳給定制錯誤頁面。然而,腳本變量的值并沒有傳給定制錯誤頁面,所以必須使用Session變量,或者把值添加到Request.Form或Request.QueryString集合以便把值傳送給定制錯誤頁面。
設置了Session變量之后,程序繼續(xù)查看點擊了哪個按鈕。每個類型的錯誤(除了第一類型外),都是由運行相應的ASP代碼產生的,第一類型的錯誤需要調用另一個頁面。
...
'look for a command sent from the FORM section buttons
If Len(Request.Form("cmdSyntax")) Then
Response.Clear
Response.Redirect "syntax_error.asp"
End If
If Len(Request.Form("cmdParamType")) Then
intDate = "error"
intDay = Day(intDate)
End If
If Len(Request.Form("cmdArray")) Then
Dim arrThis(3)
arrThis(4) = "Causes an error"
End If
If Len(Request.Form("cmdFile")) Then
Set objFSO = Server.CreateObject("Scripting.FileSystemObject")
Set objTStream = objFSO.OpenTextFile("does_not_exist.txt")
End If
If Len(Request.Form("cmdPageCount")) Then
Set objPageCount = Server.CreateObject("MSWC.PageCounter")
objPageCount.WrongProperty = 10
End If
If Len(Request.Form("cmdObject")) Then
Set objThis = Server.CreateObject("Doesnot.Exist")
End If
%>
(2) 定制錯誤頁面的工作
知道了如何創(chuàng)建錯誤后,讓我們來看看定制的錯誤頁面。在前面的章節(jié)里已經知道了構建網頁需要的理論,這里再概要地描述一下其工作過程。第一步是關閉缺省的錯誤處理器以便頁面程序不被另一個錯誤中斷。第二步通過創(chuàng)建一個新的ASPError對象收集原始錯誤信息。進行這個工作時要格式化一些值,并把它們轉換成合適的數據類型。
<%
'prevent any other errors from stopping execution
On Error Resume Next
'get a reference to the ASPError object
Set objASPError = Server.GetLastError()
'get the property values
strErrNumber = CStr(objASPError.Number) 'normal error code
strASPCode = objASPError.ASPCode 'ASP error code (if available)
If Len(strASPCode) Then
strASPCode = "'" & strASPCode & "' "
Else
strASPCode = ""
End If
strErrDescription = objASPError.Description
strASPDescription = objASPError.ASPDescription
strCategory = objASPError.Category 'type or source of error
strFileName = objASPError.File 'file path and name
strLineNum = objASPError.Line 'line number in file
strColNum = objASPError.Column 'column number in line
If IsNumeric(strColNum) Then 'if available convert to integer
lngColNum = CLng(strColNum)
Else
lngColNum = 0
End If
strSourceCode = objASPError.Source 'source code of line
...
現在構建一個錯誤報告字符串,這段程序看起來復雜,但實際上僅是一系列If ...Then語句的嵌套,用以產生良好的報告格式,沒有任何空的段落。如果錯誤是語法錯誤,來自ASPError對象的Source屬性的源代碼可在strSourceCode變量中得到,可以使用這個變量及l(fā)ngColNum的值(從ASPError對象的Column屬性中得到)增加一個標記用來指明在源程序中的什么地方發(fā)現了錯誤。
...
'create the error message string
strDetail = "ASP Error " & strASPCode & "occurred " & Now
If Len(strCategory) Then
strDetail = strDetail & " in " & strCategory
End If
strDetail = strDetail & vbCrlf & "Error number: " & strErrNumber _
& " (0x" & Hex(strErrNumber) & ")" & vbCrlf
If Len(strFileName) Then
strDetail = strDetail & "File: " & strFileName
If strLineNum > "0" Then
strDetail = strDetail & ", line " & strLineNum
If lngColNum > 0 Then
strDetail = strDetail & ", column " & lngColNum
If Len(strSourceCode) Then
'get the source line so put a ^ marker in the string
strDetail = strDetail & vbCrlf & strSourceCode & vbCrlf _
& String(lngColNum - 1, "-") & "^"
End If
End If
End If
strDetail = strDetail & vbCrlf
End If
strDetail = strDetail & strErrDescription & vbCrlf
If Len(strASPDescription) Then
strDetail = strDetail & "ASP reports: " & strASPDescription & vbCrlf
End If
...
(3) 記錄錯誤
用名為strDetail的字符串變量創(chuàng)建了錯誤報告后,可以像在第5章中做的那樣,采用FileSystemObject對象把它追加到日志文件中。如果成功,布爾型“failed flag”變量將被設置成False。
...
'now log error to a file. Edit the path to suit your machine.
'you need to give the IUSR_machinename permission to write and modify
'the file or directory used for the log file:
strErrorLog = "c:\temp\custom_error.log"
Set objFSO = Server.CreateObject("Scripting.FileSystemObject")
Set objTStream = objFSO.OpenTextFile(strErrorLog, 8, True) '8 = ForAppending
If Err.Number = 0 Then objTStream.WriteLine strDetail & vbCrlf
If Err.Number = 0 Then
objTStream.Close
blnFailedToLog = False
Else
blnFailedToLog = True
End If
%>
(4) 跳轉到另一個頁面
現在準備在網頁中創(chuàng)建一些輸出。在此之前,需要檢查錯誤細節(jié)以確定下一步要做什么。例如,可用ASPError對象的Number或其他屬性檢查錯誤類型。在這里,可認為“Type Mismatch”錯誤不是代碼中有錯誤,可能是由于用戶在文本框中輸入錯誤數據產生的。所以不顯示這個網頁的剩余部分,而是跳轉到另一個網頁
If objASPError.Number = -2146828275 Then ' 0x800A000D - type mismatch
Response.Clear
Response.Redirect "/" ' go to the Home page
End If
是否決定這樣做依賴于你自己的情況以及你打算發(fā)現、記錄或顯示的錯誤類型。需要注意的是,因為我們不想把目前的網頁環(huán)境傳送到新的網頁上,所以選擇使用Reponse.Redirect語句而不是用Server.Transfer語句。
(5) 顯示錯誤信息
最后,顯示錯誤報告和其他信息以及返回到上一個網頁或主頁的按鈕。
<%
'see if the logging to file failed
'if so, display message
If blnFailedToLog Then
Response.Write "<B>WARNING: Cannot log error to file '" & strErrorLog & "'</B>.<P>"
End If
'see if we are displaying the error information
If Session("ShowError") = "Yes" Then
%>
<PRE><% = Server.HTMLEncode(strDetail) %></PRE>
<%
End If
'see if we are displaying the debug information
If Session("ShowDebug") = "Yes" Then Server.Transfer "debug_request.asp"
'create the buttons to return to the previous or Home page
strReferrer = Request.ServerVariables("HTTP_REFERER")
If Len(strReferrer) Then
%>
<FORM ACTION="<% = strReferrer %>">
<INPUT TYPE="SUBMIT" NAME="cmdOK" VALUE=" ">
Return to the previous page<P>
</FORM>
<%
End If
%>
<FORM ACTION="/">
<INPUT TYPE="SUBMIT" NAME="cmdOK" VALUE=" ">
Go to our Home page<P>
</FORM>
對上面這段程序需要注意的是:在定制錯誤頁面里,不能使用Server.Execute方法。如果我們這樣做的話,至少程序不能正常工作。當程序把執(zhí)行轉到特定的網頁時,程序不會再返回到當前網頁,這就是我們使用Server.Transfer方法載入顯示調試信息的網頁的原因。這是下一部分要討論的問題。
7.5 程序調試——發(fā)現及處理錯誤
讀完上面內容,讀者一定很想創(chuàng)建一個沒有錯誤的ASP網頁。但你可能會發(fā)現網頁并不能工作。怎么辦,只有進行測試。 在這一部分,首先簡要看一下能使調試更容易的一些工具。Microsoft Script Debugger試圖把調試支持工具提高到像Visual Basic、Delphi和Visual C++等大多數傳統(tǒng)編程環(huán)境的水平。然而,下面將首先討論一些更傳統(tǒng)的有助于跟蹤出現在網頁中的錯誤的技術。