Contoh: Kelas Umum
Anda dapat menggunakan contoh kode dalam topik ini sebagai titik awal untuk banyak aplikasi Background Intelligent Transfer Service (BITS) yang melakukan inisialisasi COM, memerlukan penanganan kesalahan, dan menerima pemberitahuan panggilan balik.
Contoh kode berikut menentukan kelas pengecualian untuk menangani kesalahan.
class MyException
{
public:
MyException(HRESULT hr, LPWSTR message):Error(hr), Message(message)
{
}
HRESULT Error;
std::wstring Message;
};
Kelas MyException adalah kelas pengecualian umum yang menerima kode HRESULT dan string kesalahan.
Contoh kode berikut mendefinisikan kelas pembantu akuisisi sumber daya untuk fungsi CoInitializeEx.
class CCoInitializer
{
public:
CCoInitializer( DWORD dwCoInit )
{
HRESULT hr = CoInitializeEx( NULL, dwCoInit );
if (FAILED(hr))
{
throw MyException(hr,L"CoInitialize");
}
}
~CCoInitializer() throw()
{
CoUninitialize();
}
};
Kelas CCoInitializer menangani alokasi sumber daya dan dealokasi untuk inisialisasi COM. Kelas ini memungkinkan destruktor dipanggil ketika kelas keluar dari cakupan. Kelas ini menghilangkan kebutuhan akan metode CoUninitialize yang akan dipanggil setelah setiap blok pengecualian.
Contoh kode berikut adalah deklarasi antarmuka panggilan balik CNotifyInterface.
// 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&);
};
Kelas CNotifyInterface berasal dari antarmukaIBackgroundCopyCallback. Kelas CNotifyInterface mengimplementasikan antarmuka IUnknown. Untuk informasi selengkapnya, lihat IUnknown.
CNotifyInterface menggunakan metode berikut untuk menerima pemberitahuan bahwa pekerjaan selesai, telah dimodifikasi, atau dalam keadaan kesalahan: JobTransferred, JobModification, dan JobError. Semua metode ini mengambil objek pekerjaanIBackgroundCopyJob.
Contoh ini menggunakan CoTaskMemFree untuk membebaskan sumber daya memori.
Contoh kode berikut adalah implementasi antarmuka panggilan balik IBackgroundCopyCallback.
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;
}
File header berikut digunakan untuk kelas kode umum. Kelas-kelas ini digunakan dalam contoh kode sebelumnya.
// 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&);
};
Contoh kode berikut adalah implementasi kelas kode umum.
//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;
}
Topik terkait