透過昂貴的聯機控制 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:指定作業的傳輸原則設定
這是您指定成本狀態傳輸原則的位置。 您可以使用位 OR 組合來設定數個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;
}