Controllare un download BITS tramite una connessione costosa
Questo argomento illustra come bloccare il download di un processo BITS tramite una connessione costosa, ad esempio un collegamento cellulare mobile. BITS è un'API asincrona in cui l'applicazione crea un processo, aggiunge URL a tale processo e chiama la funzione Resume dell'oggetto processo. Da questo punto BITS sceglie quando il processo viene scaricato in base a fattori quali la priorità del processo e i criteri di trasferimento. Al termine del download del processo, BITS notifica all'applicazione che l'URL è stato scaricato (se l'applicazione è stata registrata per la notifica di completamento). Durante la durata del processo, se la rete dell'utente finale cambia, ad esempio se l'utente sta viaggiando e sta attualmente incorrendo in tariffe di roaming, BITS sospende il processo fino a quando le condizioni di rete non sono ottimali. Le istruzioni dettagliate seguenti illustrano come creare il processo e specificare le impostazioni appropriate dei criteri di trasferimento.
Prerequisiti
- Microsoft Visual Studio
Istruzioni
Passaggio 1: Includere i file di intestazione BITS necessari
Inserire le direttive di intestazione seguenti all'inizio del file di origine.
#include <bits.h>
#include <bits5_0.h>
Passaggio 2: Inizializzare COM
Prima di creare un'istanza dell'interfaccia IBackgroundCopyManager (usata per creare un processo BITS), è necessario inizializzare COM, impostare il modello di threading COM e specificare un livello di rappresentazione di almeno 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))
{
...
Passaggio 3: Creare un'istanza dell'interfaccia IBackgroundCopyManager
Usare l'interfaccia IBackgroundCopyManager per creare processi di trasferimento, recuperare un oggetto enumeratore che contiene i processi nella coda e recuperare singoli processi dalla coda.
IBackgroundCopyManager* pQueueMgr;
hr = CoCreateInstance(__uuidof(BackgroundCopyManager),
NULL,
CLSCTX_LOCAL_SERVER,
__uuidof(IBackgroundCopyManager),
(void **)&pQueueMgr);
Passaggio 4: Creare il processo BITS
Solo l'utente che crea il processo o un utente con privilegi di amministratore può aggiungere file al processo e modificare le proprietà del processo.
GUID guidJob;
IBackgroundCopyJob* pBackgroundCopyJob;
hr = pQueueMgr->CreateJob(L"TransferPolicy",
BG_JOB_TYPE_DOWNLOAD,
&guidJob,
(IBackgroundCopyJob **)&pBackgroundCopyJob);
Passaggio 5: Specificare l'impostazione dei criteri di trasferimento per il processo
Qui si specificano i criteri di trasferimento dello stato dei costi. È possibile impostare diversi flag BITS_COST_STATE usando una combinazione OR bit per bit per ottenere i risultati desiderati.
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);
}
Esempio
L'esempio di codice seguente illustra come impostare i criteri di trasferimento di un processo BITS in modo che l'elaborazione del processo non si verifichi mentre vengono soddisfatte determinate condizioni, ad esempio quando l'utente è in roaming o ha superato il limite di trasferimento dati mensile.
//*********************************************************
//
// 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;
}