Share via


Interfaz IBackgroundCopyCallback2 (bits3_0.h)

Implemente esta interfaz para recibir una notificación de que un archivo ha completado la descarga. En lugar de sondear el estado de descarga de un archivo, los clientes usan esta interfaz.

Para recibir notificaciones, llame al método IBackgroundCopyJob::SetNotifyInterface para especificar el puntero de interfaz a la implementación de IBackgroundCopyCallback . Para especificar qué notificaciones desea recibir, llame al método IBackgroundCopyJob::SetNotifyFlags .

Debe implementar todos los métodos de esta interfaz y la interfaz IBackgroundCopyCallback . Por ejemplo, si no se registra para la devolución de llamada transferida del archivo, el método FileTransferred todavía debe devolver S_OK. Si no desea recibir la devolución de llamada transferida del archivo, simplemente puede implementar IBackgroundCopyCallback en su lugar.

Herencia

La interfaz IBackgroundCopyCallback2 hereda de IBackgroundCopyCallback. IBackgroundCopyCallback2 también tiene estos tipos de miembros:

Métodos

La interfaz IBackgroundCopyCallback2 tiene estos métodos.

 
IBackgroundCopyCallback2::FileTransferred

BITS llama a la implementación del método FileTransferred cuando BITS finaliza correctamente la transferencia de un archivo.

Comentarios

Para obtener más información sobre cómo implementar esta interfaz, consulte la interfaz IBackgroundCopyCallback .

Ejemplos

En el ejemplo siguiente se muestra una implementación de IBackgroundCopyCallback2 . En este ejemplo también se muestra cómo controlar las llamadas reentrantes en la devolución de llamada JobModification para un modelo de apartamento de un solo subproceso.

#define TWO_GB 2147483648    // 2GB


class CNotifyInterface : public IBackgroundCopyCallback2
{
  LONG m_lRefCount;
  LONG m_PendingJobModificationCount;

public:
  //Constructor, Destructor
  CNotifyInterface() {m_lRefCount = 1; m_PendingJobModificationCount = 0;};
  ~CNotifyInterface() {};

  //IUnknown
  HRESULT __stdcall QueryInterface(REFIID riid, LPVOID *ppvObj);
  ULONG __stdcall AddRef();
  ULONG __stdcall Release();

  //IBackgroundCopyCallback methods
  HRESULT __stdcall JobTransferred(IBackgroundCopyJob* pJob);
  HRESULT __stdcall JobError(IBackgroundCopyJob* pJob, IBackgroundCopyError* pError);
  HRESULT __stdcall JobModification(IBackgroundCopyJob* pJob, DWORD dwReserved);
  HRESULT __stdcall FileTransferred(IBackgroundCopyJob* pJob, IBackgroundCopyFile* pFile);
};

HRESULT CNotifyInterface::QueryInterface(REFIID riid, LPVOID* ppvObj) 
{
  if (riid == __uuidof(IUnknown) || 
      riid == __uuidof(IBackgroundCopyCallback) ||
      riid == __uuidof(IBackgroundCopyCallback2)) 
  {
    *ppvObj = this;
  }
  else
  {
    *ppvObj = NULL;
    return E_NOINTERFACE;
  }

  AddRef();
  return NOERROR;
}

ULONG CNotifyInterface::AddRef() 
{
  return InterlockedIncrement(&m_lRefCount);
}

ULONG CNotifyInterface::Release() 
{
  ULONG  ulCount = InterlockedDecrement(&m_lRefCount);

  if(0 == ulCount) 
  {
    delete this;
  }

  return ulCount;
}

HRESULT CNotifyInterface::JobTransferred(IBackgroundCopyJob* pJob)
{
  HRESULT hr;

  //Add logic that will not block the callback thread. If you need to perform
  //extensive logic at this time, consider creating a separate thread to perform
  //the work.

  hr = pJob->Complete();
  if (FAILED(hr))
  {
    //Handle error. BITS probably was unable to rename one or more of the 
    //temporary files. See the Remarks section of the IBackgroundCopyJob::Complete 
    //method for more details.
  }

  //If you do not return S_OK, BITS continues to call this callback.
  return S_OK;
}

