Error Handling


IXFile offers rich error reporting with failure code, error code and error description for easy debugging and effective error processing. Failure code delivers general information on error and determines type of internal operation that failed. Error code contains operating system error code as defined in Windows SDK. Error description is a locale-dependent textual information describing system error. Failure and error codes contain error information of the last IXFile operation and should be retrieved immediately when method completes to avoid wiping out by another call - most methods also reset error and failure codes on successfull completion.

Failure Codes

Failure code is a negative long value that specifies type of failed operation. Most IXFile methods that have return value also return failure code on unsuccessfull completion. This means that the simplest way to obtain failure code is to save return value of the method. On succesfull completion this value is zero or greater than zero depending on the method. On unsuccessfull completion return value is negative and specifies failure code. Thus by checking return value against negative number, developers can quickly determine if operation succeeded. The only exception to this rule is when search operation has not found data; in such situation Find methods return IXF_FAILURE_NOTFOUND value which is also negative, but does not indicate an error. Failure code can be also obtained with
GetFailure method.

Failure code can have one of the following values:
IXF_FAILURE_INTERNAL object error on internal operation (invalid parameter, incorrect data, not enough memory, etc.),
IXF_FAILURE_OPEN file error on opening,
IXF_FAILURE_CLOSE file error on closing,
IXF_FAILURE_FLUSH file error on flushing data buffers,
IXF_FAILURE_READ file error on reading data,
IXF_FAILURE_WRITE file error on writing data,
IXF_FAILURE_GETPOS file error on retrieving position,
IXF_FAILURE_SETPOS file error on setting position,
IXF_FAILURE_GETSIZE file error on retrieving size,
IXF_FAILURE_SETSIZE file error on changing size,
IXF_FAILURE_LOCK file error on locking region,
IXF_FAILURE_UNLOCK file error on unlocking region,
IXF_FAILURE_STAT file error on retrieving information,
IXF_FAILURE_FILE file system operation error,
IXF_FAILURE_LICENSE object error on invalid or expired license.
Most of the failure codes concern actual file activities - that is physical operations performed on file by the operating system (opening file, reading and writing data, positioning, locking, etc.). All other errors not directly related to file activity are represented by IXF_FAILURE_INTERNAL code (invalid parameters, incorrect data, not enough memory, etc.). In any case error code contains system error code of the operation.

IXF_FAILURE_LICENSE indicates error related to license key. In such case error code does not specify system error code; instead it can have one of the following values: -1 if license key is invalid, 0 if trial license is expired, +1 if trial installation is incorrect.

Error Codes

Error code is a long value that specifies operating system error. Error code of the failed operation can be obtained with
GetError method. Complete list of system error codes and their meanings can be found in Windows SDK documentation. Failure code of the operation can be checked in conjunction with error code to locate errors more easily and precisely. GetErrorDescription can be also called to obtain textual description of system error code.

Several common error codes and their explanation in context of failure codes are listed below.
IXF_FAILURE_INTERNAL

6 ERROR_INVALID_HANDLE file handle is invalid (e.g. trying to access file that is already closed or not yet opened),
8 ERROR_NOT_ENOUGH_MEMORY there is not enough memory to complete system operation,
12 ERROR_INVALID_ACCESS requested access is incompatible with mode of operation of the object (e.g. when calling method for writing data on read-only object),
13 ERROR_INVALID_DATA internal data inconsistency (e.g. when more data must be present than buffer contains),
14 ERROR_OUTOFMEMORY there is not enough memory for data allocation,
87 ERROR_INVALID_PARAMETER parameter is incorrect (e.g. has incorrect type, size or value).


IXF_FAILURE_OPEN
  to  IXF_FAILURE_STAT

