Remarque
L’accès à cette page nécessite une autorisation. Vous pouvez essayer de vous connecter ou de modifier des répertoires.
L’accès à cette page nécessite une autorisation. Vous pouvez essayer de modifier des répertoires.
L’une des façons d’appeler les classes COM BITS à partir d’un programme .NET consiste à créer un fichier DLL de référence à partir des fichiers IDL BITS (langage de définition d’interface) dans le Kit de développement logiciel (SDK) Windows, à l’aide des outils MIDL et TLBIMP . La DLL de référence est un ensemble de wrappers de classe pour les classes COM BITS ; vous pouvez ensuite utiliser les classes wrapper directement à partir de .NET.
Une alternative à l’utilisation de DLL de référence créées automatiquement consiste à utiliser un wrapper .NET BITS tiers à partir de GitHub et NuGet. Ces wrappers ont souvent un style de programmation .NET plus naturel, mais ils peuvent se retarder derrière les modifications et mises à jour dans les interfaces BITS.
Création des DLL de référence
Fichiers BITS IDL
Vous allez commencer par l’ensemble de fichiers IDL BITS. Il s’agit de fichiers qui définissent entièrement l’interface COM BITS. Les fichiers se trouvent dans le répertoire des Kits Windows et sont nommés bitsversion.idl (par exemple, bits10_2.idl) à l’exception du fichier version 1.0 qui est simplement Bits.idl. À mesure que de nouvelles versions de BITS sont créées, de nouveaux fichiers IDL BITS sont également créés.
Vous pouvez également modifier une copie des fichiers IDL BITS du SDK pour utiliser des fonctionnalités BITS qui ne sont pas automatiquement converties en équivalents .NET. Les modifications possibles du fichier IDL sont abordées ultérieurement.
Les fichiers IDL BITS incluent plusieurs autres fichiers IDL par référence. Ils s'imbriquent également, ainsi si vous utilisez une version, elle inclut toutes les versions précédentes.
Pour chaque version de BITS que vous souhaitez cibler dans votre programme, vous aurez besoin d’une DLL de référence pour cette version. Par exemple, si vous souhaitez écrire un programme qui fonctionne sur BITS 1.5 et versions ultérieures, mais avec des fonctionnalités supplémentaires lorsque BITS 10.2 est présent, vous devez convertir les fichiers bits1_5.idl et bits10_2.idl.
Utilitaires MIDL et TLBIMP
L’utilitaire MIDL (Microsoft Interface Definition Language) convertit les fichiers IDL qui décrivent l’interface COM BITS en fichier TLB (bibliothèque de types). L’outil MIDL dépend de l’utilitaire CL (préprocesseur C) pour lire correctement le fichier de langage IDL. L’utilitaire CL fait partie de Visual Studio et est installé lorsque vous incluez des fonctionnalités C/C++ dans l’installation de Visual Studio.
L’utilitaire MIDL crée normalement un ensemble de fichiers C et H (code de langage C et en-tête de langage C). Vous pouvez supprimer ces fichiers supplémentaires en envoyant la sortie au périphérique NUL: Par exemple, la définition de l'option /dlldata NUL: empêchera la création d'un fichier dlldata.c. Les exemples de commandes ci-dessous indiquent quels commutateurs doivent être définis sur NUL :.
L’utilitaire TLBIMP (Importateur de bibliothèque de types) lit dans un fichier TLB et crée le fichier DLL de référence correspondant.
Exemples de commandes pour MIDL et TLBIMP
Il s’agit d’un exemple de l’ensemble complet de commandes pour générer un ensemble de fichiers de référence. Vous devrez peut-être modifier les commandes en fonction de votre installation du Kit de développement logiciel (SDK) Visual Studio et Windows, et en fonction des fonctionnalités bits et des versions de système d’exploitation que vous ciblez.
L’exemple crée un répertoire pour placer les fichiers DLL de référence et crée une variable d’environnement BITSTEMP pour pointer vers ce répertoire.
Les exemples de commandes exécutent ensuite le fichier vsdevcmd.bat créé par le programme d’installation de Visual Studio. Ce fichier BAT configure vos chemins d’accès et certaines variables d’environnement afin que les commandes MIDL et TLBIMP s’exécutent. Il configure également les variables WindowsSdkDir et WindowsSDKLibVersion pour pointer vers les répertoires du SDK Windows les plus récents.
REM Create a working directory
REM You can select a different directory based on your needs.
SET BITSTEMP=C:\BITSTEMPDIR
MKDIR "%BITSTEMP%"
REM Run the VsDevCmd.bat file to locate the Windows
REM SDK directory and the tools directories
REM This will be different for different versions of
REM Visual Studio
CALL "C:\Program Files (x86)\Microsoft Visual Studio\2017\Enterprise\Common7\Tools\vsdevcmd.bat"
REM Run the MIDL command on the desired BITS IDL file
REM This will generate a TLB file for the TLBIMP command
REM The IDL file will be different depending on which
REM set of BITS interfaces you need to use.
REM Run the MIDL command once per reference file
REM that you will need to explicitly use.
PUSHD .
CD /D "%WindowsSdkDir%Include\%WindowsSDKLibVersion%um"
MIDL /I ..\shared /out "%BITSTEMP%" bits1_5.idl /dlldata NUL: /header NUL: /iid NUL: /proxy NUL:
MIDL /I ..\shared /out "%BITSTEMP%" bits4_0.idl /dlldata NUL: /header NUL: /iid NUL: /proxy NUL:
MIDL /I ..\shared /out "%BITSTEMP%" bits5_0.idl /dlldata NUL: /header NUL: /iid NUL: /proxy NUL:
MIDL /I ..\shared /out "%BITSTEMP%" bits10_1.idl /dlldata NUL: /header NUL: /iid NUL: /proxy NUL:
MIDL /I ..\shared /out "%BITSTEMP%" bits10_2.idl /dlldata NUL: /header NUL: /iid NUL: /proxy NUL:
REM Run the TLBIMP command on the resulting TLB file(s)
REM Try to keep a parallel set of names.
TLBIMP "%BITSTEMP%"\bits1_5.tlb /out: "%BITSTEMP%"\BITSReference1_5.dll
TLBIMP "%BITSTEMP%"\bits4_0.tlb /out: "%BITSTEMP%"\BITSReference4_0.dll
TLBIMP "%BITSTEMP%"\bits5_0.tlb /out: "%BITSTEMP%"\BITSReference5_0.dll
TLBIMP "%BITSTEMP%"\bits10_1.tlb /out: "%BITSTEMP%"\BITSReference10_1.dll
TLBIMP "%BITSTEMP%"\bits10_2.tlb /out: "%BITSTEMP%"\BITSReference10_2.dll
DEL "%BITSTEMP%"\bits*.tlb
POPD
Une fois ces commandes exécutées, vous aurez un ensemble de DLL de référence dans le répertoire BITSTEMP.
Ajout des DLL de référence à votre projet
Pour utiliser une DLL de référence dans un projet C#, ouvrez votre projet C# dans Visual Studio. Dans l’Explorateur de solutions, cliquez avec le bouton droit sur les références, puis cliquez sur Ajouter une référence. Cliquez ensuite sur le bouton Parcourir, puis sur le bouton Ajouter. Accédez au répertoire avec les DLL de référence, sélectionnez-les, puis cliquez sur Ajouter. Dans la fenêtre Gestionnaire de références, les DLL de référence sont cochées. Cliquez ensuite sur OK.
Les DLL de référence BITS sont désormais ajoutées à votre projet.
Les informations contenues dans les fichiers DLL de référence seront incorporées dans votre programme final. Vous n’avez pas besoin d’expédier les fichiers DLL de référence avec votre programme ; vous devez simplement expédier le .EXE.
Vous pouvez modifier si les DLL de référence sont incorporées dans l’EXE final. Utilisez la propriété Embed Interop Types pour définir si les DLL de référence seront incorporées ou non. Cette opération peut être effectuée par référence. La valeur par défaut est True pour incorporer les DLL.
Modification des fichiers IDL pour un code .NET plus complet
Les fichiers BITS IDL (Microsoft Interface Definition Language) peuvent être utilisés sans modification pour rendre le fichier DLL BackgroundCopyManager. Toutefois, la DLL de référence .NET résultante manque certaines unions non translatables et a des noms difficiles à utiliser pour certaines structures et énumérations. Cette section décrit certaines des modifications que vous pouvez apporter pour rendre la DLL .NET plus complète et plus facile à utiliser.
Noms ENUM plus simples
Les fichiers IDL BITS définissent généralement des valeurs d’énumération comme suit :
typedef enum
{
BG_AUTH_TARGET_SERVER = 1,
BG_AUTH_TARGET_PROXY
} BG_AUTH_TARGET;
Le BG_AUTH_TARGET est le nom du typedef ; l’énumération réelle n’est pas nommée. Cela ne provoque généralement pas de problèmes avec le code C, mais ne se traduit pas correctement pour une utilisation avec un programme .NET. Un nouveau nom est automatiquement créé, mais il peut ressembler à _MIDL___MIDL_itf_bits4_0_0005_0001_0001 au lieu d’une valeur lisible par l’homme. Vous pouvez résoudre ce problème en mettant à jour les fichiers MIDL pour inclure un nom d’énumération.
typedef enum BG_AUTH_TARGET
{
BG_AUTH_TARGET_SERVER = 1,
BG_AUTH_TARGET_PROXY
} BG_AUTH_TARGET;
Le nom d’énumération est autorisé à être identique au nom typedef. Certains programmeurs ont une convention de nommage où les noms sont maintenus différents (par exemple, en plaçant un trait de soulignement avant le nom de l’énumération), mais cela ne fera que perturber les traductions .NET.
Types de chaînes dans des unions
Les fichiers IDL BITS transmettent des chaînes à l'aide de la convention LPWSTR (pointeur long vers une chaîne de caractères larges). Bien que cela fonctionne lors du passage de paramètres de fonction (comme la méthode Job.GetDisplayName([out] LPWSTR *pVal), il ne fonctionne pas lorsque les chaînes font partie d’unions. Par exemple, le fichier bits5_0.idl inclut l’union BITS_FILE_PROPERTY_VALUE :
typedef [switch_type(BITS_FILE_PROPERTY_ID)] union
{
[case( BITS_FILE_PROPERTY_ID_HTTP_RESPONSE_HEADERS )]
LPWSTR String;
}
BITS_FILE_PROPERTY_VALUE;
Le champ LPWSTR ne sera pas inclus dans la version .NET de l’union. Pour résoudre ce problème, remplacez LPWSTR par un WCHAR*. Le champ résultant (appelé String) sera passé en tant qu'IntPtr. Convertissez ceci en chaîne à l’aide de la méthode System.Runtime.InteropServices.Marshal.PtrToStringAuto(value.String);.
Unions dans des structures
Parfois, les unions incorporées dans des structures ne seront pas incluses dans la structure du tout. Par exemple, dans le Bits1_5.idl, la BG_AUTH_CREDENTIALS est définie comme suit :
typedef struct
{
BG_AUTH_TARGET Target;
BG_AUTH_SCHEME Scheme;
[switch_is(Scheme)] BG_AUTH_CREDENTIALS_UNION Credentials;
}
BG_AUTH_CREDENTIALS;
Le BG_AUTH_CREDENTIALS_UNION est défini comme une union, de la manière suivante :
typedef [switch_type(BG_AUTH_SCHEME)] union
{
[case( BG_AUTH_SCHEME_BASIC, BG_AUTH_SCHEME_DIGEST, BG_AUTH_SCHEME_NTLM,
BG_AUTH_SCHEME_NEGOTIATE, BG_AUTH_SCHEME_PASSPORT )] BG_BASIC_CREDENTIALS Basic;
[default] ;
} BG_AUTH_CREDENTIALS_UNION;
Le champ Informations d’identification du BG_AUTH_CREDENTIALS ne sera pas inclus dans la définition de classe .NET.
Notez que l’union est définie pour toujours être une BG_BASIC_CREDENTIALS quelle que soit la BG_AUTH_SCHEME. Comme l’union n’est pas utilisée comme une union, nous pouvons simplement passer un BG_BASIC_CREDENTIALS de cette manière :
typedef struct
{
BG_AUTH_TARGET Target;
BG_AUTH_SCHEME Scheme;
BG_BASIC_CREDENTIALS Credentials;
}
BG_AUTH_CREDENTIALS;
Utilisation de BITS à partir de C#
Instruction Using recommandée
La configuration de certaines instructions using en C# réduit le nombre de caractères que vous devez taper pour utiliser les différentes versions de BITS. Le nom « BITSReference » provient du nom de la DLL de référence.
// Set up the BITS namespaces
using BITS = BITSReference1_5;
using BITS4 = BITSReference4_0;
using BITS5 = BITSReference5_0;
using BITS10_2 = BITSReference10_2;
Exemple rapide : télécharger un fichier
Un extrait de code C# court mais complet pour télécharger un fichier à partir d’une URL est indiqué ci-dessous.
var mgr = new BITS.BackgroundCopyManager1_5();
BITS.GUID jobGuid;
BITS.IBackgroundCopyJob job;
mgr.CreateJob("Quick download", BITS.BG_JOB_TYPE.BG_JOB_TYPE_DOWNLOAD, out jobGuid, out job);
job.AddFile("https://aka.ms/WinServ16/StndPDF", @"C:\Server2016.pdf");
job.Resume();
bool jobIsFinal = false;
while (!jobIsFinal)
{
BITS.BG_JOB_STATE state;
job.GetState(out state);
switch (state)
{
case BITS.BG_JOB_STATE.BG_JOB_STATE_ERROR:
case BITS.BG_JOB_STATE.BG_JOB_STATE_TRANSFERRED:
job.Complete();
break;
case BITS.BG_JOB_STATE.BG_JOB_STATE_CANCELLED:
case BITS.BG_JOB_STATE.BG_JOB_STATE_ACKNOWLEDGED:
jobIsFinal = true;
break;
default:
Task.Delay(500); // delay a little bit
break;
}
}
// Job is complete
Dans cet exemple de code, un gestionnaire BITS nommé mgr est créé. Il correspond directement à l’interface IBackgroundCopyManager .
Un nouveau poste est créé par le responsable. La tâche est un paramètre de sortie sur la méthode CreateJob. Dans les données transmises figurent également le nom de la tâche (qui n’a pas besoin d’être unique) et le type de téléchargement, qui est une tâche de téléchargement. Un GUID BITS est également renseigné pour l’identificateur de tâche.
Une fois le travail créé, vous ajoutez un nouveau fichier de téléchargement au travail avec la méthode AddFile. Vous devez passer deux chaînes, une pour le fichier distant (l’URL ou le partage de fichiers) et l’autre pour le fichier local.
Après avoir ajouté le fichier, appelez Resume sur le travail pour le démarrer. Ensuite, le code attend que le travail soit dans un état final (ERREUR ou TRANSFÉRÉ) et le processus est alors terminé.
"Versions BITS, Conversion de type et QueryInterface"
Vous constaterez que vous devez souvent utiliser à la fois une version antérieure d’un objet BITS et une version plus récente dans votre programme.
Par exemple, lorsque vous créez un objet de travail, vous obtenez un IBackgroundCopyJob (partie de BITS version 1.0), même lorsque vous le faites à l’aide d’un objet de gestionnaire plus récent et qu’un objet IBackgroundCopyJob plus récent est disponible. Étant donné que la méthode CreateJob n’accepte pas d’interface pour la version la plus récente, vous ne pouvez pas rendre directement la version la plus récente.
Utilisez un cast .NET pour convertir un objet de type plus ancien en objet de type plus récent. Le cast appelle automatiquement une requête COM QueryInterface selon les besoins.
Dans cet exemple, il existe un objet IBackgroundCopyJob BITS nommé « job », et nous voulons le convertir en objet IBackgroundCopyJob5 nommé « job5 » afin de pouvoir appeler la méthode BITS 5.0 GetProperty. Nous allons simplement effectuer un cast vers le type IBackgroundCopyJob5 comme suit :
var job5 = (BITS5.IBackgroundCopyJob5)job;
La variable job5 est initialisée par .NET à l’aide de la requête QueryInterface correcte.
Si votre code peut s'exécuter sur un système qui ne prend pas en charge une version particulière de BITS, vous pouvez essayer de réaliser un « cast » et intercepter une « System.InvalidCastException ».
BITS5.IBackgroundCopyJob5 job5 = null;
try
{
job5 = (BITS5.IBackgroundCopyJob5)Job;
}
catch (System.InvalidCastException)
{
; // Must be running an earlier version of BITS
}
Un problème courant est lorsque vous essayez de convertir dans le mauvais type d'objet. Le système .NET ne connaît pas la relation réelle entre les interfaces BITS. Si vous demandez un type d'interface incorrect, .NET tente de la créer pour vous et échoue avec l'InvalidCastException et l'HResult 0x80004002 (E_NOINTERFACE).
Utilisation des versions 10_1 et 10_2 de BITS
Dans certaines versions de Windows 10, vous ne pouvez pas créer directement un objet BITS IBackgroundCopyManager à l’aide des interfaces 10.1 ou 10.2. Au lieu de cela, vous devez utiliser plusieurs versions des fichiers de référence DLL BackgroundCopyManager. Par exemple, vous pouvez utiliser la version 1.5 pour créer un objet IBackgroundCopyManager, puis convertir les objets de travail ou de fichier résultants à l’aide des versions 10.1 ou 10.2.