> ## Documentation Index
> Fetch the complete documentation index at: https://devdocs.xbox.com/llms.txt
> Use this file to discover all available pages before exploring further.

# Gérer et accorder des licences pour le contenu téléchargeable (DLC)

> Utilisez des produits durables comme contenu téléchargeable (DLC) dans votre titre : configuration dans Partner Center, vérifications de licence, gestion de l'installation et code de droits d'utilisation au moment de l'exécution.

Le contenu téléchargeable (DLC) est un produit qui, une fois acheté, fournit à l'utilisateur un package téléchargeable. Les DLC doivent faire l'objet d'une licence indépendante et être montés avant que leur contenu soit accessible.

Les packages DLC peuvent faire l'objet d'une licence selon le comportement de partage de contenu de chaque appareil, comme décrit dans le [Modèle de partage de produits pour les jeux](/fr/publishing/xstore-commerce/xstore-product-sharing).

Partner Center prend également en charge les produits durables sans package. Un bien durable sans package convient aux produits uniquement sous licence, qui activent du contenu déjà installé avec le jeu de base. Ces types de produits uniquement sous licence évitent de créer des packages vides que les utilisateurs devraient autrement télécharger. Pour plus d'informations, consultez [Utilisation d'un bien durable sans package](/fr/publishing/xstore-commerce/xstore-dwob).

## Workflow de développement pour les DLC

Reportez-vous à la documentation des packages de contenu téléchargeable (DLC) pour en savoir plus sur la configuration du contenu DLC, notamment sur la manière d'établir l'association avec le jeu de base via le fichier MicrosoftGame.config.

Il existe trois façons d'installer un DLC :

