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

# 发布者内容包

> 介绍如何创建和发布发布者内容包。发布者内容是一种包类型，可让游戏发布者在自己的 CDN 上托管和更新补充内容。

# 发布者内容包

*发布者内容* (Publisher Content) 是一种包类型，可让你在自己的内容分发网络 (CDN) 上托管补充游戏内容，同时由平台继续管理安装、后台下载、完整性验证和用户体验。XBOX One 系列主机支持发布者内容包；XBOX Series X|S 主机从 2026 年 10 月 GDK (GDK 2610) 起支持发布者内容包。

发布者内容包在运行时的行为与可下载内容 (DLC) 类似：它们与基础游戏一起安装，装载到你的进程中，并在游戏退出时卸载。与 DLC 不同，它们不通过 Partner Center 引入，没有应用商店 ID，也不通过 Microsoft Store 销售或授予许可。你的服务是决定发布哪些内容、何时更新以及谁接收内容的唯一可信来源。

## 何时使用发布者内容

如果你希望执行以下任一操作，请考虑使用发布者内容：

* 发布小型实时服务更新（配置数据、调整表、小型资源包），而无需经过应用商店引入流程。
* 提供基础游戏的所有玩家都会自动收到的发布者品牌附加内容。
* 重用你已为其他平台上的游戏运营的现有 CDN 和内容管道。
* 在 CDN 层控制推出时间、区域定向或 A/B 测试。

发布者内容并不能替代 DLC。当你需要按用户授权、购买流程或 Microsoft Store 许可时，请继续使用标准 [DLC 包](/zh-CN/build/core-features/common/packaging/packaging-downloadable-content-dlc)。

## 要求和限制

* 每个基础游戏一个发布者内容包。
* 拥有基础游戏的任何玩家均可使用。不进行按用户的许可检查。
* 支持 XBOX One 系列主机和 XBOX Series X|S 主机。
* 基础游戏和发布者内容包必须使用相同的包格式。例如，如果基础游戏打包为 MSIXVC2，则发布者内容包也必须为 MSIXVC2。
* 发布者内容包必须较小，即小于 1 GB。
* 发布者内容包使用发布者提供的签名材料进行签名，基础游戏中嵌入相应的公共材料，以便平台能够验证声称属于该游戏的发布者内容。基础游戏本身的签名方式与任何其他游戏相同。签名材料因包格式而异：
  * **XVC 和 MSIXVC** — 原始 CNG 签名密钥。必须使用 RSA-4096。
  * **MSIXVC2** — 带有 RSA-4096 密钥的 X.509 证书。证书必须当前有效、具有可访问的 RSA 私钥，并允许数字签名。

<Info>
  平台不为发布者内容包提供内容保密。与 Microsoft Store DLC 不同，发布者内容在分发时不加密：任何从你的 CDN 下载该文件的人都可以检查其内容。如果你需要对部分有效负载进行保密，请在打包之前在内容内部对这些部分进行加密。
</Info>

## 各部分如何协同工作

总体而言：

1. 在基础游戏的 *MicrosoftGame.config* 中声明一个**清单 URL**。此 URL 指向你在 CDN 上托管的一个小型 JSON 文件，你可以随时更新该文件。
2. 创作一个通过应用商店 ID 引用基础游戏的**发布者内容包**。
3. 使用你的发布者签名材料对发布者内容包进行签名。基础游戏中嵌入相应的公共材料，以便平台能够验证任何声称属于该游戏的发布者内容。
4. 当玩家安装基础游戏时，平台会获取你的清单，读取当前发布者内容包的 CDN URL，并将其加入安装队列。
5. 在运行时，你的游戏枚举已安装的包，并以装载 DLC 的相同方式装载发布者内容包。

要发布内容的新修订版本，请将新包上传到你的 CDN，并更新清单以指向该包。平台会在下一次更新检查时获取此更改。

## 设置基础游戏

在基础游戏的 *MicrosoftGame.config* 文件中，添加一个带有 `ManifestUrl` 子元素的 `PublisherContent` 元素。运行你的游戏的每台设备都必须能够访问该 URL。