2 ERROR_FILE_NOT_FOUND system cannot find the file specified,
3 ERROR_PATH_NOT_FOUND system cannot find the path specified,
4 ERROR_TOO_MANY_OPEN_FILES system cannot open file because of file handles limit,
5 ERROR_ACCESS_DENIED access to file is denied (e.g. trying to write data to read-only file),
15 ERROR_INVALID_DRIVE system cannot find the drive specified,
19 ERROR_WRITE_PROTECT media is write-protected (typically diskette),
29 ERROR_WRITE_FAULT system cannot write to file,
30 ERROR_READ_FAULT system cannot read from file,
32 ERROR_SHARING_VIOLATION process cannot access file because it is being used by another process,
33 ERROR_LOCK_VIOLATION process cannot access file because another process has locked it,
38 ERROR_HANDLE_EOF end of file was reached prematurely,
53 ERROR_BAD_NETPATH network path was not found,
112 ERROR_DISK_FULL there is not enough space on disk,
131 ERROR_NEGATIVE_SEEK an attempt was made to move the file pointer before the beginning of the file,
167 ERROR_LOCK_FAILED unable to lock a region of a file,
183 ERROR_ALREADY_EXISTS cannot create a file when that file already exists.


IXF_FAILURE_LICENSE


-1 license key is invalid,
0 trial license has expired,
1 trial installation is incorrect.

Error Handling in Visual Basic

In Visual Basic errors generated by COM components can be handled in two different ways depending on behaviour of the component. First and the most obvious approach is to check return value of the method against some values that indicate an error - exactly the same way as in C++. Second approach - which is most common - is based on Visual Basic exception mechanism that automatically transfers program control to error handling procedure. This is possible because methods of COM components have two return values - 'user' and 'system'. 'User' return value (if method returns something to user) is assigned to a variable on the left side of the expression and can be further processed by user. 'User' errors can have any values depending on application. 'System' return value (which is always present) is used by COM to determine if method completed successfully from the COM point of view. In other words 'system' return value determines if method was correctly processed by COM subsystem regardless of its correctness from user point of view. 'System' error values are predefined by the operating system. In Visual Basic COM method that returns 'system' error generates exception that can be trapped with OnError statement for further processing. If exception is not trapped, a window with error description is displayed and program is aborted. It is user responsibility to correctly trap errors and take adequate actions.

IXFile supports both error handling mechanisms and allows developers to select appropriate behaviour with the EnableErrorHandling method. If error handling is enabled, IXFile methods return errors as 'system' errors that generate exceptions as explained above. In error handling procedure Err Object can be used to obtain error code (Number property) and error description (Description property) of the operation - failure code must be retrieved with GetFailure method. If error handling is disabled 'system' return value of the method is always OK and error code of the operation is returned in 'user' return value. This value is actually the failure code that should be further processed as described in Failure Codes. Error handling is enabled by default but can be disabled or enabled any time with EnableErrorHandling method. To check current status of error handling IsErrorHandlingEnabled should be called.

Examples

C++

//---------------
// Main function
//---------------

  int main(int, char**)
  {
   IFile ixf;
   long rc;
   char txt[256];

// failed operations must be trapped by checking return values of methods

   rc = ixf.SetLicenseKey("YOURLICENSEKEY");
   if(rc == 0)
    rc = ixf.Initialize(); 
   if(rc == 0)
   {

// file opening error is processed differently
// because in this example it is not an error

    if(ixf.Open("data.txt") < 0)
     return(0);

// further operations are checked as usual

    rc = ixf.GetText(txt, sizeof(txt));

    .
    .
    .

   }

   if(rc < 0)

// display error message if errors encountered

    DisplayError(&ixf);

   return(0);

  }



