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

# XUserAddAsync

> XUserAddAsync

# XUserAddAsync

Asynchronously adds a user to a game session.

## Syntax

```cpp theme={null}
HRESULT XUserAddAsync(  
         XUserAddOptions options,  
         XAsyncBlock* async  
)  
```

### Parameters

*options*   \_In\_\
Type: [XUserAddOptions](/reference/system/xuser/enums/xuseraddoptions)

Options for adding a user to a game session.

*async*   \_Inout\_\
Type: [XAsyncBlock\*](/reference/system/xasync/structs/xasyncblock)

An [XAsyncBlock](/reference/system/xasync/structs/xasyncblock) for polling for the call's status and retrieving call results.

### Return value

Type: HRESULT

HRESULT success or error code.
For a list of error codes, see [Error Codes](/reference/errorcodes).

## Remarks

**XUserAddAsync** starts an asynchronous operation to add a user to the game. Use
[XUserAddResult](/reference/system/xuser/functions/xuseraddresult) to retrieve the results of the operation.

**XUserAddAsync** always shows an Account Picker UI unless either
[XUserAddOptions::AddDefaultUserSilently](/reference/system/xuser/enums/xuseraddoptions) or
[XUserAddOptions::AddDefaultUserAllowingUI](/reference/system/xuser/enums/xuseraddoptions) is passed to the *options* parameter.

If you use **XUserAddOptions::AddDefaultUserSilently**, **XUserAddAsync** does not show a UI.

There are some considerations with this function when using the [simplified user model (NDA topic)](/build/core-features/common/user/gamecore-user-models):

* With simplified user model, developers should ensure that *options*  is set to
  **XUserAddOptions::AddDefaultUserSilently**:
* On console, loose-deployed games using the simplified user model will not be allowed to
  launch unless there is already a default user signed in.
* On PC, loose-deployed games using the simpfied user model can be launched without a user;
  however, when the game calls **XUserAddAsync**, if nobody is signed in, the game will
  get terminated and the PC Bootstrapper will get launched to help sign-in a user. Subsequent
  launches will work just fine so long as the user is fully signed into XBOX Live.

There are some edge cases that developers should know about if they repeatedly
call **XUserAddAsync** with *options* set to **XUserAddOptions::AddDefaultUserSilently**:

* If you call this repeatedly, and we know the default user who launched the game, it will return that same user.
* If the previously known default user has signed out, and there is only one user signed into the device, it will
  mark that user as the new "default" user and return that.
* If the previously known default user has signed out, and there are multiple users signed into the device, it
  will return E\_GAMEUSER\_NO\_DEFAULT\_USER.

If a default user is not available, [XUserAddResult](/reference/system/xuser/functions/xuseraddresult) returns
E\_GAMEUSER\_NO\_DEFAULT\_USER. You must call **XUserAddAsync** with *options* not set to
**XUserAddOptions::AddDefaultUserSilently**.

There are also some edge cases that developers should know about if they repeatedly call
**XUserAddAsync** with *options* set to **XUserAddOptions::AddDefaultUserAllowingUI**. These are very
similar (but not identical) to the silent UI case:

* If you call this repeatedly, and we know the default user who launched the game, it will return that same user.
* If the previously known default user has signed out, and there is only one user signed into the device, it will mark that user as the new "default" user and return that.
* If the user has signed out who initially launched the game, and the number of users is either 0 or more than 1, the system will show UI to get the user and then set that user as the default.

You cannot use [XUserAddOptions::AllowGuests](/reference/system/xuser/enums/xuseraddoptions) with
**XUserAddOptions::AddDefaultUserSilently**. A guest cannot be the default user. You can safely
use **XUserAddOptions::AllowGuests** regardless of whether the current platform supports guests.

You must close each **XUserHandle** handle you retrieve from an **XUsers** API only once by calling
[XUserCloseHandle](/reference/system/xuser/functions/xuserclosehandle).

Input device pairing is performed upon successful completion of **XUserAddAsync**. If the sign-in happened automatically without UI due to the **XUserAddOptions::AddDefaultUserSilently** or **XUserAddOptions::AddDefaultUserAllowingUI** options, then the input devices assigned to the user in the system are propogated to the title. If the UI was shown for the sign-in, the input device that selected the user is assigned to that user.