```xml theme={null}
<?xml version="1.0" encoding="utf-8"?>
<Game configVersion="1">
    <!-- Existing Identity, ShellVisuals, ExecutableList, StoreId, etc. -->

    <StoreId>9NZTKMP36L8J</StoreId>

    <PublisherContent>
        <ManifestUrl>https://example.com/space-raiders/pubxvc/console/manifest.json</ManifestUrl>
    </PublisherContent>
</Game>
```

有关这些元素的详细信息，请参阅 [PublisherContent 元素 (MicrosoftGame.config)](/zh-CN/reference/system/microsoftgameconfig/elements/microsoftgameconfig-element-publishercontent) 和 [ManifestUrl 元素 (MicrosoftGame.config)](/zh-CN/reference/system/microsoftgameconfig/elements/microsoftgameconfig-element-manifesturl)。

## 创作发布者内容包

在发布者内容有效负载旁边创建一个 *MicrosoftGame.config*。使用 `PublisherContentBaseProduct` 元素按应用商店 ID 引用基础游戏。

```xml theme={null}
<?xml version="1.0" encoding="utf-8"?>
<Game configVersion="1">
    <Identity Name="ContosoStudios.SpaceRaiders.PublisherContent"
              Publisher="CN=REPLACE_WITH_YOUR_PUBLISHER"
              Version="1.0.0.0"/>

    <ShellVisuals DefaultDisplayName="Space Raiders Publisher Content"
                  PublisherDisplayName="Contoso Studios"
                  StoreLogo="StoreLogo.png"
                  Square150x150Logo="Logo.png"
                  Square44x44Logo="SmallLogo.png"
                  Description="Publisher-hosted content for Space Raiders."
                  BackgroundColor="#000040"
                  SplashScreenImage="SplashScreen.png"/>

    <PublisherContentBaseProduct>9NZTKMP36L8J</PublisherContentBaseProduct>
</Game>
```

有关详细信息，请参阅 [PublisherContentBaseProduct 元素 (MicrosoftGame.config)](/zh-CN/reference/system/microsoftgameconfig/elements/microsoftgameconfig-element-publishercontentbaseproduct)。

<Note>
  不要在发布者内容包中包含 `AllowedProducts` 元素。该元素将包标识为标准 DLC，并且与 `PublisherContentBaseProduct` 互斥。
</Note>

## 创作清单

在你于基础游戏中声明的 `ManifestUrl` 处托管一个小型 JSON 清单。该清单包含单个 `url` 字段，指向你 CDN 上的当前发布者内容包。发布后，请勿更改该 url 处的发布者内容，而应将每个新的发布者内容包版本发布到新的 url，并相应地更新清单。

```json theme={null}
{
    "url": "https://example.com/space-raiders/pubxvc/console/space-raiders-pubxvc-v2.30.1.xvc"
}
```

## 生成发布者签名材料

发布者签名材料存放在你的生成计算机上，当 `makepkg` 打包基础游戏和发布者内容包时，通过名称（或指纹）引用该材料。具体形式取决于你的目标包格式。

<Info>
  请将发布者签名密钥或证书的私钥视为生产机密。任何能够访问私有材料的人都可以生成平台会认为来自你的发布者内容包。
</Info>

### 对于 XVC 和 MSIXVC 包

在生成计算机上的 Windows CNG 密钥存储提供程序中创建 RSA-4096 签名密钥。

以下 PowerShell 示例在 Microsoft Software Key Storage Provider 中创建一个名为 `MyTestPubXvcSigningKey` 的可导出 RSA-4096 签名密钥。

