> ## 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.

# 管理可下載內容 (DLC) 並授權

> 在您的遊戲中將耐久性產品作為可下載內容 (DLC) 使用：Partner Center 設定、授權檢查、安裝管理及執行階段權利程式碼。

可下載內容 (DLC) 由一項產品組成，使用者購買後會取得可下載的套件。DLC 必須先獨立授權並掛接，才能存取其內容。

DLC 套件可依據每部裝置的內容共用行為進行授權，如[遊戲的產品共用模型](/zh-TW/publishing/xstore-commerce/xstore-product-sharing)中所述。

Partner Center 也支援不含套件的耐久性產品。不含套件的耐久性產品適用於僅授權的產品，可啟用已隨基礎遊戲安裝的內容。這類僅授權的產品可省去建立空白套件的步驟，否則使用者需要下載這些套件。如需詳細資訊，請參閱[如何使用不含套件的耐久性產品](/zh-TW/publishing/xstore-commerce/xstore-dwob)。

## DLC 的開發工作流程

請參閱可下載內容 (DLC) 套件文件，深入了解如何設定 DLC 內容，包括如何透過 MicrosoftGame.config 與基礎遊戲建立關聯。

安裝 DLC 有三種方式：

1. [鬆散 DLC 部署](#1-loose-dlc-deployment)
2. [在本機安裝 DLC 套件](#2-locally-install-dlc-package)
3. [從 Store 安裝 DLC 套件](#3-install-dlc-package-from-store)

### 1. 鬆散 DLC 部署

安裝指向您鬆散 DLC 之 MicrosoftGame.config 與資產檔案的目錄：

**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. 在本機安裝 DLC 套件

安裝由 makepkg 建立的 .xvc/.msixvc：

**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. 從 Store 安裝 DLC 套件

在開發沙箱中以測試帳戶登入後，於 Store 應用程式中搜尋或直接連結至 DLC 產品頁面並安裝。

## 驗證 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.
```

在 PC 上，也可以在 PowerShell 中使用 `get-appxpackage` 查看特定遊戲已安裝的 DLC，請注意 **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** 表示所安裝的套件類型：*None* 代表在本機建置並安裝的套件，*Store* 代表從 Store 安裝的套件。

## 購買和安裝 DLC

請參閱[基本 Store 作業](/zh-TW/publishing/xstore-commerce/xstore-basic-operations)一文，了解如何列舉目錄並提供購買附加元件的功能。您可以檢查 `[XStoreProduct](/reference/system/xstore/xstore_members).hasDigitalDownload` 來判斷附加元件產品是否為 DLC。

如果從 Store 購買 DLC，DLC 會排入下載佇列。

如果使用 [XStoreShowPurchaseUiAsync](/zh-TW/reference/system/xstore/xstore_members) 購買 DLC，DLC 不會排入下載佇列。遊戲應改為依照下列程式碼手動要求下載。您也可以選擇建立監視器來追蹤進度。

**套件識別碼**是識別特定套件的不透明字串。此識別碼對每個套件都是唯一的，但遊戲每次啟動的執行個體都會不同。因此，請勿在目前工作階段之外儲存或重複使用此識別碼。

視案例而定，您可以使用下列方法取得套件的套件識別碼：

* 呼叫 [XStoreDownloadAndInstallPackagesAsync](/zh-TW/reference/system/xstore/xstore_members) 下載並安裝套件後，您可以呼叫 [XStoreDownloadAndInstallPackagesResult](/zh-TW/reference/system/xstore/xstore_members) 取得這些套件的套件識別碼。
* 您可以呼叫 [XPackageEnumeratePackages](/zh-TW/reference/system/xstore/xstore_members)，然後從針對每個列舉套件傳回給 [XPackageEnumerationCallback](/zh-TW/reference/system/xstore/xstore_members) 回呼函式的 [XPackageDetails](/zh-TW/reference/system/xstore/xstore_members) 結構中擷取套件識別碼，以取得已下載並安裝之套件的套件識別碼。
* 您可以呼叫 [XPackageGetCurrentProcessPackageIdentifier](/zh-TW/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;
    }
}
```

## 列舉 DLC 套件

無論 DLC 以何種方式安裝，遊戲都必須先列舉已安裝的 DLC 才能使用。套件識別碼是在列舉已安裝的 DLC 時取得的。

```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);
}
```

## 偵測 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);
}
```

如果未執行到此程式碼範例，請參閱[疑難排解](/zh-TW/publishing/xstore-commerce/xstore-troubleshooting)一節。無論 DLC 套件以何種方法安裝，都應該觸發此事件。

## 取得 DLC 的授權

在開發期間，請參閱[在開發環境中測試 DLC 授權](#testing-dlc-licensing-in-development)中的注意事項。

基礎遊戲必須取得 DLC 的授權，以判斷是否應授予使用者存取其內容的權限。

遊戲通常使用限制性授權，在遊戲取得套件的授權後，套件的存取權會鎖定在該裝置及該產品執行個體上。遊戲必須釋放授權，其他執行個體或裝置才能取得存取權與授權。請與您的 Microsoft 客戶代表聯絡，確保您的遊戲已設定為使用限制性授權 (無法在 Partner Center 中設定)。如需詳細資訊，請參閱[開放式與限制性授權](/zh-TW/publishing/xstore-commerce/xstore-open-restrictive-licensing)。

由於遊戲必須釋放授權，因此遊戲負責追蹤其取得的所有 DLC 授權，並在不再需要時或終止時釋放這些授權。如果遊戲未能釋放授權，授權會在逾時期間過後自動釋放。

```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;
    }
}
```

## 判斷 DLC 的授權來源

使用 [XStoreCanAcquireLicenseForPackageAsync](/zh-TW/reference/system/xstore/xstore_members) 或 [XStoreCanAcquireLicenseForStoreIdAsync](/zh-TW/reference/system/xstore/xstore_members) (視識別碼類型而定)，可以判斷 DLC 是否

1. 可授權，若不可授權，您可以顯示購買選項
2. 可透過光碟或數位授權取得授權

```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;
    }
}
```

## 掛接和卸載 DLC

成功取得 DLC 授權後，即可掛接並存取 DLC 內容。

```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;
    }
}
```

卸載時，請釋放所有權杖和控制代碼：

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

    XPackageCloseMountHandle(mountHandle);

    XStoreCloseLicenseHandle(license);
}
```

