Getting started with XBOX GDK.NET

This article describes how to get started writing XBOX games, tools, and services in C# with the Microsoft Game Development Kit (GDK). It points you to XBOX GDK.NET, the .NET projection of the GDK flat C API, which exposes the Gaming Runtime, XBOX services, and PlayFab as ordinary modern C#, and explains what you need in order to run and ship a .NET title on XBOX on PC and on XBOX Series X|S.

.NET is one of several ways you can build with the GDK. For an overview of the engine and framework options and how the GDK fits into each one, see Microsoft Game Development Kit and game engines.

XBOX GDK.NET

XBOX GDK.NET is a source-only reference projection on GitHub. It is a working example of how to bind the Microsoft GDK, XBOX services, and PlayFab into a .NET application, so you can write your title in C# rather than in P/Invoke. The projection is modular: the Gaming Runtime is always present, and XBOX services and each PlayFab group are opt-in at packaging time, so a title that doesn't use a family doesn't carry it.

Important

XBOX GDK.NET requires at least the April 2026 Microsoft GDK Update 4. For the current minimum edition, see the supported versions matrix in the repository, which is the canonical source. Building the projection needs no GDK install at all; running against the Gaming Runtime needs the GDK, a dev-unlocked machine, and a signed-in account.

What's included

XBOX GDK.NET projects the GDK surface a .NET title actually needs, generated and verified against the real GDK headers rather than transcribed by hand:

  • Gaming Runtime - users and sign-in, game invites and protocol activation, storage, packages and DLC, game saves, game UI, networking, capture and broadcast, the Store, game streaming, accessibility, speech, and system metadata
  • XBOX services - profile, achievements, social, presence, privacy, leaderboards, real-time activity, user and title-managed statistics, title storage, string verification, events, multiplayer activity, plus the social and achievements manager layers
  • PlayFab - Core and the full generated Services surface, Game Saves, Multiplayer (Lobby and Matchmaking), and Party including PartyXboxLive
  • NativeAOT - AOT-safe on net8.0 and net10.0, enforced by analyzers, warnings-as-errors, and a real ILC compilation in CI, because consoles don't permit JIT

Coverage is measured rather than asserted: effectively the whole Gaming Runtime and PlayFab export surface is bound, with only a small number of entry points deliberately out of scope. The repository ships eng/api-coverage.ps1, which diffs the bound entry points against each native module's export table, so you can get the current tally for the edition you have installed. For the per-family breakdown, and for what is excluded and why, see Projection status in the repository.

The projection ships no native code of its own. Every P/Invoke binds to a redistributable module that the GDK already installs.

What the projection replaces

The point of XBOX GDK.NET is that a caller never sees a raw flat C convention. Everything the GDK expresses through HRESULTs, handles, and async blocks is expressed instead through the .NET idiom a C# developer already knows:

Microsoft GDK (flat C) XBOX GDK.NET
HRESULT return codes Exceptions (GameRuntimeException and typed subclasses); the numeric code is preserved on HResultCode
XAsyncBlock plus a completion callback plus a second "get result" call Task / Task<T>, awaited normally
Two-call size-then-buffer reads Ordinary properties and return values
Opaque handles with X*CloseHandle IDisposable
XUserRegisterForChangeEvent plus a registration token C# event; unsubscribing unregisters
E_ABORT from a cancelled operation OperationCanceledException via CancellationToken
X*Flags integer constants [Flags] enums

Initializing the runtime and signing in a user is ordinary C#. GameRuntime is both the entry point and the lifetime owner, and the family managers hang off the instance:

using GDK.Net;
using GDK.Net.Users;

using GameRuntime runtime = GameRuntime.Initialize();

using User user = await runtime.Users
    .AddAsync(UserAddOptions.AddDefaultUserSilently)
    .ConfigureAwait(false);

Console.WriteLine($"id 0x{user.Id:X16}, state {user.State}");

In C, those reads are XUserGetId and XUserGetState, each returning an HRESULT with the value in an out parameter. For the idioms in full, see Getting started in the repository.

Opt-in modules

XBOX services and PlayFab are separate native modules, so you choose them at packaging time. eng/packaging/GdkRedist.targets copies the modules you asked for next to the executable on every build.

Opt-in property Native modules Managed surface
(always) xgameruntime.thunks.dll GDK.Net - the Gaming Runtime: GameRuntime, UserManager, GamePackage, GameSaveProvider, StoreContext, NetworkingManager, and the rest
<GdkNetIncludeXboxLive> Microsoft.Xbox.Services.C.Thunks.dll, libHttpClient.dll GameRuntime.XboxLive - profile, achievements, social, presence, privacy, leaderboards, stats, title storage, and the manager layers
<GdkNetIncludePlayFab> PlayFabCore.dll, PlayFabServices.dll, PlayFabGameSave.dll, libHttpClient.dll GDK.Net.PlayFab - PlayFabRuntime, the generated service classes, PlayFabGameSaveFiles
<GdkNetIncludePlayFabMultiplayer> PlayFabMultiplayer.dll GDK.Net.PlayFab.Multiplayer - lobbies and matchmaking
<GdkNetIncludePlayFabParty> Party.dll, PartyXboxLive.dll GDK.Net.PlayFab.Party - voice, text chat, and network transport

