Управление загрузкой BITS через дорогостоящее подключение
В этом разделе показано, как заблокировать скачивание задания BITS через дорогостоящее подключение, например роуминг сотовой связи. BITS — это асинхронный API, в котором приложение создает задание, добавляет URL-адреса в это задание и вызывает функцию Resume объекта задания. С этого момента BITS выбирает, когда задание загружается на основе таких факторов, как приоритет задания и политика передачи. После завершения загрузки задания BITS уведомляет приложение о том, что URL-адрес загружен (если приложение зарегистрировано для уведомления о завершении). В течение времени существования задания, если сеть конечного пользователя меняется( например, если пользователь перемещается и в настоящее время взимает плату за роуминг), BITS приостановит задание до тех пор, пока сетевые условия не будут оптимальными. Ниже приведены пошаговые инструкции по созданию задания и указанию соответствующих параметров политики передачи.
Предварительные требования
- Microsoft Visual Studio;
Инструкции
Шаг 1. Включение необходимых файлов заголовков BITS
Вставьте следующие директивы заголовка в начало исходного файла.
#include <bits.h>
#include <bits5_0.h>
Шаг 2. Инициализация COM
Перед созданием экземпляра интерфейса IBackgroundCopyManager (используется для создания задания BITS), необходимо инициализировать COM, задать модель потоков COM и указать уровень олицетворения по крайней мере RPC_C_IMP_LEVEL_IMPERSONATE.
// Initialize COM and specify the COM threading model.
HRESULT hr = CoInitializeEx(NULL, COINIT_APARTMENTTHREADED);
if (SUCCEEDED(hr))
{
// Specify an impersonation level of at least RPC_C_IMP_LEVEL_IMPERSONATE.
hr = CoInitializeSecurity(NULL, -1, NULL, NULL,
RPC_C_AUTHN_LEVEL_CONNECT,
RPC_C_IMP_LEVEL_IMPERSONATE,
NULL, EOAC_NONE, 0);
if (SUCCEEDED(hr))
{
...
Шаг 3. Создание экземпляра интерфейса IBackgroundCopyManager
Используйте интерфейс IBackgroundCopyManager для создания заданий передачи, получения объекта перечислителя, содержащего задания в очереди, и извлечения отдельных заданий из очереди.
IBackgroundCopyManager* pQueueMgr;
hr = CoCreateInstance(__uuidof(BackgroundCopyManager),
NULL,
CLSCTX_LOCAL_SERVER,
__uuidof(IBackgroundCopyManager),
(void **)&pQueueMgr);
Шаг 4. Создание задания BITS
Только пользователь, создающий задание, или пользователь с правами администратора может добавлять файлы в задание и изменять свойства задания.
GUID guidJob;
IBackgroundCopyJob* pBackgroundCopyJob;
hr = pQueueMgr->CreateJob(L"TransferPolicy",
BG_JOB_TYPE_DOWNLOAD,
&guidJob,
(IBackgroundCopyJob **)&pBackgroundCopyJob);
Шаг 5. Указание параметра политики передачи для задания
Здесь указывается политика передачи состояния затрат. Для достижения желаемых результатов можно задать несколько флагов BITS_COST_STATE с помощью побитового сочетания ИЛИ .
BITS_JOB_PROPERTY_VALUE propval;
IBackgroundCopyJob5* pBackgroundCopyJob5;
propval.Dword = BITS_COST_STATE_USAGE_BASED
| BITS_COST_STATE_OVERCAP_THROTTLED
| BITS_COST_STATE_BELOW_CAP
| BITS_COST_STATE_CAPPED_USAGE_UNKNOWN
| BITS_COST_STATE_UNRESTRICTED;
hr = pBackgroundCopyJob->QueryInterface(__uuidof(IBackgroundCopyJob5),
reinterpret_cast<void**>(&pBackgroundCopyJob5));
if(SUCCEEDED(hr))
{
pBackgroundCopyJob5->SetProperty(BITS_JOB_PROPERTY_ID_COST_FLAGS, propval);
}
Пример
В следующем примере кода показано, как задать политику передачи задания BITS таким образом, чтобы обработка задания не выполнялась при выполнении определенных условий, например при перемещении пользователя или превышении лимита передачи данных за месяц.
//*********************************************************
//
// Copyright (c) Microsoft. All rights reserved.
// This code is licensed under the Microsoft Public License.
// THIS CODE IS PROVIDED *AS IS* WITHOUT WARRANTY OF
// ANY KIND, EITHER EXPRESS OR IMPLIED, INCLUDING ANY
// IMPLIED WARRANTIES OF FITNESS FOR A PARTICULAR
// PURPOSE, MERCHANTABILITY, OR NON-INFRINGEMENT.
//
//*********************************************************
#define WIN32_LEAN_AND_MEAN // Exclude rarely-used stuff from Windows headers
#include <windows.h>
#include <bits.h>
#include <stdio.h> // define wprintf
int main()
{
HRESULT hr = S_OK;
GUID guidJob;
IBackgroundCopyJob5* pBackgroundCopyJob5;
IBackgroundCopyJob* pBackgroundCopyJob;
IBackgroundCopyManager* pQueueMgr;
BITS_JOB_PROPERTY_VALUE propval;
// Specify the COM threading model.
hr = CoInitializeEx(NULL, COINIT_APARTMENTTHREADED);
if (SUCCEEDED(hr))
{
// The impersonation level must be at least RPC_C_IMP_LEVEL_IMPERSONATE.
hr = CoInitializeSecurity(NULL, -1, NULL, NULL,
RPC_C_AUTHN_LEVEL_CONNECT,
RPC_C_IMP_LEVEL_IMPERSONATE,
NULL, EOAC_NONE, 0);
if (SUCCEEDED(hr))
{
hr = CoCreateInstance(__uuidof(BackgroundCopyManager),
NULL,
CLSCTX_LOCAL_SERVER,
__uuidof(IBackgroundCopyManager),
(void **)&pQueueMgr);
if (FAILED(hr))
{
// Failed to connect to BITS.
wprintf(L"Failed to connect to BITS with error %x\n",hr);
goto done;
}
// Create a BITS job.
wprintf(L"Creating Job...\n");
hr = pQueueMgr->CreateJob(L"TransferPolicy",
BG_JOB_TYPE_DOWNLOAD,
&guidJob,
(IBackgroundCopyJob **)&pBackgroundCopyJob);
if (FAILED(hr))
{
wprintf(L"Failed to Create Job, error = %x\n",hr);
goto cancel;
}
wprintf(L" Job is succesfully created ...\n");
// Set the Transfer Policy for the job.
propval.Dword = BITS_COST_STATE_USAGE_BASED
| BITS_COST_STATE_OVERCAP_THROTTLED
| BITS_COST_STATE_BELOW_CAP
| BITS_COST_STATE_CAPPED_USAGE_UNKNOWN
| BITS_COST_STATE_UNRESTRICTED;
hr = pBackgroundCopyJob->QueryInterface(
__uuidof(IBackgroundCopyJob5),
reinterpret_cast<void**>(&pBackgroundCopyJob5)
);
if (FAILED(hr))
{
wprintf(L"Failed to Create Job, error = %x\n",hr);
goto cancel;
}
pBackgroundCopyJob5->SetProperty(BITS_JOB_PROPERTY_ID_COST_FLAGS, propval);
// Get the Transfer Policy for the new job.
BITS_JOB_PROPERTY_VALUE actual_propval;
wprintf(L"Getting TransferPolicy Property ...\n");
hr = pBackgroundCopyJob5->GetProperty(BITS_JOB_PROPERTY_ID_COST_FLAGS,
&actual_propval);
if (FAILED(hr))
{
// SetSSLSecurityFlags failed.
wprintf(L"GetProperty failed with error %x\n",hr);
goto cancel;
}
DWORD job_transferpolicy = actual_propval.Dword;
wprintf(L"get TransferPolicy Property returned %#x\n", job_transferpolicy);
}
done:
CoUninitialize();
}
return 1;
cancel:
pBackgroundCopyJob->Cancel();
pBackgroundCopyJob->Release();
goto done;
}