Poznámka:
Přístup k této stránce vyžaduje autorizaci. Můžete se zkusit přihlásit nebo změnit adresáře.
Přístup k této stránce vyžaduje autorizaci. Můžete zkusit změnit adresáře.
Jedním ze způsobů, jak volat COM třídy služby BITS z programu .NET, je vytvořit referenční soubor DLL počínaje soubory BITS IDL (Interface Definition Language) v sadě Windows SDK, za použití nástrojů MIDL a TLBIMP. Referenční knihovna DLL je sada obálek tříd pro třídy BITS COM; pak můžete použít tyto obálky tříd přímo z .NET.
Alternativou k použití automaticky vytvořených referenčních knihoven DLL je použití obálky .NET BITS třetí strany z GitHubu a NuGet. Tyto obálky mají často přirozenější programovací styl .NET, ale můžou zaostávat za změnami a aktualizacemi v rozhraních BITS.
Vytvoření referenčních knihoven DLL
Soubory BITS IDL
Začnete se sadou souborů BITS IDL. Jedná se o soubory, které plně definují rozhraní BITS COM. Soubory jsou umístěny v adresáři Windows Kits a jsou pojmenované bityverze.idl (například bits10_2.idl) s výjimkou souboru verze 1.0, který je jen Bits.idl. Při vytváření nových verzí BITS se vytvoří také nové soubory BITS IDL.
Můžete také upravit kopii souborů BITS IDL sady SDK tak, aby používaly funkce BITS, které se automaticky nepřevádějí na ekvivalenty .NET. Možné změny souborů IDL jsou popsány později.
Soubory BITS IDL obsahují několik dalších souborů IDL pomocí odkazu. Vnořují se také, takže pokud používáte jednu verzi, zahrnuje všechny nižší verze.
Pro každou verzi služby BITS, na kterou chcete cílit ve svém programu, budete potřebovat jednu referenční knihovnu DLL pro tuto verzi. Pokud například chcete napsat program, který funguje na bits 1.5 a novější, ale má další funkce, pokud je bits 10.2 k dispozici, musíte převést jak bits1_5.idl, tak soubory bits10_2.idl.
Nástroje MIDL a TLBIMP
Nástroj MIDL (Microsoft Interface Definition Language) převede soubory IDL, které popisují rozhraní BITS COM, do souboru TLB (Knihovna typů). Nástroj MIDL závisí na nástroji CL (preprocesor jazyka C), aby správně četl soubor jazyka IDL. Nástroj CL je součástí sady Visual Studio a nainstaluje se při zahrnutí funkcí C/C++ do instalace sady Visual Studio.
Nástroj MIDL obvykle vytvoří sadu souborů C a H (kód jazyka C a hlavička jazyka C). Tyto nadbytečné soubory můžete potlačit odesláním výstupu do zařízení NUL: Například nastavení /dlldata NUL: přepínač potlačí vytvoření souboru dlldata.c. Následující ukázkové příkazy ukazují, které přepínače by měly být nastaveny na hodnotu NUL:.
Nástroj TLBIMP (Type Library Importer) čte v souboru TLB a vytvoří odpovídající referenční soubor DLL.
Ukázkové příkazy pro MIDL a TLBIMP
Toto je příklad kompletní sady příkazů pro vygenerování sady referenčních souborů. Možná budete muset upravit příkazy na základě instalace Visual Studio a Windows SDK a kvůli funkcím BITS a verzím operačního systému, na které cílíte.
Příklad vytvoří adresář pro umístění referenčních souborů DLL a vytvoří proměnnou prostředí BITSTEMP, která bude odkazovat na tento adresář.
Ukázkové příkazy pak spustí soubor vsdevcmd.bat vytvořený instalačním programem sady Visual Studio. Tento soubor BAT nastaví cesty a některé proměnné prostředí tak, aby se spustily příkazy MIDL a TLBIMP. Nastaví také proměnné WindowsSdkDir a WindowsSDKLibVersion tak, aby odkazovaly na nejnovější adresáře sady Windows SDK.
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
Po spuštění těchto příkazů budete mít v adresáři BITSTEMP sadu referenčních knihoven DLL.
Přidání referenčních knihoven DLL do vašeho projektu
Pokud chcete v projektu jazyka C# použít referenční knihovnu DLL, otevřete projekt jazyka C# v sadě Visual Studio. V Průzkumníku řešení klikněte pravým tlačítkem myši na Odkazy a klikněte na Přidat odkaz. Potom klikněte na tlačítko Procházet a potom na tlačítko Přidat. Přejděte do adresáře s referenčními knihovnami DLL, vyberte je a klikněte na přidat. V okně Správce odkazů se zkontrolují referenční knihovny DLL. Potom klepněte na tlačítko OK.
K Vašemu projektu byly nyní přidány referenční knihovny DLL služby BITS.
Informace v referenčních souborech DLL budou vloženy do konečného programu. Referenční soubory DLL nemusíte dodávat s programem; Stačí poslat .EXE.
Můžete změnit, zda jsou referenční knihovny DLL vloženy do konečné exe. Pomocí vlastnosti Vložit typy interoperability nastavte, zda budou vloženy referenční knihovny DLL. To lze provést pro každý odkaz zvlášť. Výchozí hodnota je True pro vložení knihoven DLL.
Úprava souborů IDL pro podrobnější kód .NET
Soubory BITS IDL (Microsoft Interface Definition Language) lze použít beze změny k vytvoření souboru DLL BackgroundCopyManager. Výsledná referenční knihovna DLL .NET však nebude mít některé nepřeložitelné unie a má nesnadno použitelné názvy pro některé struktury a výčty. Tato část popisuje některé změny, které můžete udělat, aby knihovna DLL .NET byla dokončena a snadněji se používala.
Jednodušší názvy výčtů
Soubory BITS IDL obvykle definují hodnoty výčtu takto:
typedef enum
{
BG_AUTH_TARGET_SERVER = 1,
BG_AUTH_TARGET_PROXY
} BG_AUTH_TARGET;
BG_AUTH_TARGET je název typedef; skutečný výčt není pojmenován. To obvykle nezpůsobuje problémy s kódem jazyka C, ale nepřekládá se dobře pro použití s programem .NET. Automaticky se vytvoří nový název, ale místo hodnoty čitelné pro člověka může vypadat něco jako _MIDL___MIDL_itf_bits4_0_0005_0001_0001. Tento problém můžete vyřešit tak, že upravíte soubory MIDL, aby obsahovaly název výčtu.
typedef enum BG_AUTH_TARGET
{
BG_AUTH_TARGET_SERVER = 1,
BG_AUTH_TARGET_PROXY
} BG_AUTH_TARGET;
Název výčtu může být stejný jako název typedef. Někteří programátoři mají konvenci pojmenování, kde jsou názvy výčtů odlišeny (například vložením podtržítka před název výčtu), ale to pouze mate při překladu .NET.
Typy řetězců ve sjednoceních
Soubory IDL služby BITS předávají řetězce pomocí konvence LPWSTR (dlouhý ukazatel na širokoznakový řetězec). I když to funguje při předávání parametrů funkce (například metoda Job.GetDisplayName([out] LPWSTR *pVal)), nefunguje to, když jsou řetězce součástí Unie. Například soubor bits5_0.idl obsahuje unii 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;
Pole LPWSTR nebude součástí verze .NET unie. Pokud chcete tento problém vyřešit, změňte LPWSTR na WCHAR*. Výsledné pole (označované jako Řetězec) se předá jako IntPtr. Převeďte to na řetězec pomocí metody System.Runtime.InteropServices.Marshal.PtrToStringAuto(value.String).
Sjednocení ve strukturách
Někdy se celky vložené do struktur vůbec nezahrnou do dané struktury. Například v souboru Bits1_5.idl je BG_AUTH_CREDENTIALS definován takto:
typedef struct
{
BG_AUTH_TARGET Target;
BG_AUTH_SCHEME Scheme;
[switch_is(Scheme)] BG_AUTH_CREDENTIALS_UNION Credentials;
}
BG_AUTH_CREDENTIALS;
BG_AUTH_CREDENTIALS_UNION je definována jako unie takto:
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;
Pole Pověření v BG_AUTH_CREDENTIALS nebude součástí definice třídy .NET.
Všimněte si, že spojení je definováno tak, že vždy bude BG_BASIC_CREDENTIALS bez ohledu na BG_AUTH_SCHEME. Vzhledem k tomu, že unie se nepoužívá jako unie, můžeme jednoduše předat BG_BASIC_CREDENTIALS takto:
typedef struct
{
BG_AUTH_TARGET Target;
BG_AUTH_SCHEME Scheme;
BG_BASIC_CREDENTIALS Credentials;
}
BG_AUTH_CREDENTIALS;
Použití služby BITS z jazyka C#
Doporučený příkaz using
Nastavení některých příkazů using v jazyce C# sníží počet znaků, které je potřeba zadat, aby bylo možné použít různé verze služby BITS. Název BITSReference pochází z názvu referenční knihovny DLL.
// Set up the BITS namespaces
using BITS = BITSReference1_5;
using BITS4 = BITSReference4_0;
using BITS5 = BITSReference5_0;
using BITS10_2 = BITSReference10_2;
Rychlá ukázka: Stažení souboru
Níže je uveden krátký, ale úplný fragment kódu jazyka C#, který stáhne soubor z adresy URL.
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
V tomto vzorovém kódu se vytvoří správce BITS s názvem mgr. Přímo odpovídá rozhraní IBackgroundCopyManager.
Nová úloha je vytvořena nadřízeným. Úloha je výstupní parametr metody CreateJob. Předán je také název úlohy ke stažení (který nemusí být jedinečný) a typ úkolu, což je úloha stahování. Zaplní se také identifikátor BITS GUID pro identifikátor úlohy.
Po vytvoření úlohy přidáte do úlohy nový soubor pro stahování pomocí metody AddFile. Musíte předat dva řetězce, jeden pro vzdálený soubor (adresu URL nebo sdílenou složku) a jeden pro místní soubor.
Po přidání souboru spusťte volání Pokračovat v úloze. Pak kód počká, dokud úloha nebude v konečném stavu (CHYBA nebo PŘENESENO) a pak se dokončí.
Verze BITS, přetypování a QueryInterface
Zjistíte, že ve svém programu často musíte používat jak starší verzi objektu BITS, tak novější verzi.
Když například vytvoříte objekt úlohy, získáte IBackgroundCopyJob (součást BITS verze 1.0), i když používáte novější objekt správce a je k dispozici novější objekt IBackgroundCopyJob. Protože metoda CreateJob nepřijímá rozhraní pro novější verzi, nemůžete přímo vytvořit novější verzi.
Přetypování v .NET slouží ke konverzi objektu ze staršího typu na novější typ. Automatické obsazení zavolá rozhraní COM QueryInterface podle potřeby.
V tomto příkladu je objekt BITS IBackgroundCopyJob s názvem "job" a chceme ho převést na objekt IBackgroundCopyJob5 s názvem "job5", abychom mohli volat metodu BITS 5.0 GetProperty. Jednoduše přetypujeme typ IBackgroundCopyJob5 takto:
var job5 = (BITS5.IBackgroundCopyJob5)job;
Proměnná job5 bude inicializována rozhraním .NET pomocí správného parametru QueryInterface.
Pokud se váš kód může spustit v systému, který nepodporuje určitou verzi služby BITS, můžete zkusit provést typovou konverzi a zachytit výjimku System.InvalidCastException.
BITS5.IBackgroundCopyJob5 job5 = null;
try
{
job5 = (BITS5.IBackgroundCopyJob5)Job;
}
catch (System.InvalidCastException)
{
; // Must be running an earlier version of BITS
}
Běžným problémem je, když se pokusíte přetypovat na nesprávný typ objektu. Systém .NET neví o skutečném vztahu mezi rozhraními BITS. Pokud se zeptáte na nesprávný druh rozhraní, .NET se pokusí ho vytvořit za vás a selže s InvalidCastException a HResult 0x80004002 (E_NOINTERFACE).
Práce s BITS verzemi 10_1 a 10_2
V některých verzích Windows 10 nelze přímo vytvořit objekt BITS IBackgroundCopyManager pomocí rozhraní 10.1 nebo 10.2. Místo toho budete muset použít více verzí referenčních souborů DLL BackgroundCopyManager. Můžete například použít verzi 1.5 k vytvoření objektu IBackgroundCopyManager a potom přetypovat výsledné úlohy nebo objekty souboru pomocí verze 10.1 nebo 10.2.