Handling Errors (BITS)

There are two types of errors to handle in your application. The first error is a failed method call. Each method returns an HRESULT value. The reference page for each method identifies the return values that it is most likely to generate. For additional return values, see BITS Return Values. To get the message text associated with the return value, call the IBackgroundCopyManager::GetErrorDescription method.

The second type of error to handle is a job whose state transitions to BG_JOB_STATE_ERROR or BG_JOB_STATE_TRANSIENT_ERROR. To retrieve information related to these types of errors, call the job's IBackgroundCopyJob::GetError method. The method returns an IBackgroundCopyError interface pointer that contains information you use to determine the cause of the error. You can also receive error notification by registering to receive event notification. For details, see Registering a COM Callback.

BITS considers each job to be atomic. If one of the files in the job generates an error, the job remains in an error state until the error is resolved. Thus, you cannot delete the file that is causing the error from the job. However, if the error is caused by the server not being available or an invalid remote file, you can call the IBackgroundCopyJob3::ReplaceRemotePrefix or IBackgroundCopyFile2::SetRemoteName method to identify a new server or file name.

After determining the cause of the error, perform one of the following options:

For an upload-reply job, check the value of the BytesTotal member of the BG_JOB_REPLY_PROGRESS structure to determine if the error occurred on the upload or reply portion of the job. The error occurred on the upload if the value is BG_SIZE_UNKNOWN.

The following example shows how to retrieve an IBackgroundCopyError interface pointer. The example assumes the IBackgroundCopyJob interface pointer is valid.

HRESULT hr = 0;
HRESULT hrError = 0;
IBackgroundCopyJob* pJob;
IBackgroundCopyError* pError = NULL;
IBackgroundCopyFile* pFile = NULL;
WCHAR* pszDescription = NULL;
WCHAR* pszRemoteName = NULL;
BG_ERROR_CONTEXT Context;

hr = pJob->GetError(&pError);
if (SUCCEEDED(hr))
{
  //Retrieve the HRESULT associated with the error. The context tells you
  //where the error occurred, for example, in the transport, queue manager, the 
  //local file, or the remote file.
  pError->GetError(&Context, &hrError);  

  //Retrieve a description associated with the HRESULT value.
  hr = pError->GetErrorDescription(LANGIDFROMLCID(GetThreadLocale()), &pszDescription);
  if (SUCCEEDED(hr))
  {
    if (BG_ERROR_CONTEXT_REMOTE_FILE == Context)
    {
      hr = pError->GetFile(&pFile);  
      if (SUCCEEDED(hr))
      {
        hr = pFile->GetRemoteName(&pszRemoteName);
        if (SUCCEEDED(hr))
        {
          //Do something with the information.
          CoTaskMemFree(pszRemoteName);
        }
        pFile->Release();
      }
    }
    CoTaskMemFree(pszDescription);
  }
  pError->Release();
}
else
{
  //Error information is not available.
}