Hinweis
Für den Zugriff auf diese Seite ist eine Autorisierung erforderlich. Sie können versuchen, sich anzumelden oder das Verzeichnis zu wechseln.
Für den Zugriff auf diese Seite ist eine Autorisierung erforderlich. Sie können versuchen, das Verzeichnis zu wechseln.
Sie können die Codebeispiele in diesem Thema als Ausgangspunkt für viele BITS-Anwendungen (Background Intelligent Transfer Service) verwenden, die COM-Initialisierung ausführen, Fehlerbehandlung benötigen und Rückrufbenachrichtigungen empfangen.
Im folgenden Codebeispiel wird eine Ausnahmeklasse zum Behandeln von Fehlern definiert.
class MyException
{
public:
MyException(HRESULT hr, LPWSTR message):Error(hr), Message(message)
{
}
HRESULT Error;
std::wstring Message;
};
Die MyException-Klasse ist eine generische Ausnahmeklasse, die einen HRESULT-Code und eine Fehlerzeichenfolge akzeptiert.
Im folgenden Codebeispiel wird eine Hilfsklasse zum Abrufen von Ressourcen für die CoInitializeEx--Funktion definiert.
class CCoInitializer
{
public:
CCoInitializer( DWORD dwCoInit )
{
HRESULT hr = CoInitializeEx( NULL, dwCoInit );
if (FAILED(hr))
{
throw MyException(hr,L"CoInitialize");
}
}
~CCoInitializer() throw()
{
CoUninitialize();
}
};
Die CCoInitializer-Klasse befasst sich mit der Ressourcenzuordnung und der Deallocation für die COM-Initialisierung. Mit dieser Klasse kann der Destruktor aufgerufen werden, wenn die Klasse außerhalb des Gültigkeitsbereichs ist. Diese Klasse beseitigt die Notwendigkeit der CoUninitialize- Methode, die nach jedem Ausnahmeblock aufgerufen werden soll.
Das folgende Codebeispiel ist die Deklaration der CNotifyInterface-Rückrufschnittstelle.
// Implementation of the Callback interface
//
class CNotifyInterface : public IBackgroundCopyCallback
{
LONG m_lRefCount;
public:
//Constructor
CNotifyInterface() {m_lRefCount = 1;};
//Destructor
~CNotifyInterface() {};
//IUnknown methods
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);
private:
CNotifyInterface(const CNotifyInterface&);
CNotifyInterface& operator=(const CNotifyInterface&);
};
Die von der IBackgroundCopyCallback Schnittstelle abgeleitete CNotifyInterface-Klasse. Die CNotifyInterface-Klasse implementiert die IUnknown-Schnittstelle. Weitere Informationen finden Sie unter IUnknown.
CNotifyInterface verwendet die folgenden Methoden, um Benachrichtigungen zu erhalten, dass ein Auftrag abgeschlossen ist, geändert wurde oder sich in einem Fehlerzustand befindet: JobTransferred, JobModificationund JobError. Alle diese Methoden verwenden ein IBackgroundCopyJob- Auftragsobjekt.
In diesem Beispiel wird die CoTaskMemFree- verwendet, um Arbeitsspeicherressourcen freizugeben.
Das folgende Codebeispiel ist die Implementierung der IBackgroundCopyCallback Rückrufschnittstelle.
HRESULT CNotifyInterface::QueryInterface(REFIID riid, LPVOID* ppvObj)
{
if (riid == __uuidof(IUnknown) || riid == __uuidof(IBackgroundCopyCallback))
{
*ppvObj = this;
}
else
{
*ppvObj = NULL;
return E_NOINTERFACE;
}
AddRef();
return NOERROR;
}
ULONG CNotifyInterface::AddRef()
{
return InterlockedIncrement(&m_lRefCount);
}
ULONG CNotifyInterface::Release()
{
// not thread safe
ULONG ulCount = InterlockedDecrement(&m_lRefCount);
if(0 == ulCount)
{
delete this;
}
return ulCount;
}
HRESULT CNotifyInterface::JobTransferred(IBackgroundCopyJob* pJob)
{
HRESULT hr;
wprintf(L"Job transferred. Completing Job...\n");
hr = pJob->Complete();
if (FAILED(hr))
{
//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.
wprintf(L"Job Completion Failed with error %x\n", hr);
}
PostQuitMessage(0);
//If you do not return S_OK, BITS continues to call this callback.
return S_OK;
}
HRESULT CNotifyInterface::JobModification(IBackgroundCopyJob* pJob, DWORD dwReserved)
{
return S_OK;
}
HRESULT CNotifyInterface::JobError(IBackgroundCopyJob* pJob, IBackgroundCopyError* pError)
{
WCHAR* pszJobName = NULL;
WCHAR* pszErrorDescription = NULL;
//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.
wprintf(L"Job entered error state...\n");
HRESULT hr = pJob->GetDisplayName(&pszJobName);
if (FAILED(hr))
{
wprintf(L"Unable to get job name\n");
}
hr = pError->GetErrorDescription(GetUserDefaultUILanguage(), &pszErrorDescription);
if (FAILED(hr))
{
wprintf(L"Unable to get error description\n");
}
if (pszJobName && pszErrorDescription)
{
wprintf(L"Job %s ",pszJobName);
wprintf(L"encountered the following error:\n");
wprintf(L"%s\n",pszErrorDescription);
}
// Clean up
CoTaskMemFree(pszJobName);
CoTaskMemFree(pszErrorDescription);
PostQuitMessage(hr);
//If you do not return S_OK, BITS continues to call this callback.
return S_OK;
}
Die folgende Headerdatei wird für die allgemeinen Codeklassen verwendet. Diese Klassen werden in den vorherigen Codebeispielen verwendet.
// commoncode.h
#pragma once
//
// Exception class used for error handling
//
class MyException
{
public:
MyException(HRESULT hr, LPWSTR message):Error(hr), Message(message)
{
}
HRESULT Error;
std::wstring Message;
};
// CoInitialize helper class
class CCoInitializer
{
public:
CCoInitializer( DWORD dwCoInit )
{
HRESULT hr = CoInitializeEx( NULL, dwCoInit );
if (FAILED(hr))
{
throw MyException(hr,L"CoInitialize");
}
}
~CCoInitializer() throw()
{
CoUninitialize();
}
};
//
// Implementation of the Callback interface
//
class CNotifyInterface : public IBackgroundCopyCallback
{
LONG m_lRefCount;
public:
//Constructor, Destructor
CNotifyInterface() {m_lRefCount = 1;};
~CNotifyInterface() {};
//IUnknown
HRESULT __stdcall QueryInterface(REFIID riid, LPVOID *ppvObj);
ULONG __stdcall AddRef();
ULONG __stdcall Release();
//IBackgroundCopyCallback2 methods
HRESULT __stdcall JobTransferred(IBackgroundCopyJob* pJob);
HRESULT __stdcall JobError(IBackgroundCopyJob* pJob, IBackgroundCopyError* pError);
HRESULT __stdcall JobModification(IBackgroundCopyJob* pJob, DWORD dwReserved);
private:
CNotifyInterface(const CNotifyInterface&);
CNotifyInterface& operator=(const CNotifyInterface&);
};
Der folgende Beispielcode ist die Implementierung der allgemeinen Codeklassen.
//commoncode.cpp
#include <bits.h>
#include <bits4_0.h>
#include <stdio.h>
#include <tchar.h>
#include <lm.h>
#include <iostream>
#include <exception>
#include <string>
#include <atlbase.h>
#include <memory>
#include <new>
#include "CommonCode.h"
HRESULT CNotifyInterface::QueryInterface(REFIID riid, LPVOID* ppvObj)
{
if (riid == __uuidof(IUnknown) || riid == __uuidof(IBackgroundCopyCallback))
{
*ppvObj = this;
}
else
{
*ppvObj = NULL;
return E_NOINTERFACE;
}
AddRef();
return NOERROR;
}
ULONG CNotifyInterface::AddRef()
{
return InterlockedIncrement(&m_lRefCount);
}
ULONG CNotifyInterface::Release()
{
// not thread safe
ULONG ulCount = InterlockedDecrement(&m_lRefCount);
if(0 == ulCount)
{
delete this;
}
return ulCount;
}
HRESULT CNotifyInterface::JobTransferred(IBackgroundCopyJob* pJob)
{
HRESULT hr;
wprintf(L"Job transferred. Completing Job...\n");
hr = pJob->Complete();
if (FAILED(hr))
{
//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.
wprintf(L"Job Completion Failed with error %x\n", hr);
}
PostQuitMessage(0);
//If you do not return S_OK, BITS continues to call this callback.
return S_OK;
}
HRESULT CNotifyInterface::JobModification(IBackgroundCopyJob* pJob, DWORD dwReserved)
{
return S_OK;
}
HRESULT CNotifyInterface::JobError(IBackgroundCopyJob* pJob, IBackgroundCopyError* pError)
{
WCHAR* pszJobName = NULL;
WCHAR* pszErrorDescription = NULL;
//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.
wprintf(L"Job entered error state...\n");
HRESULT hr = pJob->GetDisplayName(&pszJobName);
if (FAILED(hr))
{
wprintf(L"Unable to get job name\n");
}
hr = pError->GetErrorDescription(GetUserDefaultUILanguage(), &pszErrorDescription);
if (FAILED(hr))
{
wprintf(L"Unable to get error description\n");
}
if (pszJobName && pszErrorDescription)
{
wprintf(L"Job %s ",pszJobName);
wprintf(L"encountered the following error:\n");
wprintf(L"%s\n",pszErrorDescription);
}
CoTaskMemFree(pszJobName);
CoTaskMemFree(pszErrorDescription);
PostQuitMessage(hr);
//If you do not return S_OK, BITS continues to call this callback.
return S_OK;
}
Verwandte Themen