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

# XStoreQueryAssociatedProductsAsync

> XStoreQueryAssociatedProductsAsync

# XStoreQueryAssociatedProductsAsync

取得使用者可在目前遊戲中購買之產品的商店清單資訊。

## 語法

```cpp theme={null}
HRESULT XStoreQueryAssociatedProductsAsync(  
         const XStoreContextHandle storeContextHandle,  
         XStoreProductKind productKinds,  
         uint32_t maxItemsToRetrievePerPage,  
         XAsyncBlock* async  
)  
```

### 參數

*storeContextHandle*   \_In\_\
類型：XStoreContextHandle

由 [XStoreCreateContext](/zh-TW/reference/system/xstore/functions/xstorecreatecontext) 傳回之使用者的商店內容控制代碼。

*productKinds*   \_In\_\
類型：[XStoreProductKind](/zh-TW/reference/system/xstore/enums/xstoreproductkind)

要傳回的產品類型。

*maxItemsToRetrievePerPage*   \_In\_\
類型：uint32\_t

每頁要擷取的項目數目上限。
每頁傳回的項目數目可介於 0 到 `maxItemsToRetrievePerPage` 之間。
如需詳細資訊，請參閱[分頁](#paging)。

*async*   \_Inout\_\
類型：[XAsyncBlock\*](/zh-TW/reference/system/xasync/structs/xasyncblock)

定義正在進行之非同步工作的 [XAsyncBlock](/zh-TW/reference/system/xasync/structs/xasyncblock)。
使用 [XAsyncBlock](/zh-TW/reference/system/xasync/structs/xasyncblock) 來輪詢呼叫的狀態並擷取呼叫結果。
如需詳細資訊，請參閱 [XAsyncBlock](/zh-TW/reference/system/xasync/structs/xasyncblock)。

### 傳回值

類型：HRESULT

HRESULT 成功或錯誤碼。

## 備註

若要取得此函式的商店清單資訊與執行結果，請在呼叫此函式之後呼叫 [XStoreQueryAssociatedProductsResult](/zh-TW/reference/system/xstore/functions/xstorequeryassociatedproductsresult)。
[XStoreQueryAssociatedProductsResult](/zh-TW/reference/system/xstore/functions/xstorequeryassociatedproductsresult) 包含一個 `XStoreProductQueryHandle`，您可以呼叫 [XStoreEnumerateProductsQuery](/zh-TW/reference/system/xstore/functions/xstoreenumerateproductsquery) 來列舉它。

您無法事先得知此查詢會傳回的產品數目。

此 API 只會傳回使用者可在 Microsoft Store 中瀏覽或在遊戲內購買的產品。
結果不包含任何已隱藏、已過期或已從商店移除的產品。
如果您需要這類產品的詳細資料，請使用 [XStoreQueryProductsAsync](/zh-TW/reference/system/xstore/functions/xstorequeryproductsasync) 並傳入該產品的 Store ID。

## 分頁

此函式會跨多個頁面傳回產品 (單一頁面最多 `maxItemsToRetrievePerPage` 個項目)。
使用 [XStoreProductsQueryHasMorePages](/zh-TW/reference/system/xstore/functions/xstoreproductsqueryhasmorepages) 和 [XStoreProductsQueryNextPageAsync](/zh-TW/reference/system/xstore/functions/xstoreproductsquerynextpageasync)/[XStoreProductsQueryNextPageResult](/zh-TW/reference/system/xstore/functions/xstoreproductsquerynextpageresult) 來處理所有分頁結果。
在 `XStoreProductsQueryHasMorePages` 傳回 false 之前，分頁都尚未完成。

<Note>
  分頁在沙箱與 RETAIL 之間的行為可能不同。
  在沙箱中，項目會累積到 `maxItemsToRetrievePerPage` 個之後才傳回一頁。
  在 RETAIL 中，每頁傳回 0 到 1 個項目是很常見的情況。

  所有使用此 API 的遊戲都務必在發行前實作並測試分頁。

  若要在沙箱中測試分頁行為，請暫時將 `maxItemsToRetrievePerPage` 設為小於已發佈至您沙箱之產品數目的值。
  若要在遊戲發行前於 RETAIL 中測試，請使用 Partner Center 中「定價和可用性」頁面上的 **Enable Private Audience** 選項來發佈產品。
  若要在遊戲發行後於 RETAIL 中測試，請使用套件測試版本 (package flight)。
</Note>

下列程式碼示範如何跨多個頁面擷取產品查詢結果。

請確保查詢控制代碼會沿著分頁遞迴向下傳遞，以避免洩漏。

```cpp theme={null}
struct QueryContext
{
    uint32_t count = 0;  // used to accumulate count of products returned across pages
    XStoreProductQueryHandle handle = nullptr;  // handle to reuse for paged operations
};

void CleanupProductQuery(XAsyncBlock* async)
{
    if (!async) return;

    auto* ctx = static_cast<QueryContext*>(async->context);
    if (ctx)
    {
        if (ctx->handle)
        {
            XStoreCloseProductsQueryHandle(ctx->handle);
            ctx->handle = nullptr;
        }

        delete ctx;
        async->context = nullptr;
    }

    delete async;
}

bool CALLBACK ProductEnumerationCallback(const XStoreProduct* product, void* context)
{
    // Use result of query
    auto* ctx = static_cast<QueryContext*>(context);

    // Empty results are possible and should be skipped
    if (product)
    {
        printf("%s %s %u\n", product->title, product->storeId, product->productKind);
        ctx->count++;
    }

    return true;
}

void CALLBACK QueryAssociatedProductsCallback(XAsyncBlock* async)
{
    auto* ctx = static_cast<QueryContext*>(async->context);

    HRESULT hr = XStoreQueryAssociatedProductsResult(async, &ctx->handle);
    if (FAILED(hr)) { CleanupProductQuery(async); return; }

    hr = XStoreEnumerateProductsQuery(ctx->handle, ctx, ProductEnumerationCallback);
    if (FAILED(hr)) { CleanupProductQuery(async); return; }

    // Check if there are more pages to process
    if (XStoreProductsQueryHasMorePages(ctx->handle))
    {
        QueryNextPage(async);
        return;
    }

    printf("Enumeration complete, %u products found\n", ctx->count);
    CleanupProductQuery(async);
}

void QueryAssociatedProducts(XStoreContextHandle storeContextHandle, XTaskQueueHandle taskQueueHandle)
{
    auto async = new XAsyncBlock{};
    async->context = new QueryContext{ 0, nullptr };
    async->queue = taskQueueHandle;
    async->callback = QueryAssociatedProductsCallback;

    XStoreProductKind typeFilter =
        XStoreProductKind::Consumable |
        XStoreProductKind::Durable |
        XStoreProductKind::Game |
        XStoreProductKind::Pass |
        XStoreProductKind::UnmanagedConsumable;

    HRESULT hr = XStoreQueryAssociatedProductsAsync(
        storeContextHandle,
        typeFilter,
        25,          // Products per page (25 is a good default, can set lower to verify paging in sandbox)
        async);

    if (FAILED(hr))
    {
        CleanupProductQuery(async);
    }
}

// In RETAIL, content will be returned across multiple pages.
// Paging is not complete until XStoreProductsQueryHasMorePages returns false.
void QueryNextPage(XAsyncBlock *async)
{
    async->callback = [](XAsyncBlock* async)
    {
        auto* ctx = static_cast<QueryContext*>(async->context);

        XStoreProductQueryHandle next = nullptr;
        HRESULT hr = XStoreProductsQueryNextPageResult(async, &next);
        if (FAILED(hr)) { CleanupProductQuery(async); return; }

        // Safe swap: avoids leaks if 'next' is a new handle, avoids double-close if identical
        if (next && next != ctx->handle)
        {
            if (ctx->handle) XStoreCloseProductsQueryHandle(ctx->handle);
            ctx->handle = next;
        }
        else
        {
            ctx->handle = next; // covers null or same-handle cases
        }

        hr = XStoreEnumerateProductsQuery(ctx->handle, ctx, ProductEnumerationCallback);
        if (FAILED(hr)) { CleanupProductQuery(async); return; }

        // Check if there are more pages to process
        if (XStoreProductsQueryHasMorePages(ctx->handle))
        {
            QueryNextPage(async);
            return;
        }

        printf("Enumeration complete, %u products found\n", ctx->count);
        CleanupProductQuery(async);
    };

    auto* ctx = static_cast<QueryContext*>(async->context);
    HRESULT hr = XStoreProductsQueryNextPageAsync(ctx->handle, async);
    if (FAILED(hr))
    {
        CleanupProductQuery(async);
    }
}

```

## 需求

**標頭：** XStore.h (包含在 XGameRuntime.h 中)

**程式庫：** xgameruntime.lib

**支援的平台：** Windows、XBOX One 系列主機和 XBOX Series 主機

## 概念文件

* [在遊戲中實作遊戲內購買](https://learn.microsoft.com/gaming/gdk/docs/gdk-dev/pc-dev/tutorials/pc-e2e-guide/e2e-services/e2e-in-game-purchases)
* [基本商店作業](/zh-TW/publishing/xstore-commerce/xstore-basic-operations)
* [授與玩家附加元件內容的存取權](/zh-TW/publishing/xstore-commerce/xstore-granting-access)
* [GDK 商務系統概觀](/zh-TW/publishing/xstore-commerce/xstore-overview)
* [Microsoft Store API 的細微速率限制](/zh-TW/publishing/xstore-commerce/xstore-fgrl)
* [商店開發權利工具 (DevEntitlementTool.exe)](/zh-TW/tools/tools-services/live-dev-entitlements-tool)

## 另請參閱

[XStore](/zh-TW/reference/system/xstore/xstore_members)\
[XStoreQueryAssociatedProductsResult](/zh-TW/reference/system/xstore/functions/xstorequeryassociatedproductsresult)\
[XStoreEnumerateProductsQuery](/zh-TW/reference/system/xstore/functions/xstoreenumerateproductsquery)\
[XStoreProductsQueryHasMorePages](/zh-TW/reference/system/xstore/functions/xstoreproductsqueryhasmorepages)\
[XStoreProductsQueryNextPageAsync](/zh-TW/reference/system/xstore/functions/xstoreproductsquerynextpageasync)\
[基本商店作業](/zh-TW/publishing/xstore-commerce/xstore-basic-operations)\
[授與玩家附加元件內容的存取權](/zh-TW/publishing/xstore-commerce/xstore-granting-access)


## Related topics

- [XStoreQueryAssociatedProductsAsync](/reference/system/xstore/functions/xstorequeryassociatedproductsasync.md)
- [XStoreQueryAssociatedProductsResult](/reference/system/xstore/functions/xstorequeryassociatedproductsresult.md)
- [XStoreQueryAssociatedProductsForStoreIdAsync](/reference/system/xstore/functions/xstorequeryassociatedproductsforstoreidasync.md)
- [XStoreQueryProductsAsync](/reference/system/xstore/functions/xstorequeryproductsasync.md)
- [XStoreQueryProductForPackageAsync](/reference/system/xstore/functions/xstorequeryproductforpackageasync.md)