1. [Déploiement de DLC libre](#1-loose-dlc-deployment)
2. [Installer localement un package DLC](#2-locally-install-dlc-package)
3. [Installer un package DLC depuis le Store](#3-install-dlc-package-from-store)

### 1. Déploiement de DLC libre

Installez le répertoire qui pointe vers le fichier MicrosoftGame.config et les fichiers de ressources de votre DLC libre :

**XBOX :**

```cmd theme={null}
> xbapp deploy <DLC directory>

Package Full Name: 41336MicrosoftATG.DLC1_2020.10.14.0_neutral__dspnxghe87tn0
The operation completed successfully.
```

**PC :**

```cmd theme={null}
> wdapp register <DLC directory>  

Registered 41336MicrosoftATG.DLC1_2020.10.14.0_x64__dspnxghe87tn0
Copied temporary generated AppXManifest.xml file to C:\Users\<ntuser>\AppData\Local\Temp\41336MicrosoftATG.DLC1_2020.10.14.0_x64__dspnxghe87tn0_AppXManifest.xml
The operation completed successfully.
```

### 2. Installer localement un package DLC

Installez le fichier .xvc/.msixvc créé par makepkg :

**XBOX :**

```cmd theme={null}
> xbapp install <xvc package>  

12:16:21.800 Registered for streaming: 41336MicrosoftATG.DLC1_2020.10.14.0_neutral__dspnxghe87tn0_xs.xvc
12:16:22.645 Launch   0.00% Package   0.00%
12:16:32.650 Launch 100.00% Package 100.00%
12:16:32.651 Streaming install finished

The operation completed successfully.
```

**PC :**

```cmd theme={null}
> wdapp install <.msixvc package>  

Starting installation. See the Microsoft Store app for further details.
Launch   100% Package   100%
Installed 100%.
Installed 41336MicrosoftATG.DLC1_2020.10.14.0_x64__dspnxghe87tn0
```

### 3. Installer un package DLC depuis le Store

Avec un compte de test connecté au sandbox de développement, recherchez la page produit du DLC dans l'application Store ou accédez-y par un lien direct, puis installez-le.

## Valider l'installation du DLC

**XBOX :**

```cmd theme={null}
> xbapp listdlc

Registered DLC by Package Full Name:

   41336MicrosoftATG.DLC1_2020.10.14.0_neutral__dspnxghe87tn0

The operation completed successfully.
```

**PC :**

```cmd theme={null}
> wdapp listdlc

Registered DLC packages by Package Full Name:

41336MicrosoftATG.DLC1_2020.10.14.0_x64__dspnxghe87tn0

The operation completed successfully.
```

Sur PC, il est également possible de voir les DLC installés pour un titre particulier à l'aide de `get-appxpackage` dans PowerShell ; notez la section **Dependencies** :

```cmd theme={null}
> get-appxpackage 41336MicrosoftATG.DownloadableContent

Name              : 41336MicrosoftATG.DownloadableContent
Publisher         : CN=A4954634-DF4B-47C7-AB70-D3215D246AF1
Architecture      : X64
ResourceId        :
Version           : 2020.10.14.0
PackageFullName   : 41336MicrosoftATG.DownloadableContent_2020.10.14.0_x64__dspnxghe87tn0
InstallLocation   : E:\Repos\ATG\gx_dev\Samples\Live\DownloadableContent\Gaming.Desktop.x64\Debug
IsFramework       : False
PackageFamilyName : 41336MicrosoftATG.DownloadableContent_dspnxghe87tn0
PublisherId       : dspnxghe87tn0
IsResourcePackage : False
IsBundle          : False
IsDevelopmentMode : True
NonRemovable      : False
Dependencies      : {41336MicrosoftATG.DLC1_2020.10.14.0_x64__dspnxghe87tn0}
IsPartiallyStaged : False
SignatureKind     : None
Status            : Ok
```

**SignatureKind** indique le type de package installé : *None* pour un package créé et installé localement, *Store* pour un package installé depuis le Store.

## Achat et installation de DLC

Reportez-vous à l'article [Opérations de base du Store](/fr/publishing/xstore-commerce/xstore-basic-operations) pour comprendre comment énumérer le catalogue et proposer l'achat de modules complémentaires. Vous pouvez déterminer si des produits de modules complémentaires sont des DLC en examinant `[XStoreProduct](/reference/system/xstore/xstore_members).hasDigitalDownload`.

Si un DLC est acheté depuis le Store, son téléchargement est mis en file d'attente.

Si un DLC est acheté à l'aide de [XStoreShowPurchaseUiAsync](/fr/reference/system/xstore/xstore_members), son téléchargement n'est pas mis en file d'attente. Le jeu doit plutôt demander manuellement un téléchargement en suivant le code. Vous pouvez éventuellement créer un moniteur pour suivre la progression.

L'**identificateur de package** est une chaîne opaque qui identifie un package spécifique. L'identificateur est unique pour chaque package, mais il diffère à chaque instance lancée du jeu. Par conséquent, ne stockez pas et ne réutilisez pas l'identificateur au-delà de la session en cours.

Vous pouvez utiliser les méthodes suivantes pour obtenir l'identificateur d'un package, selon le scénario :

* Après avoir appelé [XStoreDownloadAndInstallPackagesAsync](/fr/reference/system/xstore/xstore_members) pour télécharger et installer des packages, vous pouvez obtenir les identificateurs de ces packages en appelant [XStoreDownloadAndInstallPackagesResult](/fr/reference/system/xstore/xstore_members).
* Vous pouvez obtenir les identificateurs des packages déjà téléchargés et installés en appelant [XPackageEnumeratePackages](/fr/reference/system/xstore/xstore_members), puis en récupérant l'identificateur de package dans la structure [XPackageDetails](/fr/reference/system/xstore/xstore_members) renvoyée à votre fonction de rappel [XPackageEnumerationCallback](/fr/reference/system/xstore/xstore_members) pour chaque package énuméré.
* Vous pouvez obtenir l'identificateur de package du jeu actuel en appelant [XPackageGetCurrentProcessPackageIdentifier](/fr/reference/system/xstore/xstore_members).

```cpp theme={null}
void StartDownload()
{
    auto async = new XAsyncBlock{};
    async->queue = m_asyncQueue;
    async->context = this;
    async->callback = [](XAsyncBlock* asyncBlockInner)
    {
        uint32_t count = 0;
        HRESULT hr = XStoreDownloadAndInstallPackagesResultCount(asyncBlockInner, &count);

        std::vector<char[XPACKAGE_IDENTIFIER_MAX_LENGTH]> packageIds(count);

        XStoreDownloadAndInstallPackagesResult(asyncBlockInner, count, packageIds.data());

        for(auto packageId : packageIds)
        {
            hr = XPackageCreateInstallationMonitor(
                packageId,  
                0,  
                nullptr,  
                1000,  
                m_asyncQueue,
                &m_pimHandle);

            if(SUCCEEDED(hr))
            {
                XTaskQueueRegistrationToken callbackToken;

                XPackageRegisterInstallationProgressChanged(
                    m_pimHandle,
                    this,
                    [](void* context, XPackageInstallationMonitorHandle pimHandle)
                    {
                        XPackageInstallationProgress progress;
                        XPackageGetInstallationProgress(pimHandle, &progress);

                        if(!progress.completed)
                        {
                            printf("%llu%% installed\n", static_cast<double>(progress.installedBytes) / static_cast<double>(progress.totalBytes);
                        }
                        else
                        {
                            XPackageCloseInstallationMonitorHandle(pimHandle);
                        }
                    }, &callbackToken);

                // Persist callbackToken to unregister upon completion
            }
        }

        delete asyncBlockInner;
    }

    const char* storeIds[] =  
    {
        "9PLNMXRKNM4C",  
        "9PLNMXRKNM5D"
    };

    HRESULT hr = XStoreDownloadAndInstallPackagesAsync(storeContext, storeIds, ARRAYSIZE(storeIds), async);

    if (FAILED(hr))
    {
        delete async;
        return;
    }
}
```

## Énumération des packages DLC

Quelle que soit la manière dont les DLC sont installés, le jeu doit énumérer les DLC installés avant de les utiliser. C'est lors de l'énumération des DLC installés que l'identificateur de package est obtenu.

```cpp theme={null}
bool CALLBACK DlcCallback(void* context, const XPackageDetails* details)
{
    printf("DLC found: name: %s packageId: %s\n", details->displayName, details->packageIdentifier);

    return true;
}

void RefreshInstalledPackages()
{
    HRESULT hr = XPackageEnumeratePackages(
        XPackageKind::Content,  
        XPackageEnumerationScope::ThisAndRelated,  
        this,  
        DlcCallback);
}
```

## Détection de l'installation d'un package DLC

```cpp theme={null}
void RegisterPackageInstalledEvent()
{
    XPackageRegisterPackageInstalled(
        m_asyncQueue,
        this,  
        [](void *context, const XPackageDetails *package)
        {
            printf("Package Installed event received: %s\n", package->displayName);
        },  
        &m_packageInstallToken);
}
```

Consultez la section [Résolution des problèmes](/fr/publishing/xstore-commerce/xstore-troubleshooting) si l'exemple de code n'est pas atteint. L'événement doit être déclenché quelle que soit la méthode d'installation du package DLC.

## Acquisition de la licence d'un DLC

En développement, consultez les remarques dans [Tester les licences de DLC en développement](#testing-dlc-licensing-in-development).

Le jeu de base doit acquérir la licence du DLC pour déterminer s'il doit donner à l'utilisateur l'accès à son contenu.

Les jeux utilisent généralement les licences restrictives : une fois que le jeu a acquis la licence d'un package, l'accès au package est verrouillé sur cet appareil et cette instance du produit. Le jeu doit libérer la licence avant qu'une autre instance ou un autre appareil puisse acquérir les droits d'accès et la licence. Contactez votre représentant de compte Microsoft pour vous assurer que votre jeu est configuré pour utiliser les licences restrictives (ce paramètre ne se configure pas dans Partner Center). Pour plus d'informations, consultez [Licences ouvertes et restrictives](/fr/publishing/xstore-commerce/xstore-open-restrictive-licensing).

Comme le jeu doit libérer la licence, il est chargé de suivre toutes les licences de DLC qu'il acquiert et de les libérer lorsqu'elles ne sont plus nécessaires ou à l'arrêt. Si le jeu ne libère pas une licence, celle-ci est libérée automatiquement après un délai d'expiration.

```cpp theme={null}
void CALLBACK AcquireLicenseForPackageCallback(XAsyncBlock* async)
{
    XStoreLicenseHandle licenseHandle = nullptr;

    HRESULT hr = XStoreAcquireLicenseForPackageResult(
        async,
        &licenseHandle);

    if (FAILED(hr))
    {
        printf("Failed retrieve the license handle: 0x%x\n", hr);
        return;
    }

    bool isValid = XStoreIsLicenseValid(licenseHandle);

    printf("isValid: %s\n", isValid ? "true" : "false");

    hr = XStoreRegisterPackageLicenseLost(licenseHandle, m_asyncQueue, context,
       [](void *context)  
       {
           // Check if the license lost corresponded to any mounted DLC
           // If so, it is up to the game to determine an appropriate time
           // to unmount the DLC, e.g. after the current match is completed
       });

    delete async;
}

void AcquireLicenseForPackage(const char* packageIdentifier)
{
    auto async = new XAsyncBlock{};
    async->context = this;
    async->queue = m_asyncQueue;
    async->callback = AcquireLicenseForPackageCallback;

    HRESULT hr = XStoreAcquireLicenseForPackageAsync(
        m_storeContext,
        packageIdentifier,
        async);

    if (FAILED(hr))
    {
        delete async;
        return;
    }
}
```

## Détermination de la source de licence d'un DLC

À l'aide de [XStoreCanAcquireLicenseForPackageAsync](/fr/reference/system/xstore/xstore_members) ou de [XStoreCanAcquireLicenseForStoreIdAsync](/fr/reference/system/xstore/xstore_members) (selon le type d'identificateur), il est possible de déterminer si le DLC est

1. Disponible sous licence, afin de pouvoir présenter des options d'achat dans le cas contraire
2. Disponible sous licence par disque ou par licence numérique

```cpp theme={null}
void PreviewLicense(const char* storeId)
{
    auto async = new XAsyncBlock{};
    async->queue = m_asyncQueue;
    async->callback = [](XAsyncBlock* async)
    {
        XStoreCanAcquireLicenseResult result;

        HRESULT hr = XStoreCanAcquireLicenseForStoreIdResult(
            async,
            &result);

        if (FAILED(hr))
        {
            printf("Error calling XStoreCanAcquireLicenseForStoreIdResult: 0x%x\n", hr);
        }
        else
        {
            // Status = 1 Licensable and
            // a. licensableSku = "DISC" if disc licensed
            // b. licensableSku = "0010" or similar if digital licensed
            printf("Status: %u LicensableSku: %s\n", result.status, result.licensableSku);
        }

        delete async;
    };

    HRESULT hr = XStoreCanAcquireLicenseForStoreIdAsync(
        m_xStoreContext,
        storeId,
        async);

    if (FAILED(hr))
    {
        delete async;

        printf("Error calling XStoreCanAcquireLicenseForStoreIdAsync: 0x%x", hr);
        return;
    }
}
```

## Montage et démontage d'un DLC

Une fois la licence du DLC acquise, le contenu du DLC peut être monté et consulté.

```cpp theme={null}

void CALLBACK MountPackageCallback(XAsyncBlock* async)
{
    XPackageMountHandle mountHandle = {};

    HRESULT hr = XPackageMountWithUiResult(async, &mountHandle);

    if (SUCCEEDED(hr))
    {
        // Access DLC goodness
    }
    else
    {
        XStoreCloseLicenseHandle(license);
        printf("Error mounting package: 0x%x\n", hr);
    }

    delete async;
};

void MountPackage(const char* packageIdentifier)
{
    auto async = new XAsyncBlock{};
    async->queue = m_asyncQueue;
    async->context = context;
    async->callback = MountPackageCallback;

    HRESULT hr = XPackageMountWithUiAsync(packageIdentifier, async);

    if (FAILED(hr))
    {
        printf("XPackageMountWithUiAsync failed : 0x%x\n", hr);
        delete async;
    }
}
```

Lors du démontage, libérez tous les jetons et handles :

```cpp theme={null}
void UnmountPackage(XPackageMountHandle mountHandle, XStoreLicenseHandle license, XTaskQueueRegistrationToken licenseLostToken)
{
    XStoreUnregisterPackageLicenseLost(license, licenseLostToken, false);

    XPackageCloseMountHandle(mountHandle);

    XStoreCloseLicenseHandle(license);
}
```

## Désinstallation d'un DLC

Utilisez [XPackageUninstallPackage](/fr/reference/system/xstore/xstore_members) pour désinstaller un package DLC. Le package doit d'abord être démonté.

## Smart Delivery et DLC

Les titres XBOX Series X/S peuvent obtenir la licence et monter des DLC créés pour le titre XBOX One. En général, ce scénario se produit lorsque le package DLC ne contient pas de données utilisées par le jeu. La seule façon de le vérifier est de déterminer si l'ID `AllowedProduct` du DLC ERA dans son fichier package.appxmanifest, qui est un GUID, correspond à l'ID de produit XBOX hérité attribué au produit dans Partner Center.

Si ce n'est pas le cas, le titre a peut-être été migré depuis l'ancien XBOX Developer Portal (XDP) mis hors service, et il ne fonctionne qu'avec les packages téléchargés depuis le Store, car la version XBOX Series X/S est attribuée à l'ID de produit de la XBOX One. À des fins de développement, consultez la remarque dans la section [Résolution des problèmes](/fr/publishing/xstore-commerce/xstore-troubleshooting).

## DLC provenant d'autres produits

Il est possible d'énumérer et d'utiliser des DLC provenant d'un autre produit. Pour le titre qui souhaite utiliser un DLC d'un autre produit, attribuez une relation « Can sell and use » au produit DLC dans la section **Product relationship setup** de Partner Center. Le choix des produits disponibles est limité au compte de l'éditeur.

## Tester les licences de DLC en développement

Pour plus d'informations, consultez [Activation des tests de licence](/fr/publishing/xstore-commerce/xstore-licensing-setup).

Les packages DLC locaux doivent être créés avec un paramètre /contentid.

L'EKBID de chaque package DLC doit être remplacé par rapport aux valeurs par défaut.

## Documentation de référence de l'API

* [XStore (contenu de l'API)](/fr/reference/system/xstore/xstore_members)
  * Fonctions
    * [XStoreShowPurchaseUiAsync](/fr/reference/system/xstore/xstore_members)
    * [XStoreDownloadAndInstallPackagesAsync](/fr/reference/system/xstore/xstore_members)
    * [XStoreDownloadAndInstallPackagesResult](/fr/reference/system/xstore/xstore_members)
    * [XStoreCanAcquireLicenseForPackageAsync](/fr/reference/system/xstore/xstore_members)
    * [XStoreCanAcquireLicenseForStoreIdAsync](/fr/reference/system/xstore/xstore_members)
  * Structures
    * [xstoreproduct](/fr/reference/system/xstore/xstore_members)
* [XPackage (contenu de l'API)](/fr/reference/system/xstore/xstore_members)
  * Fonctions
    * [XPackageEnumeratePackages](/fr/reference/system/xstore/xstore_members)
    * [XPackageEnumerationCallback](/fr/reference/system/xstore/xstore_members)
    * [XPackageGetCurrentProcessPackageIdentifier](/fr/reference/system/xstore/xstore_members)
    * [XPackageUninstallPackage](/fr/reference/system/xstore/xstore_members)
  * Structures
    * [XPackageDetails](/fr/reference/system/xstore/xstore_members)

## Voir aussi

[Vue d'ensemble du commerce](/fr/publishing/xstore-commerce/xstore-commerce-overview)

[Activation des tests de licence](/fr/publishing/xstore-commerce/xstore-licensing-setup)

[Utilisation d'un bien durable sans package](/fr/publishing/xstore-commerce/xstore-dwob)

[Référence de l'API XStore](/fr/reference/system/xstore/xstore_members)


## Related topics

- [Guide des BVT de certification pour PC](/fr-CA/publishing/game-publishing/concepts/certification/certification-pc-bvt-guide.md)
- [Guide des BVT de certification pour console](/fr-CA/publishing/game-publishing/concepts/certification/certification-console-bvt-guide.md)
- [Guide BVT de certification pour console](/fr/publishing/game-publishing/concepts/certification/certification-console-bvt-guide.md)
- [XR-037 Dépendances envers les paquets de contenu](/fr-CA/publishing/certification/xr/xr-037.md)
- [XR-037 Dépendances vis-à-vis des packages de contenu](/fr/publishing/certification/xr/xr-037.md)
