Title: WinDNA Error Handling 101 Paul Bates Support Professional Solution Integration Engineering Microsoft
1WinDNA Error Handling 101Paul BatesSupport
ProfessionalSolution Integration
EngineeringMicrosoft Corporation
2Agenda
- Why have error handling?
- Error handling in Windows Distributed interNet
Applications Architecture (WinDNA). - Where should I put error handling?
- Central storage of errors.
- Error handling in ASP using Visual Basic Script
(VBScript). - Error handling in VB ActiveX component.
- Error handling in C ATL ActiveX component.
- Error handling in SQL Server stored procedure.
- Miscellaneous.
- Questions.
3Why have error handling?
- Notification of a problem.
- Corrective course of action.
- Problem isolation.
- Knowledge is power.
4Error Handling in WinDNA Architecture
5Where should I put error handling?
- In the client code, display the errors propagated
back to the client. - In the middle-tier, errors should be handled,
logged, and raised to the client. Typically, it
is advantageous to provide the middle-tier
components with robust error handling. - In data-tier, if a stored procedure is called,
then logic should be added to handle and return
errors accordingly.
6Central Storage of Errors
- Errors should be stored for future analysis.
- Errors should be stored with sufficient details.
- Errors should be stored in a central location in
order to correlate related errors. - Good places to store errors
- Windows NT Event Log
- SQL Server database
7Central Storage of Errors (2) Windows NT Event
Log
- The Windows NT Event Log is a good location to
store errors on the middle-tier (MTS/COM) server
and is ideal for simple logging done during the
development phase of the code. - In Visual Basic, we can log the error using the
following code - App.LogEvent "Error Occurred in" Err.Source
- " " Str(Err.Number) "" Err.Description
- In Visual C, we can log the error using the
code on the following slide.
8Central Storage of Errors (3) Windows NT Event
Log Visual C Example
- include ltwindows.hgt
- //Good References
- //ATL's CServiceModuleLogEvent Method.
- //Platform SDK Debugging and Error Handling
- void RaiseMyError(LPCTSTR pError)
-
-
- HANDLE hEventSource
-
- //Get a handle to the NT application log.
- hEventSource OpenEventLog(NULL,"Application")
-
- if (hEventSource ! NULL)
-
- //Write Error To Event Log
- ReportEvent(hEventSource, EVENTLOG_ERROR_TYPE,
0, 0, NULL, 1, 0, pError, NULL)
9Central Storage of Errors (4) Windows NT Event
Log Visual C Example
- //code continued from previous slide.
- else
-
- //Get Extended Error Information
- LPVOID lpMsgBuf
- FormatMessage( FORMAT_MESSAGE_ALLOCATE_BUFFER
FORMAT_MESSAGE_FROM_SYSTEM
FORMAT_MESSAGE_IGNORE_INSERTS, - NULL,GetLastError(),MAKELANGID(LANG_NEUTRAL,
SUBLANG_DEFAULT), (LPTSTR) lpMsgBuf,0,NULL ) - //Report error that is in lpMsgBuf to alternate
location since we can not get to event log! - //lpMsgBuf got allocated. So release it when
we are finished writing extended - //error information.
- LocalFree( lpMsgBuf )
-
-
-
-
10Central Storage of Errors (5)SQL Server Database
(or DBMS)
- In a production environment where multiple
clients may be logging simultaneously, using a
database such as SQL Server or Oracle is ideal. - Relational database management systems (RDBMSs)
are robust enough to handle multi-user logging of
errors to a database effectively. - Logging errors to databases.
11Central Storage of Errors (6)SQL Server Database
(or DBMS)
- Public Sub SQLLogError(errnum As Long,
Description As String, Source As String) - On Error GoTo Errhand
- 'use pubs
- 'create table err_store (dt datetime default
getdate(), num int,description char(255), source
char(255)) - 'insert into err_store values(default, 429,"Can
not create object.","mycompmethod") - Dim objConn As ADODB.Connection
- Dim objErr As ADODB.Error
- Dim insStr As String
12Central Storage of Errors (7)SQL Server Database
(or DBMS)
- Dim strevent As String
- insStr "insert into pubs..err_store
values(default," _ - Str(errnum) ",'" _
- Description "','" _
- Source "')"
- Set objConn CreateObject("ADODB.Connection")
- objConn.Open "DSNTEST", "sa", ""
- objConn.Execute insStr
- objConn.Close
- Set objConn Nothing
- Exit Sub
13Central Storage of Errors (8)SQL Server Database
(or DBMS)
- Errhand
- 'Unable to log by conventional means
- 'Log to event log - or maybe a file
- 'Log Why ADO/SQL logging may have failed.
- For Each objErr In objConn.Errors
- strevent objErr.Number ""
objErr.SQLState "" objErr.Description ""
objErr.NativeError - App.LogEvent strevent
- Next
- 'Log Error That should have gone to sql
- App.LogEvent "Unable To Log Error Info to SQL
Server " insStr - End Sub
14Error Handling in ASP
- Most developers are using VBScript.
- However, it is important to note that both
JScript and DHTML have a more robust mechanism
of error handling, but this is outside of scope
of this presentation. - Additional details can be found on MSDN
- Handling and Avoiding Web Page Errors Part 1
The Basics by Michael D. Edwards - Handling and Avoiding Web Page Errors Part 2
Run-Time Errors by Michael D. Edwards - Build MTS Components with Visual Basic for
Deployment in Your ASP-Based Apps by Ted Pattison
15Error Handling in ASP Using VBScript
- lt
- On Error Resume Next
- call a COM object, or something, or Err.Raise to
cause error. - If Err.Number 0
- Then Response.Write Code Executed!
- Else
- Response.Write Error!ltbrgt"
- Response.Write Err.Description
- Clear the error. After finished processing
error, the developer needs to manually clear this
as VBScript will not etc. - Err.Clear
- End If gt
16Error Handling in VB ActiveX Component
- vbObjectError reserves numbers from vbObjectError
to vbObjectError512. When defining your own
errors, start at vbObjectError5121. - Const gMyErrorNum11vbObjectError512
- Consider enumerating errors.
- In most cases, the class module should handle the
error, log the error, and raise it back to the
calling code. - Using MsgBox to display error in ActiveX DLL is
considered a bad coding practice and it will
cause an ActiveX EXE to hang. - If component uses ADO or objects that have error
collections, then make sure to process errors in
method that accesses the ADO object or these
objects.
17Error Handling in VB ActiveX Component (2)
CLIENT
OBJECT1
OBJECT2
The Client references Object1 which references
Object2. An error occurs in Object2 and is
raised back to Object1 which raises it back to
the client.
18Error Handling in VB ActiveX Component (3)
- Public Sub Test()
- On Error GoTo errorhand
- some code that causes an error here we could
manually call Err.Raise. - Err.Raise vbObjectError 1024, "MyCompTest",
"My Own Error" - normal cleanup code
- Exit Sub
- errorhand
- We could have a member function of class to log
error! - SQLLogError Err.Number, Err.Description,Err.Sourc
e - Err.Raise Err.Number, Err.Description,
Err.Source - End Sub
19Error Handling in VB ActiveX Component (4)With
ADO or Objects Having Error Collections
- Public Sub Test()
- On Error GoTo errorhand
- Dim objConn As ADODB.Connection
- Dim objErr As ADODB.Error
- Ado code and cleanup.
- Exit Sub
- errorhand
-
- For Each objErr In objConn.Errors
- strevent objErr.Number ""
objErr.SQLState "" objErr.Description ""
objErr.NativeError - App.LogEvent strevent
- Or log to SQL Server as discussed earlier.
- Next
- clean up code and set objects to nothing etc.
- End Sub
20Error Handling in C ATL ActiveX Component
- COM objects return an HRESULT such as S_OK,
E_FAIL, or some other code. - COM object that supports standard COM type
exception handling supports the interface
ISupportErrorInfo. - ISupportErrorInfo can be queried to see if an
interface supports exceptions.
21Error Handling in C ATL ActiveX Component (2)
- Series of events leading to birth of error
- Exception occurs.
- Error object created by calling CreateErrorInfo.
- SetErrorInfo called to associate error with
thread of caller. - HRESULT returned to client to indicate problem
occurred. - Client queries to see if object has
ISupportErrorInfo. - Client calls with IID to see if it supports
exceptions. - Client calls GetErrorInfo to get the IErrorInfo
to reference the error object in order to get the
error information.
22Error Handling in C ATL ActiveX Component (3)
23Error Handling in C ATL ActiveX Component (4)
24Error Handling in C ATL ActiveX Component (5)
25Error Handling in C ATL ActiveX Component (6)
26Error Handling in C ATL ActiveX Component (7)
27Error Handling in C ATL ActiveX Component (8)
STDMETHODIMP CMyDivInterfaceSupportsErrorInfo(RE
FIID riid) static const IID arr
IID_IMyDiv for (int i0 i lt
sizeof(arr) / sizeof(arr0) i) if
(InlineIsEqualGUID(arri,riid)) return
S_OK return S_FALSE
28Error Handling in C ATL ActiveX Component (9)
29Error Handling in C ATL ActiveX Component (10)
- STDMETHODIMP CMyDivDivEm(int i, int j, double
iresult) -
- //If j is 0 then flag error. We can not divide
by zero. - if (0j)
-
- //Create the error object
- ICreateErrorInfo pCEI
- CreateErrorInfo(pCEI)
- //Fill the error information
- pCEI-gtSetDescription(L"Can not divide by
zero!") - pCEI-gtSetGUID(IID_IMyDiv)
- pCEI-gtSetSource(L"CMyDivDivEm")
30Error Handling in C ATL ActiveX Component (11)
- IErrorInfo pEI
- pCEI-gtQueryInterface(IID_IErrorInfo,(void
)pEI) - //Set the Error Information for the Client to
Retrieve - SetErrorInfo(0,pEI)
- //Release Cleanup
- pEI-gtRelease()
- pCEI-gtRelease()
- //Return an appropriate HRESULT
- return E_INVALIDARG
-
- //It is ok to divide, so divide and return
results - iresulti/j
- return S_OK
31Error Handling in C ATL ActiveX Component (12)
- The previous code shows you the manual way of
handling the error, but there is an easier way - Use the CComCoClassError that calls the
overloaded function AtlReportError which in turn
calls AtlSetErrorInfo in ATLIMPL.CPP. - Replace the code in the previous example with
- if (0j)
-
- return Error("Can not divide by zero!")
-
- else
-
- iresulti/j
- return S_OK
-
32Error Handling in SQL Server Stored Procedures
- Errors can be raised back to ADO, ODBC, OLEDB by
using RAISERROR. Syntax - RAISERROR (msg_id msg_str,
severity,state, argument,...n ) WITH
option,...n - User-defined error messages can be created using
sp_addmessage. - RAISERROR (101, 1, 2) WITH SETERROR
- RAISERROR (101, 1, 2) WITH LOG
33Error Handling in SQL Server Stored Procedure
(2)Importance of Severity of Error Raised
- Severity level
- 0-18 User defined
- 0-10 Cause SQL_SUCCESS_WITH_INFO to be returned
this is like a warning. - 11-18 Cause SQL_ERROR to be returned. Real
error. - 19-25 For sysadmins only and require WITH LOG
option. - 20-25 Are considered fatal and will cause client
connection to be disconnected. - Severity determines whether transaction is rolled
back.
34Error Handling in SQL Server Stored Procedure (3)
- use pubs
- go
- / Create Table For Testing /
- create table zfailtest (i int)
- go
- / Create the store Procedure that Will Fail /
- create procedure sp_failit
- as
- begin transaction
- insert into pubs..zfailtest values (1)
- rollback transaction
- RAISERROR('Transaction Rolled Back in Procedure
sp_failit',18, 1)
35Miscellaneous
- HRESULT structure is defined in Winerror.h.
- HRESULT can be easily translated using the
FormatMessage() API. - HRESULT can also be translated using the Visual
C Error Lookup Tool (Tools/Error Lookup.
36(No Transcript)