## 解除安裝 DLC

使用 [XPackageUninstallPackage](/zh-TW/reference/system/xstore/xstore_members) 解除安裝 DLC 套件。必須先卸載套件。

## Smart Delivery 與 DLC

XBOX Series X/S 遊戲可以授權並掛接為 XBOX One 遊戲建立的 DLC。此案例通常發生在 DLC 套件不包含遊戲所使用之資料時。唯一的檢查方式是確認 ERA DLC 在其 package.appxmanifest 中的 `AllowedProduct` ID (一個 GUID) 是否與 Partner Center 中指派給該產品的 Legacy XBOX Product ID 相符。

如果不相符，該遊戲可能是從已停用的 XBOX Developer Portal (XDP) 移轉而來，且僅適用於從 Store 下載的套件，因為 XBOX Series X/S 版本被指派了 XBOX One 的產品識別碼。如需開發用途，請參閱[疑難排解](/zh-TW/publishing/xstore-commerce/xstore-troubleshooting)一節中的注意事項。

## 來自不同產品的 DLC

可以列舉並使用來自不同產品的 DLC。對於想要使用來自不同產品之 DLC 的遊戲，請在 Partner Center 的 **Product relationship setup** 區段中，為 DLC 產品指派 "Can sell and use" 關係。可用產品的選擇範圍僅限於發行者帳戶。

## 在開發環境中測試 DLC 授權

如需詳細資訊，請參閱[啟用授權測試](/zh-TW/publishing/xstore-commerce/xstore-licensing-setup)。

本機 DLC 套件必須使用 /contentid 參數建立。

每個 DLC 套件的 EKBID 都必須覆寫預設值。

## 參考 API 文件

* [XStore (API 內容)](/zh-TW/reference/system/xstore/xstore_members)
  * 函式
    * [XStoreShowPurchaseUiAsync](/zh-TW/reference/system/xstore/xstore_members)
    * [XStoreDownloadAndInstallPackagesAsync](/zh-TW/reference/system/xstore/xstore_members)
    * [XStoreDownloadAndInstallPackagesResult](/zh-TW/reference/system/xstore/xstore_members)
    * [XStoreCanAcquireLicenseForPackageAsync](/zh-TW/reference/system/xstore/xstore_members)
    * [XStoreCanAcquireLicenseForStoreIdAsync](/zh-TW/reference/system/xstore/xstore_members)
  * 結構
    * [xstoreproduct](/zh-TW/reference/system/xstore/xstore_members)
* [XPackage (API 內容)](/zh-TW/reference/system/xstore/xstore_members)
  * 函式
    * [XPackageEnumeratePackages](/zh-TW/reference/system/xstore/xstore_members)
    * [XPackageEnumerationCallback](/zh-TW/reference/system/xstore/xstore_members)
    * [XPackageGetCurrentProcessPackageIdentifier](/zh-TW/reference/system/xstore/xstore_members)
    * [XPackageUninstallPackage](/zh-TW/reference/system/xstore/xstore_members)
  * 結構
    * [XPackageDetails](/zh-TW/reference/system/xstore/xstore_members)

## 另請參閱

[商務概觀](/zh-TW/publishing/xstore-commerce/xstore-commerce-overview)

[啟用授權測試](/zh-TW/publishing/xstore-commerce/xstore-licensing-setup)

[如何使用不含套件的耐久性產品](/zh-TW/publishing/xstore-commerce/xstore-dwob)

[XStore API 參考](/zh-TW/reference/system/xstore/xstore_members)


## Related topics

- [認證主機 BVT 指南](/zh-TW/publishing/game-publishing/concepts/certification/certification-console-bvt-guide.md)
- [XBOX 主機遊戲的認證測試 XBOX 需求](/zh-TW/publishing/certification/console-cert-tested-requirements.md)
- [認證 PC BVT 指南](/zh-TW/publishing/game-publishing/concepts/certification/certification-pc-bvt-guide.md)
- [XR-037 內容套件的相依性](/zh-TW/publishing/certification/xr/xr-037.md)
- [XR037 對內容套件的相依性](/zh-TW/publishing/certification/fma/xr-037.md)
