Publishing MonoGame Desktop Games to Microsoft Store: The Complete MSIX & WAP Guide
Bringing an indie game to the Microsoft Store on Windows 10 and Windows 11 gives developers direct access to hundreds of millions of PC players, seamless updates, Windows Game Bar integration, and containerized installation safety. However, if your game is built with MonoGame (.NET 8.0 or .NET 9.0 WindowsDX), getting it into the store presents a unique architectural challenge: bridging a standard Win32 desktop executable (.exe) with the modern MSIX / AppX application model.
At Arar Games, we have walked this road from initial compilation to live store distribution with titles like Paint Trek and Blocked: Pixel Panzer. In this battle-tested guide, we break down the end-to-end technical pipeline: configuring your projects, navigating Visual Studio's Publish options, mastering the Package.appxmanifest, scaling visual tile assets, resolving Windows App Certification Kit (WACK) errors, and submitting your production bundle to the Microsoft Partner Center.
1. Architectural Foundation: Win32 vs. MSIX
Traditional MonoGame games compile into a standard Win32 executable accompanied by framework runtime .dll files and a Content/ directory containing compiled binary assets (.xnb textures, .ogg audio, sprite sheets, and compiled HLSL shaders).
While Microsoft Store supports distributing loose unpackaged Win32 executables, wrapping your game inside a Windows Application Packaging (WAP) project to produce an MSIX bundle provides substantial technical and operational benefits:
flowchart TD
subgraph "Game Codebase"
Shared["Shared Library\n(Entities, Systems, Game State, Math)"]
Desktop["Desktop Project (.NET 9.0 WindowsDX)\n(Win32 Executable Entry Point)"]
Shared --> Desktop
end
subgraph "Packaging Layer (WAP Project)"
WAP["Windows App Packaging (.wapproj)\n(Microsoft Desktop Bridge)"]
Manifest["Package.appxmanifest\n(Identity, Capabilities, Tile Assets)"]
StoreAssoc["Package.StoreAssociation.xml\n(Partner Center Binding)"]
Desktop --> WAP
Manifest --> WAP
StoreAssoc --> WAP
end
subgraph "Output & Distribution"
WAP -->|Create App Packages| Sideload["Sideloading Package\n(*.appxbundle + Add-AppDevPackage.ps1)"]
WAP -->|Store Upload Mode| UploadBundle["Store Upload Bundle\n(*_bundle.appxupload / *.msixupload)"]
UploadBundle --> MSStore["Microsoft Partner Center\n(Live Store Ingestion)"]
end
Why Wrap MonoGame in a WAP Project?
- Isolated Containerized Lifecycle: MSIX applications run in an isolated environment. Files, virtualized registry entries, and runtime states are cleanly removed upon uninstallation, leaving zero system clutter.
- Dynamic Architecture & Asset Streaming: A single
.appxuploadbundle packagesx86andx64binaries together with multiple DPI scale packs (scale-100throughscale-400). Windows Store delivers only the required architecture and screen assets for each player's device, significantly reducing download sizes. - Automated Crash Telemetry: Visual Studio packages your debugging symbols (
.appxsym) into the upload bundle. If your game encounters an unhandled exception on a player's machine, the Microsoft Partner Center analytics dashboard displays the exact stack trace with function names and line numbers.
2. Project Hierarchy & Configuration
A clean MonoGame solution should maintain strict separation between platform-agnostic game logic and platform packaging:
SolutionDir/
│
├── YourGame.Shared/ # Core game mechanics, systems, levels, entities
│ └── YourGame.Shared.csproj
│
├── YourGame.Desktop/ # Main desktop entry point (WinExe)
│ ├── Content/ # MonoGame Content Pipeline assets (.mgcb -> .xnb)
│ ├── Program.cs
│ └── YourGame.Desktop.csproj
│
└── YourGame.Package/ # Windows App Packaging Project (.wapproj)
├── Images/ # Scaled logos, tiles, splash screen
├── Package.appxmanifest # Identity, capabilities, visual elements
├── Package.StoreAssociation.xml
└── YourGame.Package.wapproj
Step 1: Main Game Project Configuration (.csproj)
Ensure your desktop project is configured for multi-architecture building:
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<OutputType>WinExe</OutputType>
<TargetFramework>net9.0-windows</TargetFramework>
<UseWindowsForms>true</UseWindowsForms>
<ApplicationHighDpiMode>PerMonitorV2</ApplicationHighDpiMode>
<Platforms>AnyCPU;x64;x86</Platforms>
</PropertyGroup>
<!-- Ensure game content is copied during packaging -->
<ItemGroup>
<Content Include="Content\**\*.*">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</Content>
</ItemGroup>
<ItemGroup>
<PackageReference Include="MonoGame.Framework.WindowsDX" Version="3.8.*" />
<PackageReference Include="MonoGame.Content.Builder.Task" Version="3.8.*" />
</ItemGroup>
</Project>
Step 2: Multi-Platform NuGet Restoration
Before compiling a multi-architecture bundle, restore packages explicitly for both 64-bit and 32-bit runtimes:
dotnet restore YourGame.Desktop.csproj -r win-x64
dotnet restore YourGame.Desktop.csproj -r win-x86
3. Demystifying Visual Studio's Publish Menu
When you right-click your Windows Application Packaging project in Visual Studio and expand the Publish submenu, you are presented with three distinct options:
graph TD
Menu["Right Click WAP Project > Publish"]
Menu --> Opt1["1. Associate App with the Store..."]
Menu --> Opt2["2. Convert Content Group Map File"]
Menu --> Opt3["3. Create App Packages... (Primary Workflow)"]
Opt1 --> Sync["Synchronizes Cloud App Identity with Local Manifest\n(Generates Package.StoreAssociation.xml)"]
Opt2 --> Streaming["Streaming Install Asset Conversion\n(For massive games with staged downloads)"]
Opt3 --> Wizards["Package Wizard:\n- Sideloading (Local QA Testing)\n- Microsoft Store Upload (_bundle.appxupload)"]
1. Associate App with the Store...
- Purpose: Connects your local Visual Studio solution with your Microsoft Partner Center developer account.
- What It Does: You sign in with your developer credentials and select your reserved app name. Visual Studio queries the Partner Center API, retrieves your official Publisher ID, Package Name, Publisher Display Name, and Package Family Name (PFN), and generates
Package.StoreAssociation.xml. - Why It Matters: Without this association, your package will be signed with a temporary local certificate that Microsoft Partner Center will immediately reject upon upload due to identity mismatches.
2. Convert Content Group Map File
- Purpose: Supports Microsoft's Streaming Installation architecture.
- What It Does: In massive games (e.g., 50+ GB AAA titles), streaming install allows users to launch the first level while subsequent game content downloads in the background. Developers write a
SourceAppxContentGroupMap.xml(which supports wildcards), and this menu command transforms it into the finalAppxContentGroupMap.xmlrequired by the Windows packaging pipeline. - Relevance for Indie Titles: For standard indie games (under a few gigabytes), streaming installation is unnecessary. You can safely ignore this option.
3. Create App Packages... (The Main Production Wizard)
This is the core tool you will use to build, sign, and package your game for QA testing and store submission.
4. Configuring the Package Creation Wizard
When you click Publish \(\rightarrow\) Create App Packages..., follow this exact production workflow:
Step 1: Select Distribution Method
- For Store Submission: Select "Microsoft Store under a new or existing app name". This links the build to your verified cloud identity and optimizes the archive for Microsoft Store signing.
- For Local QA / Sideloading: Select "Sideloading". This creates a
.msixbundleor.appxbundlesigned with a generated test certificate (.cer) along with installation scripts (Add-AppDevPackage.ps1), allowing you to test on other PCs without publishing.
Step 2: Select and Configure Packages
On the configuration screen, adjust the parameters:
┌─────────────────────────────────────────────────────────────┐
│ Output location: .\AppPackages\ │
│ Version: 1.0.0.0 [☑ Automatically increment] │
│ │
│ Generate app bundle: Always │
│ │
│ Architectures: │
│ ☑ x86 Configuration: Release (x86) │
│ ☑ x64 Configuration: Release (x64) │
│ ☐ ARM (Not recommended for desktop Win32 games) │
│ ☐ ARM64 (Not recommended for desktop Win32 games) │
│ │
│ Options: │
│ ☑ Include public symbol files │
│ ☑ Generate artifacts to validate app with WACK │
└─────────────────────────────────────────────────────────────┘
Understanding Version Numbering:
Windows packaging follows standard Semantic Versioning: Major.Minor.Build.Revision.
- Initial release starts at
1.0.0.0. - Minor patches increment revision (
1.0.1.0), while major releases increment the minor or major digits (1.1.0.0,2.0.0.0). - The Absolute Store Rule: Every new package uploaded to Microsoft Partner Center must have a higher version number than the currently active package.
Automatically increment: Keeping this checked increments the Revision digit with every build, preventing accidental upload rejections due to duplicate version numbers.
Why x64 + x86 with Generate app bundle: Always?
x64: Targets modern 64-bit Windows installations (98%+ of desktop PC gamers).x86: Provides fallback compatibility for older 32-bit hardware.AlwaysBundle: Visual Studio bundles both architectures into a single archive (_bundle.appxupload). Players only download the specific binary for their processor architecture.
5. Mastering Package.appxmanifest
The manifest defines runtime requirements, visual assets, display orientation, and permissions:
<?xml version="1.0" encoding="utf-8"?>
<Package
xmlns="http://schemas.microsoft.com/appx/manifest/foundation/windows10"
xmlns:uap="http://schemas.microsoft.com/appx/manifest/uap/windows10"
xmlns:rescap="http://schemas.microsoft.com/appx/manifest/foundation/windows10/restrictedcapabilities"
IgnorableNamespaces="uap rescap">
<Identity
Name="YourPublisher.YourGame"
Publisher="CN=YOUR-OFFICIAL-PUBLISHER-ID"
Version="1.0.0.0" />
<Properties>
<DisplayName>Your Game Title</DisplayName>
<PublisherDisplayName>Your Studio Name</PublisherDisplayName>
<Logo>Images\StoreLogo.png</Logo>
</Properties>
<Dependencies>
<TargetDeviceFamily Name="Windows.Universal" MinVersion="10.0.0.0" MaxVersionTested="10.0.0.0" />
<TargetDeviceFamily Name="Windows.Desktop" MinVersion="10.0.17763.0" MaxVersionTested="10.0.26100.0" />
</Dependencies>
<Applications>
<Application Id="App"
Executable="$targetnametoken$.exe"
EntryPoint="$targetentrypoint$">
<uap:VisualElements
DisplayName="Your Game Title"
Description="An action-packed 2D arcade shooter built with MonoGame."
BackgroundColor="transparent"
Square150x150Logo="Images\Square150x150Logo.png"
Square44x44Logo="Images\Square44x44Logo.png">
<uap:DefaultTile
Wide310x150Logo="Images\Wide310x150Logo.png"
Square71x71Logo="Images\SmallTile.png"
Square310x310Logo="Images\LargeTile.png" />
<uap:SplashScreen Image="Images\SplashScreen.png" />
<uap:LockScreen BadgeLogo="Images\BadgeLogo.png" Notification="badgeAndTileText"/>
<uap:InitialRotationPreference>
<uap:Rotation Preference="landscape"/>
</uap:InitialRotationPreference>
</uap:VisualElements>
</Application>
</Applications>
<Capabilities>
<Capability Name="internetClient" />
<rescap:Capability Name="runFullTrust" />
</Capabilities>
</Package>
Essential Settings:
<rescap:Capability Name="runFullTrust" />: Because MonoGame relies on DirectX 11, unmanaged hardware drivers, and raw Win32 message handling via SharpDX or SDL, it cannot execute inside a sandbox app-container.runFullTrustgrants desktop privileges while retaining containerized file safety.InitialRotationPreferenceset tolandscape: Windows gaming handhelds (e.g., ASUS ROG Ally, Lenovo Legion Go, GPD Win) run portrait-native displays with hardware rotation. Explicitly settinglandscapeprevents the game from opening sideways or flipped.
6. The Visual Asset Scaling Grid & The BadgeLogo Trap
Windows displays application icons across varying desktop DPI settings (scale-100, scale-125, scale-150, scale-200, scale-400). Missing scale variations cause blurry rendering or validation warnings.
| Asset Type | Base Size (scale-100) | scale-200 | scale-400 | Purpose |
|---|---|---|---|---|
| Square44x44Logo | 44 x 44 px | 88 x 88 px | 176 x 176 px | Taskbar and Start app list |
| Square150x150Logo | 150 x 150 px | 300 x 300 px | 600 x 600 px | Medium Start Menu tile |
| Wide310x150Logo | 310 x 150 px | 620 x 300 px | 1240 x 600 px | Wide Start Menu tile |
| LargeTile | 310 x 310 px | 620 x 620 px | 1240 x 1240 px | Large Start Menu tile |
| SmallTile | 71 x 71 px | 142 x 142 px | 284 x 284 px | Small Start Menu tile |
| SplashScreen | 620 x 300 px | 1240 x 600 px | 2480 x 1200 px | Initial launch window banner |
| StoreLogo | 50 x 50 px | 100 x 100 px | 200 x 200 px | Store catalog tile |
| BadgeLogo | 24 x 24 px | 48 x 48 px | 96 x 96 px | Lock screen notification badge |
Warning
The Monochrome BadgeLogo Requirement:
The lock screen badge (BadgeLogo) must consist strictly of pure white (#FFFFFF) pixels and alpha transparency. If you include colored pixels or gradients in your BadgeLogo assets, Windows App Certification Kit (WACK) will flag a contrast violation and fail certification.
7. Package Verification: WACK & Troubleshooting
Once Visual Studio finishes building, the Finished creating package screen appears:
Output location: [Your Solution Dir]\AppPackages\
Package that will be validated: ...\YourApp_1.0.0.0_x86_x64.appxbundle
Common Obstacle: "The tool AppCert.exe wasn't found"
Clicking Launch Windows App Certification Kit might trigger this error:
Microsoft Visual Studio:
The tool AppCert.exe wasn't found. Please ensure that the most recent
installation of the Windows Software Development Kit includes the
Windows App Certification Kit feature.
Why This Occurs & How to Resolve It:
- Visual Studio's default workload installation sometimes omits the standalone WACK binary.
- Resolution: Open Visual Studio Installer \(\rightarrow\) Modify \(\rightarrow\) Navigate to Individual components \(\rightarrow\) Search for "Windows App Certification Kit" \(\rightarrow\) Check the box and complete the installation.
- Alternative: Running WACK locally is optional. If your manifest and assets are properly configured, you can proceed directly to uploading your package to Microsoft Partner Center. Microsoft's cloud ingestion pipeline runs comprehensive automated certification tests automatically upon submission.
The MonoGame "Blocked Executable" False Positive
When running WACK against a MonoGame application, you might observe a warning listing compiled texture files (.xnb) or audio streams (.ogg) as potential unverified executables.
Why does this happen?
Compressed binary data inside .xnb or .ogg files can coincidentally match byte patterns of portable executable (PE) headers. As long as these files reside strictly inside your game's Content/ directory and are not executed via system calls, Microsoft's certification team acknowledges them as static game assets and approves the submission without issue.
8. Sideloading: Testing Before Store Submission
Before submitting to the store, verify your packaged build on a clean machine:
- Locate the test output folder:
AppPackages/YourGame_1.0.0.0_Test/ - In this folder, you will find:
YourGame_1.0.0.0_x86_x64.appxbundle(or.msixbundle)YourGame_1.0.0.0_x86_x64.cer(Local test signing certificate)Add-AppDevPackage.ps1(PowerShell installer)
- Right-click PowerShell and select Run as Administrator, then execute:
Set-ExecutionPolicy RemoteSigned -Scope Process .\Add-AppDevPackage.ps1 - Follow the interactive prompts to trust the development certificate and install the app.
- Launch the game directly from the Windows Start Menu to confirm that gamepad controls, high-DPI scaling, audio playback, and graphics rendering perform smoothly in the containerized environment.
9. Microsoft Partner Center Submission Checklist
With your verified _bundle.appxupload file ready, log in to Microsoft Partner Center:
Dashboard > Apps & Games > [Your Game Title] > Start submission
1. Pricing and Availability
- Markets: Select
All worldwide markets(240 territories). - Base Price: Set your price in USD (e.g.,
$0.99orFree). Microsoft automatically converts regional prices into local currencies.
2. Properties & Privacy Policy
- Category: Set to
Games\(\rightarrow\) Select up to 3 relevant subgenres (e.g.,Action + adventure,Shooter,Arcade). - Privacy Policy URL: Because the manifest declares
<Capability Name="internetClient" />, Microsoft mandates an active privacy policy URL (a GitHub repository page or website link is sufficient). - Game Settings: Check
Single player\(\rightarrow\)PC.
3. Age Ratings (IARC Questionnaire)
- Complete the International Age Rating Coalition (IARC) questionnaire.
- Accurately declare that your arcade game does not feature graphic gore, profanity, or real-money gambling. Arcade titles like Paint Trek or Blocked typically receive an Everyone / PEGI 3 rating immediately.
4. Store Listings & ASO (App Store Optimization)
- Description: Detail your game mechanics, weapon systems, level progression, and controller support.
- Screenshots: Upload 1920x1080 (16:9) PC screenshots showing actual gameplay. Ensure your desktop screenshots do not show mobile on-screen touch joysticks!
- Keywords: Add relevant search tags (e.g.,
monogame,pixel,arcade,retro,shooter).
5. Package Upload & Ingestion
- Navigate to Packages and drag-and-drop your
..._bundle.appxuploadfile. - Partner Center will parse the archive, verify
x86andx64architectures, extract symbol files, and confirm capabilities. - Once all sections display green checkmarks, click Submit to the Store. Certification typically completes within 24 to 72 hours.
10. Automation: Headless MSBuild Pipeline
For automated CI/CD pipelines (GitHub Actions, Azure DevOps, or local automation scripts), you can compile your WAP project directly via MSBuild without opening Visual Studio:
msbuild YourGame.Package\YourGame.Package.wapproj `
/p:Configuration=Release `
/p:Platform=x64 `
/p:AppxBundlePlatforms="x86|x64" `
/p:AppxBundle=Always `
/p:UapAppxPackageBuildMode=StoreUpload `
/p:AppxPackageDir=".\AppPackages\"
Combining this command with the Microsoft Store Submission API allows you to push game updates directly to the store upon tagging a new release in Git.
Conclusion
Publishing a MonoGame desktop application to the Microsoft Store does not require refactoring your codebase for UWP or compromising on .NET 9 performance. By encapsulating your desktop build within a Windows Application Packaging (WAP) project, configuring runFullTrust, standardizing your asset scale grid, and packaging hybrid x86|x64 bundles, you gain a modern, trusted presence on Windows 10 and Windows 11.
With this pipeline in place, you can focus on what matters most: delivering fantastic gameplay experiences to PC gamers across the globe!
Hiç yorum yok:
Yorum Gönder