明輝手游網(wǎng)中心:是一個(gè)免費(fèi)提供流行視頻軟件教程、在線學(xué)習(xí)分享的學(xué)習(xí)平臺(tái)!

ASP 3.0高級(jí)編程(314)

[摘要]7.4.4 使用IIS錯(cuò)誤頁(yè)面 與ASP錯(cuò)誤處理過程相關(guān)的內(nèi)容是為IIS提供可定制的錯(cuò)誤頁(yè)面。事實(shí)上,在IIS 4.0中也有這個(gè)特點(diǎn)。但新的ASP內(nèi)置對(duì)象ASPError,更易于使用且提...
7.4.4 使用IIS錯(cuò)誤頁(yè)面
       與ASP錯(cuò)誤處理過程相關(guān)的內(nèi)容是為IIS提供可定制的錯(cuò)誤頁(yè)面。事實(shí)上,在IIS 4.0中也有這個(gè)特點(diǎn)。但新的ASP內(nèi)置對(duì)象ASPError,更易于使用且提供更加強(qiáng)大的功能。
       在第4章,當(dāng)我們研究Server.Execute和Server.Transfer方法時(shí),已經(jīng)講述了如何建立定制的錯(cuò)誤頁(yè)面。我們也討論和使用了ASPError對(duì)象,但這種方式受到了一定的限制。在這一部分,將介紹如何將定制的錯(cuò)誤網(wǎng)頁(yè)和ASPError對(duì)象結(jié)合起來建立一個(gè)更好的處理ASP錯(cuò)誤的方法。
       我們可以使用VBScript檢查ASPError對(duì)象的內(nèi)容,從而創(chuàng)建一個(gè)定制的錯(cuò)誤頁(yè)面。構(gòu)建一個(gè)包含錯(cuò)誤內(nèi)容全面信息的字符串,且寫入到服務(wù)器磁盤上的日志文件中。然而網(wǎng)頁(yè)的設(shè)計(jì)僅使訪問者看到網(wǎng)頁(yè)不可用這樣一條信息是不行的,應(yīng)該使訪問者能夠選擇是重新載入上一個(gè)網(wǎng)頁(yè)還是回到主頁(yè),使他們沒意識(shí)已經(jīng)發(fā)生了錯(cuò)誤。
       盡管我們采用VBScript創(chuàng)建這個(gè)網(wǎng)頁(yè),但其使用的一些特性對(duì)JScript來說也是適用的,這兩種腳本語(yǔ)言的相互轉(zhuǎn)換也是比較容易的。
       可以從http://www.wrox.com站點(diǎn)下載本章及本書其他章節(jié)的示例文件。
1.  設(shè)置定制的錯(cuò)誤頁(yè)面
在能使用定制的錯(cuò)誤頁(yè)面之前,必須在Internet Services Manager進(jìn)行相應(yīng)的設(shè)置(設(shè)置方式見第4章)。把示例文件裝入計(jì)算機(jī)的wwwroot目錄中,打開Chapter07子目錄的Properties對(duì)話框,在Custom Errors選項(xiàng)卡中,滾動(dòng)列表并選中HTTP錯(cuò)誤“500:100”條目,點(diǎn)擊Edit Properties按鈕,并鍵入定制的錯(cuò)誤頁(yè)面Custom_error.asp的URL,如圖7-17所示:

圖7-17  Custom Errors選項(xiàng)卡
現(xiàn)在Chapter07子目錄中的頁(yè)面出現(xiàn)一個(gè)ASP錯(cuò)誤時(shí),就會(huì)打開定制的錯(cuò)誤頁(yè)面。
2.  使用定制的錯(cuò)誤頁(yè)面
在瀏覽器中打開Chapter07目錄并選擇到“Using a Custom Error Page”的鏈接,這個(gè)頁(yè)面顯示了一系列用于產(chǎn)生各種類型的錯(cuò)誤的按鈕,點(diǎn)擊標(biāo)有“Load a Page with a Syntax error”的按鈕,如圖7-18所示:

圖7-18  演示定制錯(cuò)誤頁(yè)面的屏幕1
這將載入一個(gè)名為syntax_error.asp的簡(jiǎn)單頁(yè)面。然而看不到這個(gè)頁(yè)面,因?yàn)檫@個(gè)頁(yè)面包含了一個(gè)語(yǔ)法錯(cuò)誤。ASP終止這個(gè)頁(yè)面的編譯/執(zhí)行,并把執(zhí)行轉(zhuǎn)到定制錯(cuò)誤頁(yè)面,這個(gè)頁(yè)面展示了錯(cuò)誤的細(xì)節(jié)和兩個(gè)按鈕,這兩個(gè)按鈕用以返回上個(gè)頁(yè)面(主菜單)或返回Web站點(diǎn)的缺省主頁(yè),如圖7-19所示:

圖7-19  演示定制錯(cuò)誤頁(yè)面的屏幕2
這個(gè)頁(yè)面也把錯(cuò)誤報(bào)告追加到服務(wù)器磁盤C:\temp文件夾中名為custom_error.log的日志文件中,可以在文件編輯器中打開并查看它,圖7-20所示的日志文件已經(jīng)記錄了幾個(gè)錯(cuò)誤。

圖7-20 日志文件
如果在頁(yè)面中得到了一個(gè)信息,指明日志文件不能寫入信息,可能是因?yàn)镮USR_machinename(IUSR_計(jì)算機(jī)名)帳號(hào)沒有訪問C:\temp目錄的權(quán)限。當(dāng)測(cè)試這個(gè)頁(yè)面時(shí),應(yīng)該給予IUSR_machinename帳號(hào)對(duì)這個(gè)目錄的全部控制權(quán),或者改變custom_error.asp頁(yè)面的程序代碼以指向一個(gè)IUSR有全部控制權(quán)的文件夾
錯(cuò)誤消息出現(xiàn)在頁(yè)面中的唯一原因,是因?yàn)樵赾ause_error.asp頁(yè)面中我們選擇了相應(yīng)的復(fù)選框。如果關(guān)閉該選項(xiàng)并再次點(diǎn)擊按鈕,便看不到錯(cuò)誤的詳細(xì)情況,然而錯(cuò)誤信息仍然記錄在服務(wù)器磁盤上的custom_error.log錯(cuò)誤日志文件中。
“Display debugging information”復(fù)選框給定制錯(cuò)誤頁(yè)面(而不是日志文件)提供了更多的信息,有助于調(diào)試那些使用ASP內(nèi)置對(duì)象集合值的頁(yè)面,如圖7-21所示:

圖7-21  cause_error.asp頁(yè)面的選擇框
在本章下面部分,將再討論這一問題,同時(shí)也可以了解“Cause An Error”頁(yè)面上的其他按鈕所提供的其他種類的錯(cuò)誤信息。注意有一些按鈕能夠比其他的按鈕能夠提供更多信息。特別是只有最后一個(gè)按鈕給出ASP錯(cuò)誤代碼的值(這里是ASP 0177)。
(1) “Cause An Error”頁(yè)面的功能
與先前討論的示例頁(yè)面一樣,引起錯(cuò)誤的頁(yè)面使用同樣的技術(shù),用<Form>把值提交給同一個(gè)頁(yè)面。然后ASP程序查看窗口上點(diǎn)擊的是那個(gè)SUBMIT按鈕,然后運(yùn)行代碼的相應(yīng)部分。同時(shí)查看是否頁(yè)面上兩個(gè)復(fù)選框是否選中,如果是這樣,程序首先設(shè)置一個(gè)或兩個(gè)會(huì)話級(jí)的變量以指明這一點(diǎn)。
<%
'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,當(dāng)錯(cuò)誤發(fā)生時(shí),正在運(yùn)行的網(wǎng)頁(yè)的整個(gè)ASP環(huán)境由IIS傳給定制錯(cuò)誤頁(yè)面。然而,腳本變量的值并沒有傳給定制錯(cuò)誤頁(yè)面,所以必須使用Session變量,或者把值添加到Request.Form或Request.QueryString集合以便把值傳送給定制錯(cuò)誤頁(yè)面。
設(shè)置了Session變量之后,程序繼續(xù)查看點(diǎn)擊了哪個(gè)按鈕。每個(gè)類型的錯(cuò)誤(除了第一類型外),都是由運(yùn)行相應(yīng)的ASP代碼產(chǎn)生的,第一類型的錯(cuò)誤需要調(diào)用另一個(gè)頁(yè)面。
...
'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) 定制錯(cuò)誤頁(yè)面的工作
知道了如何創(chuàng)建錯(cuò)誤后,讓我們來看看定制的錯(cuò)誤頁(yè)面。在前面的章節(jié)里已經(jīng)知道了構(gòu)建網(wǎng)頁(yè)需要的理論,這里再概要地描述一下其工作過程。第一步是關(guān)閉缺省的錯(cuò)誤處理器以便頁(yè)面程序不被另一個(gè)錯(cuò)誤中斷。第二步通過創(chuàng)建一個(gè)新的ASPError對(duì)象收集原始錯(cuò)誤信息。進(jìn)行這個(gè)工作時(shí)要格式化一些值,并把它們轉(zhuǎn)換成合適的數(shù)據(jù)類型。
<%
'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
...
現(xiàn)在構(gòu)建一個(gè)錯(cuò)誤報(bào)告字符串,這段程序看起來復(fù)雜,但實(shí)際上僅是一系列If ...Then語(yǔ)句的嵌套,用以產(chǎn)生良好的報(bào)告格式,沒有任何空的段落。如果錯(cuò)誤是語(yǔ)法錯(cuò)誤,來自ASPError對(duì)象的Source屬性的源代碼可在strSourceCode變量中得到,可以使用這個(gè)變量及l(fā)ngColNum的值(從ASPError對(duì)象的Column屬性中得到)增加一個(gè)標(biāo)記用來指明在源程序中的什么地方發(fā)現(xiàn)了錯(cuò)誤。
...
'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) 記錄錯(cuò)誤
用名為strDetail的字符串變量創(chuàng)建了錯(cuò)誤報(bào)告后,可以像在第5章中做的那樣,采用FileSystemObject對(duì)象把它追加到日志文件中。如果成功,布爾型“failed flag”變量將被設(shè)置成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) 跳轉(zhuǎn)到另一個(gè)頁(yè)面
現(xiàn)在準(zhǔn)備在網(wǎng)頁(yè)中創(chuàng)建一些輸出。在此之前,需要檢查錯(cuò)誤細(xì)節(jié)以確定下一步要做什么。例如,可用ASPError對(duì)象的Number或其他屬性檢查錯(cuò)誤類型。在這里,可認(rèn)為“Type Mismatch”錯(cuò)誤不是代碼中有錯(cuò)誤,可能是由于用戶在文本框中輸入錯(cuò)誤數(shù)據(jù)產(chǎn)生的。所以不顯示這個(gè)網(wǎng)頁(yè)的剩余部分,而是跳轉(zhuǎn)到另一個(gè)網(wǎng)頁(yè)
If objASPError.Number = -2146828275 Then            ' 0x800A000D - type mismatch
   Response.Clear
  Response.Redirect "/"                                           ' go to the Home page