//------------------------
// Error message function 
//------------------------

  void DisplayError(IFile *ixf)
  {
   long rc;

// get failure code

   rc = ixf->GetFailure();

// check if failure code has negative value that indicates an error

   if(rc < 0)
   {
    char msg[256], desc[128], txt[20];

    strcpy(msg, "IXFile method failed on");

//  prepare message text according to failure type

    switch(rc)
    {
     case IXF_FAILURE_INTERNAL:
      strcat(msg, " internal operation.");
     break;
     case IXF_FAILURE_OPEN:
      strcat(msg, " file opening.");
     break;
     case IXF_FAILURE_CLOSE:
      strcat(msg, " file closing.");
     break;
     case IXF_FAILURE_FLUSH:
      strcat(msg, " file flushing.");
     break;
     case IXF_FAILURE_READ:
      strcat(msg, " file reading.");
     break;
     case IXF_FAILURE_WRITE:
      strcat(msg, " file writing.");
     break;
     case IXF_FAILURE_GETPOS:
      strcat(msg, " reading file position.");
     break;
     case IXF_FAILURE_SETPOS:
      strcat(msg, " setting file position.");
     break;
     case IXF_FAILURE_GETSIZE:
      strcat(msg, " reading file size.");
     break;
     case IXF_FAILURE_SETSIZE:
      strcat(msg, " changing file size.");
     break;
     case IXF_FAILURE_LOCK:
      strcat(msg, " file locking.");
     break;
     case IXF_FAILURE_UNLOCK:
      strcat(msg, " file unlocking.");
     break;
     case IXF_FAILURE_STAT:
      strcat(msg, " retrieving file information.");
     break;
     case IXF_FAILURE_FILE:
      strcat(msg, " file system operation.");
     break;
     case IXF_FAILURE_LICENSE:
      strcat(msg, " license verification.");
    }

// get system error number and its description

    ixf->GetErrorDescription(desc, sizeof(desc) - 1);
    sprintf(txt, " (%d)", ixf->GetError());

// and append them to the message

    strcat(msg, "\n\n");  
    strcat(msg, desc);
    strcat(msg, txt);

// display complete error information

    printf("%s\n", msg);
   }
  }

BASIC

'----------------
' Main procedure 
'----------------

  Sub Main()

   Dim ixf As IXFile
   Dim txt As String

   Set ixf = New IXFile

' set error handler for processing all errors

   On Error GoTo Err:

   ixf.SetLicenseKey "YOURLICENSEKEY"
   ixf.Initialize   

' temporarily disable error handling to trap errors on file opening
' because in this example it is not an error

   ixf.EnableErrorHandling False

   If (ixf.Open("data.txt") < 0) Then   
    Exit Sub
   End If

' reenable error handling for further operations

   ixf.EnableErrorHandling True

   ixf.GetText txt

   .
   .
   .

   Exit Sub

' error handling procedure

Err: 
   DisplayError ixf
 
  End Sub



'-------------------------
' Error message procedure 
'-------------------------

  Sub DisplayError(ixf As IXFile)
 
   Dim rc As FailureType
   Dim msg As String

' get failure code

   rc = ixf.GetFailure()

' check if failure code has negative value that indicates an error

   If (rc < 0) Then

    msg = "IXFile method failed on"

'  prepare message text according to failure type

    Select Case rc
     Case IXF_FAILURE_INTERNAL
      msg = msg & " internal operation."
     Case IXF_FAILURE_OPEN
      msg = msg & " file opening."
     Case IXF_FAILURE_CLOSE
      msg = msg & " file closing."
     Case IXF_FAILURE_FLUSH
      msg = msg & " file flushing."
     Case IXF_FAILURE_READ
      msg = msg & " file reading."
     Case IXF_FAILURE_WRITE
      msg = msg & " file writing."
     Case IXF_FAILURE_GETPOS
      msg = msg & " reading file position."
     Case IXF_FAILURE_SETPOS
      msg = msg & " file positioning."
     Case IXF_FAILURE_GETSIZE
      msg = msg & " reading file size."
     Case IXF_FAILURE_SETSIZE
      msg = msg & " changing file size."
     Case IXF_FAILURE_LOCK
      msg = msg & " file locking."
     Case IXF_FAILURE_UNLOCK
      msg = msg & " file unlocking."
     Case IXF_FAILURE_STAT:
      msg = msg & " retrieving file information."
     case IXF_FAILURE_FILE:
      msg = msg & " file system operation."
     Case IXF_FAILURE_LICENSE
      msg = msg & " license verification."
    End Select

' append system error number and its description to the message

    msg = msg & Chr(10) & Chr(10) & Err.Description & " (" & Err.Number & ")"

' clear error and failure codes to avoid processing same error twice

    ixf.ClearError

   Else

' non-IXFile error - get its description

    msg = Err.Description

   End If

' display complete error information

   MsgBox msg, vbExclamation Or vbOKOnly

 End Sub

See Also

GetError, GetFailure, GetErrorDescription, ClearError, EnableErrorHandling, IsErrorHandlingEnabled