Device association can be tracked via the [XUserRegisterForDeviceAssociationChanged](/reference/system/xuser/functions/xuserregisterfordeviceassociationchanged) method.

The following example demonstrates how to asynchronously add a user to a game session.

```cpp theme={null}
HRESULT AddUserComplete(XAsyncBlock* ab)
{
    unique_user_handle user;
    RETURN_IF_FAILED(XUserAddResult(ab, &user));

    XUserLocalId userLocalId;
    XUserGetLocalId(user.get(), &userLocalId);

    auto iter = std::find_if(
        _users.begin(),
        _users.end(),
        [&userLocalId](const User& candidate)
    {
        XUserLocalId candidateUserLocalId;
        XUserGetLocalId(candidate.Handle(), &candidateUserLocalId);
        return candidateUserLocalId == userLocalId;
    });

    // User already known
    if (iter != _users.end())
    {
        appLog.AddLog("User already in list\n");
        return S_OK;
    }

    try
    {
        _users.emplace_back(user.get());
        _users.back().LoadGamerPicAsync(_queue);
    }
    CATCH_RETURN();

    return S_OK;
}

HRESULT AddUser(bool allowGuests, bool silent)
{
    auto asyncBlock = std::make_unique<XAsyncBlock>();
    ZeroMemory(asyncBlock.get(), sizeof(*asyncBlock));
    asyncBlock->queue = _queue;
    asyncBlock->context = this;
    asyncBlock->callback = [](XAsyncBlock* ab)
    {
        auto asyncBlock = std::unique_ptr<XAsyncBlock>(ab);
        LOG_IF_FAILED(static_cast<UserWindow*>(ab->context)->AddUserComplete(ab));
    };

    XUserAddOptions options = XUserAddOptions::None;

    if (allowGuests)
    {
        WI_SET_FLAG(options, XUserAddOptions::AllowGuests);
    }

    if (silent)
    {
        WI_SET_FLAG(options, XUserAddOptions::AddDefaultUserSilently);
    }

    if (SUCCEEDED_LOG(XUserAddAsync(
        options,
        asyncBlock.get())))
    {
        // The call succeeded, so release the std::unique_ptr ownership of XAsyncBlock* since the callback will take over ownership.
        // If the call fails, the std::unique_ptr will keep ownership and delete the XAsyncBlock*
        asyncBlock.release();
    }

    return S_OK;
}
```

## Requirements

**Header:** XUser.h

**Library:** xgameruntime.lib

**Supported platforms:** Windows, Steam Deck, XBOX One family consoles and XBOX Series consoles

## Conceptual documentation

* [Run Microsoft Game Development Kit (GDK) API task](/build/core-features/common/async/async-libraries/async-library-xasync-example-run-gdk-task)
* [Asynchronous programming design goals and improvements](/build/core-features/common/async/async-whitepaper)
* [Implement player sign-in in your game](https://learn.microsoft.com/gaming/gdk/docs/gdk-dev/pc-dev/tutorials/pc-e2e-guide/e2e-services/e2e-user-sign-in)
* [Intro to Game Chat 2](/services/xbox-services/multiplayer/chat/game-chat2/game-chat-2-intro)
* [Using the Game Chat 2 C++ API](/services/xbox-services/multiplayer/chat/game-chat2/using-game-chat-2)
* [Implement player sign in](/services/xbox-services/playfab-integration)

## See also

[XUser](/reference/system/xuser/xuser_members)

[XUserAddOptions](/reference/system/xuser/enums/xuseraddoptions)

[XUserCloseHandle](/reference/system/xuser/functions/xuserclosehandle)


## Related topics

- [User identity and XUser](/build/core-features/common/user/player-identity-xuser.md)
- [XUserAddResult](/reference/system/xuser/functions/xuseraddresult.md)
- [XUserAddOptions](/reference/system/xuser/enums/xuseraddoptions.md)
- [Unity C# API wrappers for the GDK](/build/gdk-and-engines/unity/unity-api-wrappers.md)
- [Headless automation of XUser](/build/core-features/common/user/users-headless-automation.md)