End If
是否決定這樣做依賴于你自己的情況以及你打算發(fā)現(xiàn)、記錄或顯示的錯(cuò)誤類型。需要注意的是,因?yàn)槲覀儾幌氚涯壳暗木W(wǎng)頁(yè)環(huán)境傳送到新的網(wǎng)頁(yè)上,所以選擇使用Reponse.Redirect語(yǔ)句而不是用Server.Transfer語(yǔ)句。
(5) 顯示錯(cuò)誤信息
最后,顯示錯(cuò)誤報(bào)告和其他信息以及返回到上一個(gè)網(wǎng)頁(yè)或主頁(yè)的按鈕。
<%
'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="&nbsp;&nbsp;&nbsp;">
   &nbsp; Return to the previous page<P>
   </FORM>
<%
End If
%>
<FORM ACTION="/">
<INPUT TYPE="SUBMIT" NAME="cmdOK" VALUE="&nbsp;&nbsp;&nbsp;">
&nbsp; Go to our Home page<P>
</FORM>
對(duì)上面這段程序需要注意的是:在定制錯(cuò)誤頁(yè)面里,不能使用Server.Execute方法。如果我們這樣做的話,至少程序不能正常工作。當(dāng)程序把執(zhí)行轉(zhuǎn)到特定的網(wǎng)頁(yè)時(shí),程序不會(huì)再返回到當(dāng)前網(wǎng)頁(yè),這就是我們使用Server.Transfer方法載入顯示調(diào)試信息的網(wǎng)頁(yè)的原因。這是下一部分要討論的問題。

7.5 程序調(diào)試——發(fā)現(xiàn)及處理錯(cuò)誤
       讀完上面內(nèi)容,讀者一定很想創(chuàng)建一個(gè)沒有錯(cuò)誤的ASP網(wǎng)頁(yè)。但你可能會(huì)發(fā)現(xiàn)網(wǎng)頁(yè)并不能工作。怎么辦,只有進(jìn)行測(cè)試。
       在這一部分,首先簡(jiǎn)要看一下能使調(diào)試更容易的一些工具。Microsoft Script Debugger試圖把調(diào)試支持工具提高到像Visual Basic、Delphi和Visual C++等大多數(shù)傳統(tǒng)編程環(huán)境的水平。然而,下面將首先討論一些更傳統(tǒng)的有助于跟蹤出現(xiàn)在網(wǎng)頁(yè)中的錯(cuò)誤的技術(shù)。