```powershell theme={null}
Add-Type -AssemblyName System.Security

$keyName = "MyTestPubXvcSigningKey"
$providerName = "Microsoft Software Key Storage Provider"

$cngParams = [System.Security.Cryptography.CngKeyCreationParameters]::new()
$cngParams.Provider     = [System.Security.Cryptography.CngProvider]::new($providerName)
$cngParams.KeyUsage     = [System.Security.Cryptography.CngKeyUsages]::Signing
$cngParams.ExportPolicy = [System.Security.Cryptography.CngExportPolicies]::AllowExport

<# Use an RSA-4096 key. #>
$len = [System.Security.Cryptography.CngProperty]::new(
    "Length", [BitConverter]::GetBytes([int]4096),
    [System.Security.Cryptography.CngPropertyOptions]::None)
$cngParams.Parameters.Add($len)

$key = [System.Security.Cryptography.CngKey]::Create(
    [System.Security.Cryptography.CngAlgorithm]::Rsa, $keyName, $cngParams)

Write-Host "Created CNG key '$keyName' in the $providerName."
```

通过 `/usepublisherkey` 将生成的密钥名称传递给 `makepkg pack`。如果使用默认以外的 CNG 密钥存储提供程序，还需通过 `/publisherkeyprovider` 传递其名称。

### 对于 MSIXVC2 包

创建一个主题密钥为 RSA-4096 密钥的 X.509 证书，并将该证书及其私钥安装到 `CurrentUser\My` 证书存储中。

以下 PowerShell 示例在 `CurrentUser\My` 中创建一个自签名 RSA-4096 证书，并导出其 `.cer` 文件。

```powershell theme={null}
$subject = "CN=MyTestPubXvcSigningCertificate"
$certificatePath = Join-Path $PWD "MyTestPubXvcSigningCertificate.cer"

$certificate = New-SelfSignedCertificate `
    -Subject $subject `
    -CertStoreLocation "Cert:\CurrentUser\My" `
    -Provider "Microsoft Software Key Storage Provider" `
    -KeyAlgorithm RSA `
    -KeyLength 4096 `
    -HashAlgorithm SHA256 `
    -KeyUsage DigitalSignature `
    -NotAfter (Get-Date).AddYears(5)

Export-Certificate `
    -Cert $certificate `
    -FilePath $certificatePath `
    -Type CERT
```

通过 `/usepublishercert` 将导出的 `.cer` 路径或证书指纹传递给 `makepkg pack`。如果证书安装在 `My` 以外的存储中，还需通过 `/publishercertstore` 传递其名称。

## 打包基础游戏和发布者内容

两次 `pack` 调用必须引用相同的密钥或证书。

### 对于 XVC 和 MSIXVC 包

打包基础游戏：

```console theme={null}
makepkg pack /f layout.xml /d <base_game_folder> /pd <output_folder> /usepublisherkey <publisherkeyname>
```

打包发布者内容：

```console theme={null}
makepkg pack /f layout.xml /d <publisher_content_folder> /pd <output_folder> /usepublisherkey <publisherkeyname>
```

如果使用 Microsoft Software Key Storage Provider 以外的 CNG 密钥存储提供程序，请在两个命令中都添加 `/publisherkeyprovider <providername>`。

### 对于 MSIXVC2 包

打包基础游戏：

```console theme={null}
makepkg pack /msixvc2 /d <base_game_folder> /pd <output_folder> /usepublishercert <thumbprint|certificate.cer>
```

打包发布者内容：

```console theme={null}
makepkg pack /msixvc2 /d <publisher_content_folder> /pd <output_folder> /usepublishercert <thumbprint|certificate.cer>
```

如果证书安装在 `CurrentUser\My` 以外的存储中，请在两个命令中都添加 `/publishercertstore <store>`。

有关详细信息，请参阅 [生成包 (makepkg.exe)](/zh-CN/build/core-features/common/packaging/deployment/makepkg)。

## 发布和更新

<Note>
  发布者内容包托管在你的 CDN 上，无法上传到 Partner Center。`makepkg upload` 会拒绝松散形式和打包形式的发布者内容包。基础游戏包通过标准 Partner Center 流程正常上传。
</Note>

1. 将打包后的发布者内容 XVC 上传到你的 CDN 上清单中引用的 URL。
2. 将清单 JSON 上传到你在基础游戏的 `ManifestUrl` 元素中声明的 URL。
3. 照常通过 Partner Center 提交并发布基础游戏。

要推出更新：

1. 将新的发布者内容包上传到你的 CDN 上的新 URL。不要替换旧的发布者内容包。
2. 更新清单中的 `url` 值，使其指向新包。
3. 将更新后的 JSON 文件上传到你在基础游戏的 `ManifestUrl` 元素中声明的 URL。

已安装的设备会在下一次更新检查时检测到此更改，并在后台下载新的发布者内容包。

## 在运行时访问发布者内容

在运行时，以发现 DLC 的相同方式发现已安装的发布者内容：使用 [XPackageEnumeratePackages](/zh-CN/reference/system/xpackage/functions/xpackageenumeratepackages)，然后使用 [XPackageMountWithUiAsync](/zh-CN/reference/system/xpackage/functions/xpackagemountwithuiasync) 装载返回的包。

传递 [XPackageKind::PublisherContent](/zh-CN/reference/system/xpackage/enums/xpackagekind) 可将枚举筛选为仅发布者内容：

```cpp theme={null}
HRESULT hr = XPackageEnumeratePackages(
    XPackageKind::PublisherContent,
    XPackageEnumerationScope::ThisOnly,
    nullptr,
    [](void*, const XPackageDetails* details) -> bool
    {
        // details->packageIdentifier can be passed to XPackageMountWithUiAsync.
        // details->kind is XPackageKind::PublisherContent.
        return true;
    });