HRESULT CNotifyInterface::JobError(IBackgroundCopyJob* pJob, IBackgroundCopyError* pError)
{
  HRESULT hr;
  BG_FILE_PROGRESS Progress;
  BG_ERROR_CONTEXT Context;
  HRESULT ErrorCode = S_OK;
  WCHAR* pszJobName = NULL;
  WCHAR* pszErrorDescription = NULL;
  BOOL IsError = TRUE;

  //Use pJob and pError to retrieve information of interest. For example,
  //if the job is an upload reply, call the IBackgroundCopyError::GetError method 
  //to determine the context in which the job failed. If the context is 
  //BG_JOB_CONTEXT_REMOTE_APPLICATION, the server application that received the 
  //upload file failed.

  hr = pError->GetError(&Context, &ErrorCode);

  //If the proxy or server does not support the Content-Range header or if
  //antivirus software removes the range requests, BITS returns BG_E_INSUFFICIENT_RANGE_SUPPORT.
  //This implementation tries to switch the job to foreground priority, so
  //the content has a better chance of being successfully downloaded.
  if (BG_E_INSUFFICIENT_RANGE_SUPPORT == ErrorCode)
  {
    hr = pError->GetFile(&pFile);
    hr = pFile->GetProgress(&Progress);
    if (BG_SIZE_UNKNOWN == Progress.BytesTotal)
    {
      //The content is dynamic, do not change priority. Handle as an error.
    }
    else if (Progress.BytesTotal > TWO_GB)
    {
      //BITS does not use range requests if the content is less than 2 GB. 
      //However, if the content is greater than 2 GB, BITS
      //uses 2 GB ranges to download the file, so switching to foreground 
      //priority will not help.
    }
    else
    {
      hr = pJob->SetPriority(BG_JOB_PRIORITY_FOREGROUND);
      hr = pJob->Resume();
      IsError = FALSE;
    }

    pFile->Release();
  }

  if (TRUE == IsError)
  {
    hr = pJob->GetDisplayName(&pszJobName);
    hr = pError->GetErrorDescription(LANGIDFROMLCID(GetThreadLocale()), &pszErrorDescription);

    if (pszJobName && pszErrorDescription)
    {
      //Do something with the job name and description. 
    }

    CoTaskMemFree(pszJobName);
    CoTaskMemFree(pszErrorDescription);
  }

  //If you do not return S_OK, BITS continues to call this callback.
  return S_OK;
}

HRESULT CNotifyInterface::JobModification(IBackgroundCopyJob* pJob, DWORD dwReserved)
{
  HRESULT hr;
  WCHAR* pszJobName = NULL;
  BG_JOB_PROGRESS Progress;
  BG_JOB_STATE State;

  //If you are already processing a callback, ignore this notification.
  if (InterlockedCompareExchange(&m_PendingJobModificationCount, 1, 0) == 1)
  {
    return S_OK;
  }

  hr = pJob->GetDisplayName(&pszJobName);
  if (SUCCEEDED(hr))
  {
    hr = pJob->GetProgress(&Progress);
    if (SUCCEEDED(hr))
    {
      hr = pJob->GetState(&State);
      if (SUCCEEDED(hr))
      {
        //Do something with the progress and state information.
        //BITS generates a high volume of modification
        //callbacks. Use this callback with discretion. Consider creating a timer and 
        //polling for state and progress information.
      }
    }
    CoTaskMemFree(pszJobName);
  }

  m_PendingJobModificationCount = 0;

  return S_OK;
}

HRESULT CNotifyInterface::FileTransferred(IBackgroundCopyJob* pJob, IBackgroundCopyFile* pFile)
{
  HRESULT hr = S_OK;
  IBackgroundCopyFile3* pFile3 = NULL;
  BOOL IsValid = FALSE;

  hr = pFile->QueryInterface(__uuidof(IBackgroundCopyFile3), (void**)&pFile3);
  if (SUCCEEDED(hr))
  {
    // Add code to validate downloaded content and set IsValid.

    hr = pFile3->SetValidationState(IsValid);
    if (FAILED(hr))
    {
      // Handle error
    }

    pFile3->Release();
  }

	return S_OK;
}

Requisitos

Requisito Value
Cliente mínimo compatible Windows Vista
Servidor mínimo compatible Windows Server 2008
Plataforma de destino Windows
Encabezado bits3_0.h (incluya Bits.h)

Consulte también

IBackgroundCopyCallback

IBackgroundCopyJob::SetNotifyFlags

IBackgroundCopyJob::SetNotifyInterface