|
|||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
Announcements
Chapters
Services
Feature Zones
|
IntroductionBITS is a system service available in Windows 2000, XP, Server 2003, and Vista. It's used by the system to upload and download Internet files; Windows Update uses this service. The service is a basic COM component, and exposes its objects by some interfaces. This article focuses on how to wrap BITS in an application to add, remove, and monitor jobs, add files to jobs, and some other functionality to automate tasks. BackgroundMost probably, BITS was developed to manage background system updates from section to section to maintain up/download data integrity. Actually, only the system uses this service, but Microsoft has documented this "piece of mind" in PSDK, and freely distributes an application to manage it: Using the CodeThe C++ project is created with Visual C++ 2005 Express, PSDK Server 2003 SP1 (2005.03), ATL 3.0 (in PSDK sources), and WTL 7.5 (SourceForge). The WTLWizard is used to create it, but the code was modified to remove the BITS OverviewThe service can upload and download files in the background and foreground, resume jobs when connected, and suspend them when closing the system section. Files are transferred only using the HTTP and HTTPS protocols with or without authentication. The component abstraction uses jobs as the basic unit; a job defines the transfer scheduling model and can contain one or more files. It is identified by an ID. Two or more jobs can have the same name, but not the same ID; names are case sensitive. Each job has its own priority; there are four priority types: low, normal, high, and foreground. For the first three types, the transfer is in the background. Other applications that share the connection can stop the job transfer and take the full bandwidth; jobs in the foreground mode use the full bandwidth. All jobs share the transfer time, so big jobs don't blocks small jobs. Like many basic COM components, BITS exposes a main object, all the others are accessible through the main object.
Creating the Main Component ObjectTo simplify COM programming, the BITS interfaces are transformed in typedef CComPtr<IBackgroundCopyManager> CComBitsManager;
typedef CComPtr<IEnumBackgroundCopyJobs> CComBitsEnumJobs;
typedef CComPtr<IBackgroundCopyJob> CComBitsJob;
typedef CComPtr<IEnumBackgroundCopyFiles> CComBitsEnumFiles;
typedef CComPtr<IBackgroundCopyFile> CComBitsFile;
typedef CComPtr<IBackgroundCopyError> CComBitsError;
All methods of each object are very immediate and simple. BITS is not a complicated component. For methods that return ...
CString strText;
LPWSTR pwstrText = NULL;
hResult = comobj->SomeMethod (&pwstrText);
if (SUCCEEDED (hResult))
{
strText = pwstrText;
::CoTaskMemFree (pwstrText);
}
...
In the example above, the Now, we are ready to use the component. The main object can be created when initializing the application and it is released at exit. A // Create BITS manager object
...
CComBitsManager comBits;
hResult = comBits.CoCreateInstance (__uuidof (BackgroundCopyManager),
NULL, CLSCTX_LOCAL_SERVER);
...
// Release BITS manager object
...
comBits.Release ();
...
All other objects must be queried at the moment you want to use them. Don't query for job enumerator objects and save them for later use, job properties and status inside a job collection are not updated. Always query for a job enumerator at the moment you need to get job properties and status, and release it when you are done, as explained in the next paragraph. Monitoring JobsWhen we need to wrap a service, it is important to get information about its status and the involved objects. In most cases, we cannot save objects to be used later, they most often change in number and form. Each time we want to know how many objects are currently managed by the service, we must query for them. This operation is made in the refresh loop, and objects will be released at the end of the loop. Their status and property values are displayed to the user in a human readable form and saved in other object types. This process takes a lot of work; in the sample code, the refresh time can be customized in the Option dialog, from 1 to 20 seconds. To simplify UI update ( // Enumerating Jobs
...
CComBitsEnumJobs comEnumJobs;
CComBitsJob comJob;
hResult = comBits.EnumJobs (0, &comEnumJobs);
if (SUCCEEDED (hResult))
{
ULONG ulCount = 0;
hResult = comEnumJobs->GetCount (&ulCount);
hResult = comEnumJobs->Reset ();
// signed/unsigned syndrome
int iCount = ulCount;
for (int i = 0; i < iCount; i++)
{
hResult = comEnumJobs->Next (1, &comJob, NULL);
if (SUCCEEDED (hResult))
{
// Get job data and update UI
...
// Get job files and update UI
...
// End using Job
comJob.Release ();
}
}
// End using EnumJobs
comEnumJobs.Release ();
}
...
When a function returns an unsigned value other than a The code above shows how to enumerate jobs. The first parameters of the method // Enumerate Files
...
CComBitsEnumFiles comEnumFiles;
CComBitsFile comFile;
hResult = comJob.EnumFiles (&comEnumFiles);
if (SUCCEEDED (hResult))
{
ULONG ulCount = 0;
hResult = comEnumFiles->GetCount (&ulCount);
hResult = comEnumFiles->Reset ();
// signed/unsigned syndrome
int iCount = ulCount;
for (int i = 0; i < iCount; i++)
{
hResult = comEnumFiles->Next (1, &comFile, NULL);
if (SUCCEEDED (hResult))
{
// Get file data and update UI
...
// End using File
comFile.Release ();
}
}
// End using EnumFiles
comEnumFiles.Release ();
}
...
Enumerating files is similar to enumerating jobs. The job has many properties, a status, and progress data. Properties include the date and time of creation, the transfer priority, the name, ID, and description, the owner, the time delay before trying to connect to a remote server and starting transfers, and a no progress timeout after which the job raises an error and most often loses transferred job data and tries a new connection. These two last parameters are in seconds. The retry delay by default is 10 minutes (600 seconds), the second one is a big timeout - 1,209,600 seconds, corresponding to 14 days - this means if the job cannot transfer data during this time, the status is set to 'error', and the job is reset. The status before this event is called 'transient error'. Progress data is maintained in a struct, the members of the struct are: the total number of files added to the job and the number of transferred files, the total bytes to transfer, and the bytes already transferred. File data is restricted to remote and local file names and the progress, a struct containing three members: the total bytes to transfer, the bytes already transferred, and a completion flag - this flag specifies that the file is available to the user and not that it was fully transferred. To test if a file was completely transferred, compare the transferred and total byte count; if they contain the same value, the file was successfully transferred. Creating and Managing Jobs and FilesAll BITS operations are implemented by the job object, only the job creation is a main object method. The most important property of a job is the ID. This is the only value needed to create a job. The ID must have the ...
// Create a Job
CComBitsJob comJob;
GUID guidID;
hResult = ::UuidCreate (&guidID);
if (SUCCEEDED (hResult))
{
hResult = comBits->CreateJob (TEXT ("The Job"), BG_JOB_TYPE_DOWNLOAD,
&guidID, &comJob);
...
}
...
A newly created job has normal priority and its state is suspended. Use the job's methods to set the initial state and add files: // Job common operations
hResult = comJob->Resume ();
hResult = comJob->Suspend ();
hResult = comJob->Cancel ();
hResult = comJob->Complete ();
The To add files, use the method // Files operations
hResult = comJob->AddFile (strRemoteFile, strLocalFile);
hResult = comJob->AddFileSet (iCount, oFileSetArray);
The remote URL protocol must be HTTP or HTTPS. The URL must specify a static file. Redirection is not supported. If the URL is not valid, the job rejects the file. A job downloads one file at a time in the same order it was added: the first added file is the first transferred. Error HandlingWhen an error occurs, the status of the job becomes ' Update2nd June, 2008
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||