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

# 检查更新

> 在游戏中使用 XStoreQueryGameAndDlcPackageUpdatesAsync 检查并应用 XBOX 游戏和 DLC 包的更新，以保持多人游戏版本一致。

如果游戏保持最新版本至关重要，游戏可以检查并应用更新。当游戏包含多人游戏功能，需要所有玩家运行的游戏具有相同的功能时，这一点尤其重要。

游戏可以使用 [XStoreQueryGameAndDlcPackageUpdatesAsync](/reference/system/xstore/xstore_members) 检查更新，如以下示例代码所示：

```cpp theme={null}
void CALLBACK QueryGameAndDlcPackageUpdatesCallback(XAsyncBlock* async)
{
    unsigned int numUpdates = 0;

    HRESULT hr = XStoreQueryGameAndDlcPackageUpdatesResultCount(async, &numUpdates);

    if (SUCCEEDED(hr))
    {
        if (numUpdates > 0)
        {
            std::vector<XStorePackageUpdate> packages(numUpdates);

            hr = XStoreQueryGameAndDlcPackageUpdatesResult(async, numUpdates, packages.data());

            if (SUCCEEDED(hr))
            {
                for (auto &package : packages)
                {
                    printf("Update available %s\n", package.packageIdentifier);
                }
            }
        }
        else
        {
            printf("No updates are available\n");
        }
    }

    delete async;
}

void CheckForUpdates()
{
    auto asyncBlock = new XAsyncBlock{};
    asyncBlock->queue = m_asyncQueue;
    asyncBlock->callback = QueryGameAndDlcPackageUpdatesCallback;

    if (FAILED(XStoreQueryGameAndDlcPackageUpdatesAsync(m_xStoreContext, asyncBlock)))
    {
        delete asyncBlock;
    }
}
```

如果游戏包含许多不需要检查更新的 DLC 项目（例如仅用于授权的空 DLC 包），上述代码可能会因为逐个检查而带来不必要的开销。

请改用 [XStoreQueryPackageUpdatesAsync](/reference/system/xstore/xstore_members)，按当前游戏的包 ID 进行过滤，包 ID 可通过 [XPackageGetCurrentProcessPackageIdentifier](/reference/system/xstore/xstore_members) 获取，或从 [XPackageEnumeratePackages](/reference/system/xstore/xstore_members) 返回的包 ID 中过滤：

```cpp theme={null}
void CALLBACK QueryPackageUpdatesCallback(XAsyncBlock* async)
{
    unsigned int numUpdates = 0;

    HRESULT hr = XStoreQueryPackageUpdatesResultCount(async, &numUpdates);

    if (FAILED(hr))
    {
        printf("XStoreQueryPackageUpdatesResultCount failed : 0x%x\n", hr);
        return;
    }

    printf("Number of updates: %d", numUpdates);

    if (count > 0)
    {
        std::vector<XStorePackageUpdate> packages(numUpdates);

        hr = XStoreQueryPackageUpdatesResult(async, numUpdates, packages.data());
        
        if (SUCCEEDED(hr))
        {
            for (auto &package : packages)
            {
                printf("Update available %s\n", package.packageIdentifier);
            }
        }
    }
}

void QueryPackageUpdates()
{
    std::vector<std::string> packageIds;

    HRESULT hr = XPackageEnumeratePackages(
        XPackageKind::Game,
        XPackageEnumerationScope::ThisOnly, // this will return for the base game only
        &packageIds, [](void* context, const XPackageDetails* details) -> bool
        {
            auto packageIds = reinterpret_cast<std::vector<std::string>*>(context);

            printf("Identifier: %s name: %s\n", details->packageIdentifier, details->displayName);

            packageIds->push_back(details->packageIdentifier);
        });

    // packageIds now populated with just the base game package Id

    auto asyncBlock = new XAsyncBlock();
    asyncBlock->queue = m_asyncQueue;
    asyncBlock->context = m_storeContext;
    asyncBlock->callback = QueryPackageUpdatesCallback;

    hr = XStoreQueryPackageUpdatesAsync(
        m_storeContext,
        packageIds.data(),
        packageIds.size(),
        asyncBlock);

    if (FAILED(hr))
    {
        printf("XStoreQueryPackageUpdatesAsync failed: 0x%x\n", hr);
        return;
    }
}
```

## 下载并安装更新

在确定了更新集合后，使用 [XStoreDownloadAndInstallPackageUpdatesAsync](/reference/system/xstore/xstore_members) 将所有更新加入队列并进行下载。

<Note />

此时游戏会终止以应用更新。此过程在没有警告的情况下发生，因此在调用此函数前，请提供充分的用户提示或确认。

