Handling Errors in Native Applications
For applications you develop using Microsoft Visual C++ for Devices, error information can be obtained from the application runtime, the data provider, or by using the Microsoft SQL Server Compact 3.5 (SQL Server Compact 3.5) ActiveX error control objects and collections. Using the SQL Server Compact 3.5 error control objects and collections is the method for handling Replication, RemoteDataAccess, and Engine object errors.
Retrieving Error Information
Applications written with Microsoft Visual C++ for Devices can receive much more detailed information from SQL Server Compact 3.5 than HRESULTs. How you retrieve this extended error information depends on which of the following methods the application uses to interact with SQL Server Compact 3.5:
- OLE DB error objects
The OLE DB provider for SQL Server Compact 3.5 returns a rich set of error objects that can be accessed using OLE DB error objects. The OLE DB error objects store multiple layers of errors and provide additional information beyond standard errors. For more information, see Using OLE DB Error Objects (SQL Server Compact). - SQL Server Compact 3.5 error control objects and collections
The Replication, RemoteDataAccess, and Engine objects reveal error collections and parameters that can be accessed through Visual C++. These native programs reference the SQL Server error objects and collections by adding sqlce_sync.hto the project references and by referencing these files by using the include directive. For more information, see Programming the Native Error Object (SQL Server Compact).
Using the Native Error Control Objects and Collections
The SSCEErrors collection contains an SSCEError object for each error generated. Each SSCEError object contains an SSCEParams collection. The descriptions of errors can be retrieved from SSCEParam objects in the SSCEParams collection. Unlike SQL Server, SQL Server Compact 3.5 returns detailed information about an error as a collection of six parameters. When you build error messages, use a series of nested FOR loops to retrieve each SSCEParam object in the SSCEParams collection for each SSCEError object.
Examples
The following example shows how to display Replication, RemoteDataAccess, and Engine object errors by using Visual C++ for Devices.
// Error handling example
#include "sqlce_sync.h"
void ShowErrors(ISSCEErrors* pISSCEErrors)
{
HRESULT hr;
LONG cbBuf;
LONG i;
LONG lErrorCount;
LONG lErrorIndex;
LONG lParamCount;
LONG lParamIndex;
VARIANT var;
VARIANT varParam;
WCHAR wszBuff[4096];
WCHAR* pwszBuffPos = &wszBuff[0];
BSTR bstr;
ISSCEError* pISSCEError = NULL;
ISSCEParams* pISSCEParams = NULL;
ISSCEParam* pISSCEParam = NULL;
BOOL fSuccess = FALSE;
// Initialize the variants.
VariantInit(&var);
VariantInit(&varParam);
// Get the count of errors.
if(FAILED(hr = pISSCEErrors->get_Count(&lErrorCount))) goto Exit;
if (lErrorCount <= 0)
{
MessageBox(NULL, L"No extended error information.",L"ShowErrors", MB_OK);
fSuccess = TRUE;
goto Exit;
}
// Display errors, one at a time, in a single message box.
// If there are too many errors, they might not all display correctly.
// If so, we recommend that you perform logic based on the number of errors.
for (lErrorIndex = 0; lErrorIndex < lErrorCount; lErrorIndex++)
{
cbBuf = swprintf(pwszBuffPos, L"E R R O R %d of %d\r\n",
lErrorIndex+1, lErrorCount);
pwszBuffPos += cbBuf;
// Get the next error record.
var.vt = VT_I4;
var.lVal = lErrorIndex;
if(FAILED(hr = pISSCEErrors->get_Item(var, &pISSCEError))) goto Exit;
// Error description
if (FAILED(hr = pISSCEError->get_Description(&bstr))) goto Exit;
cbBuf = swprintf(pwszBuffPos, L"DESCRIPTION: '%s'\r\n", bstr);
pwszBuffPos += cbBuf;
SysFreeString(bstr);
// Error number
if (FAILED(hr = pISSCEError->get_Number(&i))) goto Exit;
cbBuf = swprintf(pwszBuffPos, L"NUMBER: %8.8X\r\n", i);
pwszBuffPos += cbBuf;
// Native error
if (FAILED(hr = pISSCEError->get_NativeError(&i))) goto Exit;
cbBuf = swprintf(pwszBuffPos, L"NATIVE_ERROR: %d\r\n", i);
pwszBuffPos += cbBuf;
// Error source
if (FAILED(hr = pISSCEError->get_Source(&bstr))) goto Exit;
cbBuf = swprintf(pwszBuffPos, L"SOURCE: '%s'\r\n", bstr);
pwszBuffPos += cbBuf;
SysFreeString(bstr);
// Retrieve the error parameters.
if (FAILED(hr = pISSCEError->get_Params(&pISSCEParams))) goto Exit;
// Get the number of error parameters.
if (FAILED(hr = pISSCEParams->get_Count(&lParamCount))) goto Exit;
// Display the value of each parameter.
for (lParamIndex = 0; lParamIndex < lParamCount; lParamIndex++)
{
// Get the parameter object.
var.vt = VT_I4;
var.lVal = lParamIndex;
if (FAILED(hr = pISSCEParams->get_Item(var, &pISSCEParam))) goto Exit;
// Get and display the parameter value.
if (FAILED(hr = pISSCEParam->get_Param(&varParam))) goto Exit;
if (VT_I4 == varParam.vt || VT_UI4 == varParam.vt)
{
cbBuf = swprintf(pwszBuffPos, L"P%d: %d\r\n", lParamIndex,
(LONG) varParam.lVal);
}
else if (VT_I2 == varParam.vt || VT_UI2 == varParam.vt)
{
cbBuf = swprintf(pwszBuffPos, L"P%d: %d\r\n", lParamIndex,
(LONG) varParam.iVal);
}
else if (VT_BSTR == varParam.vt)
{
cbBuf = swprintf(pwszBuffPos, L"P%d: '%s'\r\n", lParamIndex,
varParam.bstrVal);
}
pwszBuffPos += cbBuf;
// Clear the variant.
VariantClear(&varParam);
// Release the parameter object.
pISSCEParam->Release();
pISSCEParam = NULL;
}
cbBuf = swprintf(pwszBuffPos, L"\r\n");
pwszBuffPos += cbBuf;
}
// Display the error information.
MessageBox(NULL, wszBuff,L"Error", MB_OK);
fSuccess = TRUE;
Exit:
// Release the parameter object.
if (pISSCEParam)
{
pISSCEParam->Release();
pISSCEParam = NULL;
}
// Release the parameters object.
if (pISSCEParams)
{
pISSCEParams->Release();
pISSCEParams = NULL;
}
// Release the error object.
if (pISSCEError)
{
pISSCEError->Release();
pISSCEError = NULL;
}
// The Errors object is released in calling routine.
if (!fSuccess)
{
MessageBox(NULL, L"Error while processing errors!",L"ShowErrors", MB_OK);
}
return;
}
See Also
Other Resources
Programming the Native Error Object (SQL Server Compact)