```

如果你已从其他来源获得包标识符，请使用 [XPackageGetPackageKind](/zh-CN/reference/system/xpackage/functions/xpackagegetpackagekind) 确定它是否引用发布者内容包：

```cpp theme={null}
XPackageKind kind;
HRESULT hr = XPackageGetPackageKind(packageIdentifier, &kind);
if (SUCCEEDED(hr) && kind == XPackageKind::PublisherContent)
{
    // Handle Publisher Content.
}
```

由于发布者内容不通过 Microsoft Store 授予许可，因此在装载之前无需调用 [XStoreQueryPackageIdByKind](/zh-CN/gdk-docs/docs/reference/system/xstore/xstore_members) 或执行应用商店许可检查。

## 卸载行为

当玩家卸载基础游戏时，平台会自动卸载关联的发布者内容包。你无需在游戏代码中显式删除它。

## 另请参阅

* [PublisherContent 元素 (MicrosoftGame.config)](/zh-CN/reference/system/microsoftgameconfig/elements/microsoftgameconfig-element-publishercontent)
* [ManifestUrl 元素 (MicrosoftGame.config)](/zh-CN/reference/system/microsoftgameconfig/elements/microsoftgameconfig-element-manifesturl)
* [PublisherContentBaseProduct 元素 (MicrosoftGame.config)](/zh-CN/reference/system/microsoftgameconfig/elements/microsoftgameconfig-element-publishercontentbaseproduct)
* [生成包 (makepkg.exe)](/zh-CN/build/core-features/common/packaging/deployment/makepkg)
* [XPackageKind](/zh-CN/reference/system/xpackage/enums/xpackagekind)
* [XPackageGetPackageKind](/zh-CN/reference/system/xpackage/functions/xpackagegetpackagekind)
* [XPackageEnumeratePackages](/zh-CN/reference/system/xpackage/functions/xpackageenumeratepackages)
* [GDK 可下载内容 (DLC) 包](/zh-CN/build/core-features/common/packaging/packaging-downloadable-content-dlc)


## Related topics

- [MicrosoftGame.config 元素 - PublisherContentBaseProduct](/zh-CN/reference/system/microsoftgameconfig/elements/microsoftgameconfig-element-publishercontentbaseproduct.md)
- [MicrosoftGame.config 元素 - PublisherContent](/zh-CN/reference/system/microsoftgameconfig/elements/microsoftgameconfig-element-publishercontent.md)
- [XPackageGetPackageKind](/zh-CN/reference/system/xpackage/functions/xpackagegetpackagekind.md)
- [XPackageKind](/zh-CN/reference/system/xpackage/enums/xpackagekind.md)
- [MicrosoftGame.config 元素 - ManifestUrl](/zh-CN/reference/system/microsoftgameconfig/elements/microsoftgameconfig-element-manifesturl.md)