```cpp theme={null}
void DownloadUpdates()
{
    std::vector<const char*> packageIds;

    for (XStorePackageUpdate package : m_updates)
    {
        // m_updates populated from the update check
        packageIds.push_back(package.packageIdentifier);
    }

    if (!packageIds.empty())
    {
        auto asyncBlock = new XAsyncBlock{};
        asyncBlock->context = this;
        asyncBlock->queue = m_asyncQueue;
        asyncBlock->callback = [](XAsyncBlock* asyncBlockInner)
        {
            // Called when update is complete
            auto pThis = reinterpret_cast<Sample*>(asyncBlockInner->context);
            HRESULT hr = XStoreDownloadAndInstallPackageUpdatesResult(asyncBlockInner);

            delete asyncBlockInner;
        };

        HRESULT hr = XStoreDownloadAndInstallPackageUpdatesAsync(m_xStoreContext, packageIds.data(), packageIds.size(), asyncBlock);
    }
}
```

## 监控下载进度

当下载正在进行时，使用 [XPackageCreateInstallationMonitor](/reference/system/xstore/xstore_members) 监控下载进度：

```cpp theme={null}
void CreateInstallationMonitor(const char* packageId)
{
    XPackageInstallationMonitorHandle pimHandle;

    HRESULT hr = XPackageCreateInstallationMonitor(packageId, 0, nullptr, 1000, m_asyncQueue, &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);
    }
}
```

## 测试更新

在开发期间，你只能通过本地包来测试更新的可用性。

1. 创建包含更新检查和下载代码的 V1 包。
2. 使用相同的标识但递增的版本号创建 V2 包。
3. 运行 `xbapp/wdapp install` V1。
4. 运行 `xbapp/wdapp update` V2 `/a`。
5. 启动 V1。

确保两个包之间的内容 ID 匹配。

此流程的结果是：V1 中的 `XStoreQueryGameAndDlcPackageUpdatesAsync` 或 `XStoreQueryPackageUpdatesAsync` 调用会找到任何可用更新，然后 `XStoreDownloadAndInstallPackageUpdatesAsync` 会使用发布的 V2 包更新 V1。当 V2 的“下载”正在进行时，此状态会显示在 XBOX 下载队列、XBOX 应用或 Microsoft Store 应用中的队列项目上。安装完成后，V2 就被安装了。你可以使用 `xbapp/wdapp list[dlc]` 验证安装情况。

使用 `/m` 代替 `/a` 会将更新标记为“强制”，这只会影响 [XStorePackageUpdate](/reference/system/xstore/xstore_members)`.isMandatory` 字段。

由于签名差异，你无法从开发版本更新到从商店下载的包。

有关如何创建高效的更新以及不同的测试方法，请参阅下一节中引用的内容更新页面。

## 参考 API 文档

* [XStore（API 内容）](/reference/system/xstore/xstore_members)
  * 函数
    * [XStoreQueryGameAndDlcPackageUpdatesAsync](/reference/system/xstore/xstore_members)
    * [XStoreQueryPackageUpdatesAsync](/reference/system/xstore/xstore_members)
    * [XStoreDownloadAndInstallPackageUpdatesAsync](/reference/system/xstore/xstore_members)
  * 结构体
    * [XStorePackageUpdate](/reference/system/xstore/xstore_members)
* [XPackage（API 内容）](/reference/system/xstore/xstore_members)
  * 函数
    * [XPackageGetCurrentProcessPackageIdentifier](/reference/system/xstore/xstore_members)
    * [XPackageEnumeratePackages](/reference/system/xstore/xstore_members)
    * [XPackageCreateInstallationMonitor](/reference/system/xstore/xstore_members)

## 另请参阅

[商务概述](/publishing/xstore-commerce/xstore-commerce-overview)

[启用 XStore 开发与测试](/publishing/xstore-commerce/xstore-product-testing-setup)

内容更新最佳实践

创建、检查和测试内容更新

[XStore API 参考](/reference/system/xstore/xstore_members)


## Related topics

- [创建、检查和测试内容更新](/zh-CN/build/core-features/common/packaging/packaging-testing-updates.md)
- [XStoreDownloadAndInstallPackageUpdatesAsync](/zh-CN/reference/system/xstore/functions/xstoredownloadandinstallpackageupdatesasync.md)
- [XStoreQueryGameAndDlcPackageUpdatesAsync](/zh-CN/reference/system/xstore/functions/xstorequerygameanddlcpackageupdatesasync.md)
- [XStoreQueryPackageUpdatesAsync](/zh-CN/reference/system/xstore/functions/xstorequerypackageupdatesasync.md)
- [XStorePackageUpdate](/zh-CN/reference/system/xstore/structs/xstorepackageupdate.md)