The last two PlayFab groups import PlayFabCore.dll, so asking for either turns <GdkNetIncludePlayFab> on as well.

Supported runtimes and engines

Runtime Tier
net8.0 (LTS) Primary
net10.0 (LTS) Primary
netstandard2.0 Compatibility (MonoGame / Mono / broad reach)

All three runtimes target win-x64. The supported architectures, GDK editions, .NET SDK versions, and build toolchain are listed in the supported versions matrix in the repository, which is kept current as new editions are validated.

All three targets export an identical public surface; what differs is how that surface is implemented. The net8.0 and net10.0 targets use [LibraryImport] and [UnmanagedCallersOnly] function pointers, which is what makes them AOT-safe; netstandard2.0 uses [DllImport] and delegates, and exists solely for MonoGame and Mono reach. For the detail, see Architecture.

MonoGame, Stride, and bespoke .NET hosts and tooling on Windows are supported engine and framework targets. Only Microsoft-supported .NET LTS releases are targeted, and the window moves as LTS releases ship and reach end of life.

What this is and what it isn't

  • This is a source-only projection, not a product. It's MIT-licensed at the wrapper layer; the Microsoft GDK and the PlayFab extension libraries it binds to are installed and licensed separately, consistent with our other XBOX samples.

  • There is no set update cadence for support or maintenance. We'll watch the repo, monitor issues, and iterate where it makes sense, but this isn't a commercial release. That said, we're excited to hear your feedback, and see any community PRs, as we evolve this together.

  • Supports only Windows and consoles through the GDK. There is no Linux or macOS support.

Requirements to run

The Gaming Runtime refuses to initialize in a process with no package identity, so running a .NET title against it needs more than the .NET SDK:

To do this You need
Build the library and run the unit tests A current .NET SDK. No GDK install required.
Run anything against the Gaming Runtime An installed Microsoft GDK, a dev-unlocked Windows machine, and an account signed in to the XBOX app
Package a title The GDK, for makepkg.exe
Publish with NativeAOT The MSVC toolchain, because ILC shells out to link.exe

Packaging is not required in order to run. On PC, title identity can come from a MicrosoftGame.config beside the executable rather than from a registered package, so a plain dotnet run or a self-contained publish works on a dev-unlocked machine. Packaging remains what a title ships as.

Get started

Building needs nothing but the .NET SDK:

dotnet restore
dotnet build -c Release
dotnet test -c Release --no-build

Use these resources to clone the repository, build the projection, and start integrating it with your .NET project:

  • XBOX GDK.NET: microsoft/XBOX-GDK-dotnet - The .NET projection of the Microsoft GDK, XBOX services, and PlayFab.
  • Microsoft GDK: microsoft/GDK - Microsoft Public GDK.
  • PlayFab SDK: PlayFab Unified SDK - PlayFab Unified SDK.
  • Documentation: XBOX GDK.NET documentation index - Getting started, building, architecture, projection status, and the generated API reference.
  • Samples: samples/GDK.Net.UserSample and samples/GDK.Net.PlayFabSample - Readable end-to-end demos of sign-in and of the PlayFab surface.
  • Issues: XBOX GDK.NET issues - Report bugs, request features, or contribute back.

After you have integrated the Microsoft GDK with your .NET project, follow the rest of the PC end-to-end guide to register your title, set up your product in Partner Center, and publish your game to the Microsoft Store.

Support for XBOX Series X|S and XBOX One

XBOX consoles don't permit JIT compilation, so a .NET title that ships to console must be NativeAOT-compiled. XBOX GDK.NET is AOT-safe on net8.0 and net10.0, and the repository enforces that with AOT, trim, and single-file analyzers under warnings-as-errors, a real ILC compilation in CI, and a live packaged run on hardware.

AOT is opt-in, not imposed. An ordinary dotnet build, dotnet test, or dotnet publish is unchanged and JIT-compiled, which is what you'll normally use while developing for XBOX on PC. To AOT-publish a title of your own:

dotnet publish -c Release -f net10.0 -r win-x64 --self-contained -p:PublishAot=true

Two environment notes:

  • Use net10.0 (or net9.0), not net8.0. The NativeAOT runtime pack was first published for 9.0, so a net8.0 AOT publish can't be restored with a 10.x SDK. XBOX GDK.NET still targets net8.0 for framework-dependent consumers; only the AOT publish needs the newer target framework.

  • vswhere.exe must be on PATH. ILC resolves link.exe by shelling out to vswhere, so when it's missing you get an opaque MSB3073 rather than a clear error. A vcvars64 shell is not sufficient.

For the background on why NativeAOT matters for games, what it costs you, and how to structure a codebase for it, see NativeAOT for gaming. For the full contract and the verification steps behind it, see NativeAOT in the repository.

If you are building for XBOX Series X|S or XBOX One, contact your XBOX representative. If you are not yet registered, see Register for the ID@XBOX program to get started.