September 11th, 2024

Modernize your UWP app with preview UWP support for .NET 9 and Native AOT

Sergio Pedri
Senior Software Engineer

We’re introducing the initial preview UWP (Universal Windows Platform) support for .NET 9, providing a path for existing UWP developers to modernize their apps with the latest .NET and Native AOT.

Preview UWP support for .NET 9

Are you a UWP app developer considering migrating to Windows App SDK and WinUI 3? Or wanting to leverage the latest releases of .NET and Native AOT? Or perhaps you’ve been struggling with referencing new versions of your favorite libraries, because they only include support for .NET 6 and above? Well, look no further! This preview UWP support for .NET 9 provides a path for UWP apps to modernize using the latest version of .NET.

Note

UWP support for .NET 9 is available in preview, and as such you should expect to potentially find issues, as well as missing functionality (such as no XAML Designer at the moment). You should also expect some binary size regressions compared to .NET Native (more on this below). This first public preview is only the first step in this journey for UWP apps to adopt the latest version of .NET, and we’re looking forward to your feedback (see #summary for support contacts) as we work on improving the tooling and the developer experience to make it as good as possible.

What is the UWP support for .NET 9

This preview is a set of updated tools and components that are part of .NET, Visual Studio, the Windows SDK, and more, to allow using the latest version of .NET and C# for building UWP apps. This preview does not introduce any new features for UWP. Instead, it provides a migration path for developers to modernize their apps with .NET 9 while they consider moving toward WinUI 3. It is rather a way for UWP app developers to modernize their apps and leverage all the recent advancements in .NET and C#, while still retaining the existing features that UWP provides today.

Note

If you are starting to develop new Windows apps, we recommend you consider using the Windows App SDK and WinUI 3 rather than UWP. Although still officially supported, UWP is not under active development. You can refer to Start developing Windows apps for more information. If you’d like to keep leveraging AppContainer (see #glossary) for extra security, just like UWP, refer to MSIX AppContainer apps to see how you can configure your WinUI 3 app to be a partial trust Windows app.

The main goals of the UWP support for .NET 9 are as follows:

  • Providing a better migration path for UWP developers wanting to migrate to WinUI 3. Rather than having to perform the entire migration in a single step (meaning both updating all the .NET runtime as well as the entire UI framework and app model), the UWP support for .NET 9 provides an incremental path towards WinUI 3. By allowing you to focus on upgrading the .NET runtime, separate from the UI framework and app model, and adopting advances in .NET to modernize your codebase, you can now split the migration into two “checkpoints”. First, move to .NET 9, and get the app working under Native AOT (which can already require significant work depending on the scenarios). Then, after making sure that this first part of the migration is successful, you can focus on switching from UWP XAML to WinUI 3, and to the Win32 app model. Using this approach makes the migration more incremental, and less risky. This is also the approach that we are taking with the Microsoft Store: we are currently working on migrating to .NET 9, and we plan on shipping a new version of the app running on Native AOT in the near future.
  • Enabling developers to remove dependencies on .NET Native, so they can benefit from the latest .NET and C# features, no matter what their app model is. If you are currently targeting UWP because you can’t migrate to Windows App SDK and WinUI 3 for some reason (maybe because Windows App SDK doesn’t support some critical APIs, or because you don’t have resources to do a full migration yet), we still want to allow you to get up to par with all other Windows UI frameworks. This update reduces the friction UWP developers experience when attempting to modernize legacy apps using older libraries from the ecosystem. Additionally, it will allow you to stop using .NET Native, which on top of being limited to more or less the .NET Core 2.0 feature level (and just .NET Standard 2.0 for shared class libraries), has extremely slow build times, poor debugging support for issues related to trimming and AOT compatibility, and is only receiving security updates.

Whether you’re migrating from UWP to WinUI 3, or you’re just trying to be more productive on your app’s existing UI framework, this preview lets you modernize to the latest .NET and C# and take advantage of recent tooling improvements to ease your migration journey.

Tip

If you’re not familiar with all the exact terminology around UWP and all related technologies, or if you’d simply like to learn more, you can refer to the #glossary section at the end of this blog post. This glossary provides all the context you might need to fully understand where the UWP support for .NET 9 ties into the Windows platform.

How to get started

In order to try out the UWP support for .NET 9, a few preview tools are needed. Here’s everything you’ll need to install.

First, make sure to get Visual Studio 2022 17.12 Preview 2, which went live just yesterday! All new tooling is included in the “Universal Windows Platform tools” section under the “Windows application development” workload. To install all the necessary components, follow these easy steps:

  • Open the Visual Studio Installer.
  • Under “Workloads” > “Desktop & Mobile”, select the “Windows application development” workload.
  • Under “Optional” (in the right pane), select:
    • “Universal Windows Platform tools”, which contains all tooling for UWP apps
    • “Windows 11 SDK (10.0.26100.0)”, needed to build UWP XAML apps

The Visual Studio Installer, with the UWP components selected to install all necessary tooling to leverage the UWP support for .NET 9

You’ll also need an updated version of the XAML compiler that supports .NET 9 projects. This will be included in an upcoming servicing release of the Windows 11 SDK (10.0.26100.0). However, if you want to try things out today, we have a small bundle with just the updated XAML compiler, which you can manually patch on your machine. To do that, download the preview Windows SDK bundle and follow the instructions in the README file.

Next, you’ll need to install the latest nightly build of the .NET SDK, which you can download from the .NET SDK GitHub repo. These changes will also be available in .NET 9 RC2, once it releases later this year. For the time being, you’ll find the download link for .NET 9 nightly builds in the latest builds table page. Don’t forget to follow the instructions in the README to also add the necessary preview NuGet feed for .NET 9 packages. In order to avoid installing nightly .NET SDK builds machine-wide, you can pick the .zip option of the .NET SDK instead of the installer. Then, extract it in a folder of your choosing (we recommend excluding the folder from Windows Defender for extra build performance or setting up a DevDrive), and add it to PATH. This is a convenient way to try out nightly builds without having to worry about uninstalling them later on.

For further convenience, below is the contents of a complete nuget.config file you can copy-paste next to your .sln file that includes the .NET 9 feed. This will ensure that UWP .NET projects using the latest nightly build of the .NET 9 SDK from the .NET SDK repo will be able to correctly restore all their dependent NuGet packages:

<?xml version="1.0" encoding="utf-8"?>
<configuration>
  <packageSources>
    <clear />
    <add key="nuget" value="https://api.nuget.org/v3/index.json" />
    <add key="dotnet9" value="https://pkgs.dev.azure.com/dnceng/public/_packaging/dotnet9/nuget/v3/index.json" />
  </packageSources>
</configuration>

As part of the UWP support for .NET 9, we now also have new project templates for UWP apps and libraries. To get started, install this VSIX to get all the new templates (in preview), which we’ll be using in the guide below as well to show how to create a new UWP project with .NET 9 support.

And that’s it! All other changes across other components are included or referenced by default. Now that all preview tools are installed, we can actually start creating our first UWP .NET 9 project, or start migrating our existing UWP applications to the latest .NET and C#.

Note

This preview should be seen as an incremental migration step, with the ultimate goal of moving toward WinUI 3 for the most up-to-date and actively supported framework.

Creating a UWP .NET 9 project

After installing the VSIX we linked above, the new templates should show up automatically when opening Visual Studio, or you can also easily filter all templates by searching for “UWP”. These templates are meant to be a convenient way to create updated UWP apps, libraries, runtime components, and more, targeting .NET 9, both to help migrating existing apps, as well as for developers wanting to experiment with new project ideas.

To see all these new templates, launch Visual Studio and click “Create a new project”:

The new project templates for UWP apps using .NET 9, initially provided through a VSIX installer as part of the preview UWP support for .NET 9

We included 5 new project templates:

  • Blank UWP App (Preview for .NET 9): this is a classic UWP XAML applications, and the most popular UWP project template. If you’re not sure where to start, click on this project template. Just like the original project template for UWP, it includes some basic setup with a root Frame, a MainPage that is navigated to, and minimal sample XAML content. This project template also features single-project MSIX support, just like WinUI 3 applications (and just like classic UWP does). This ensures a smooth migration path from classic UWP to WinUI 3 as well.
  • Blank UWP CoreApplication App (Preview for .NET 9): this is a brand new template, that was previously only available for UWP C++ applications. This is meant for more advanced scenarios, and it allows creating apps with purely Composition/DirectX content, with no XAML whatsoever! It’s also perfect for experimenting with Win2D and graphics APIs.
  • UWP Windows Runtime Component (Preview for .NET 9): a managed WinRT component, using latest the latest versions of .NET and CsWinRT. It can be used on its own to create reusable software components that can be shared across applications, or to implement UWP functionality that requires WinRT component activation. For instance, you can use this template to implement out-of-process UWP background tasks or custom video effects.
  • UWP Class Library (Preview for .NET 9): a UWP class library using latest .NET and C#, with XAML support.
  • Blank UWP App with Windows Application Packaging Project (Preview for .NET 9): this project is equivalent to the first one, except that rather than leveraging single-project MSIX packaging, it uses a separate Windows Application Packaging project.

Let’s click on “Blank UWP App (Preview for .NET 9)” to try it out (make sure to select Windows 11 22H2, build 26100, as the target framework, in the new project wizard), and let’s inspect the resulting project. You will notice that it combines all the familiar aspects of UWP XAML apps (the app manifest file, App.xaml with shared resources and basic initialization of the root Frame and navigation to a page, and MainPage, the default XAML page that is displayed when the application is launched), with things that should be familiar to you if you’ve worked with modern .NET before. In particular, we now (finally! 🎊) have an SDK-style .csproj file (no more super verbose legacy-style .csproj with all individual XAML and C# files listed!), and a Properties folder with some launch and publish settings.

Tip

When creating a new project with one of the preview templates, you might get an error dialog saying “Operation is not valid due to the current state of the object.”. This is due to the UWP Project Wizard in Visual Studio not supporting .NET 9 projects yet. This issue will be fixed in the next release of Visual Studio. As a temporary workaround, you can close Visual Studio, open it again, manually open the .sln file that was created, and then right click > Add > Existing Project, and browse the new .csproj file that was created. That error dialog does not prevent the actual project from being created and saved on disk. If you’re instead using one of the new templates to create a project in an existing solution, the new project should just show up correctly after dismissing the error dialog.

For this initial preview (using Visual Studio 17.12 Preview 2), you’ll need to make a slight temporary modification to the .csproj in order for things to work. The UWP support for .NET 9 is currently relying on the single-project MSIX tooling in Windows App SDK, which is causing the WebView2 NuGet package to also be referenced by default. We have made changes for it to support UWP .NET 9 apps as well, but those are not released publicly just yet. So for now, you need to manually exclude all assets from that NuGet package to avoid it causing build errors. Without those, you’ll probably see something like this in the errors window when trying to build your project:

Error WMC1006: "Cannot resolve Assembly or Windows Metadata file 'Type universe cannot resolve assembly: System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089.'"

To fix this, we can add the following to the .csproj file:

<PackageReference Include="Microsoft.Web.WebView2" Version="1.0.2783-prerelease" IncludeAssets="none" />

This is only temporary, and it will no longer be needed once the new update for this package is released.

With all of these changes, we should end up with the following:

The .csproj for a UWP app targeting .NET 9 and NativeAOT, using the new preview UWP support for .NET 9

So clean! We just need a total of 16 lines of code (ignoring the temporary WebView2 workaround), and nothing else! Alright, now that our new project is ready, it’s time to run our very first UWP .NET 9 app! We can just click the green “Start Debugging” button in Visual Studio as always:

A UWP .NET 9 app running with the debugger in Visual Studio

And there it is: UWP XAML running on .NET 9! 🚀

We made changes to several components in Visual Studio to ensure a great developer experience. You’ll notice:

  • XAML IntelliSense is supported, including code completion, suggestions, etc.
  • XAML Live Preview shows up by default as it does in classic UWP
  • XAML Diagnostics works as expected, and you can see the toolbar and the live visual tree on the left
  • All .NET diagnostic tools will work as expected: this is the same latest .NET you know and love!
  • We also support XAML Hot Reload (as well as C# Hot Reload)!

This first preview does not include the XAML designer, but keep reading for more info on this!

The project in detail

Now that we’ve successfully run our first UWP .NET 9 app, we should take a moment to look into some technical details to better understand how UWP .NET 9 projects are structured. You might notice a few properties that are set automatically in the .csproj file by the project template. This is what they’re doing:

  • UseUwp: this property is used by the .NET 9 SDK, and it makes it reference the new WinRT projections for Windows.UI.Xaml.* types in the Windows SDK package for .NET projects. By default, these projections are not referenced, as they are incompatible with WinUI 3. We don’t want WinUI 3 developers to see both Windows.UI.Xaml (UWP XAML) and Microsoft.UI.Xaml (WinUI 3) types, as that would be fairly confusing. Instead, we added these projections into a separate .dll in the same framework package that all .NET Windows apps use, and made it opt-in, via by the “UseUwp” property. Additionally, when this property is set, the .NET SDK enables a special feature switch for CsWinRT, which projects all built-in .NET types as compatible with UWP XAML types, as opposed to WinUI 3 types. For instance, the INotifyPropertyChanged interface will be projected as Windows.UI.Xaml.Data.INotifyPropertyChanged, as opposed to Microsoft.UI.Xaml.Data.INotifyPropertyChanged. If you’re curious to check out these changes, see the .NET PR (dotnet/sdk/#41936) and the CsWinRT PR (microsoft/CsWinRT/#1421) on GitHub.
  • UseUwpTools: this property tells several MSBuild components that we’re building a UWP app with support for .NET 9, and that all necessary tooling for it should be enabled. For instance, it makes Visual Studio automatically import all XAML files in the project, import the XAML compiler, declare some necessary project capabilities, and more. It also makes MSBuild enable the APPX tooling when a class library is being built. This allows creating UWP .NET 9 class libraries that also include XAML items, as well as .resw files (for localized resources).
  • EnableMsixTooling: this property enables the single-project MSIX support, meaning you can create a UWP applications from a single .csproj file, as you’d expect. As we mentioned, in this first preview we’re relying on Windows App SDK to provide this support, but we’ll update this in the future to switch to a standalone NuGet package providing single-project MSIX support for both UWP .NET 9 apps, as well as for Windows App SDK apps. When we do that, the issue of the WebView2 NuGet package being automatically referenced will also be fixed.

These three properties are making all the magic happen so that we can now build UWP XAML apps on latest .NET! ✨

Notice we’re also setting PublishAot (see docs) and DisableRuntimeMarshalling (see docs) in the .csproj (and in all UWP .NET 9 project templates). This is because Native AOT is the only supported way for publishing UWP apps targeting .NET 9 in the Microsoft Store. This is meant to be a direct upgrade path for all UWP apps using .NET Native today, and it also ensures that the usual fast startup of UWP apps will be preserved. Additionally, the Microsoft Store does not allow publishing UWP apps using managed code, so of course, Native AOT provides us with a modern solution for that native code requirement.

It is worth calling out when migrating from .NET Native to Native AOT, you should expect a fair amount of friction and complexity in making sure that all of your code (including all of your dependencies) will work correctly with Native AOT. At first, depending on your app, you might see things stop working as expected until updated for AOT.

On the bright side, working to enable Native AOT in your app will make it much more resilient, and additionally, this work can be 100% reused if you then decided to also move from UWP to Windows App SDK in the future. As they both leverage .NET, they are identical to respect to the constraints and code changes needed for Native AOT support!

With traditional UWP apps using .NET Native, you could find differences in behavior between Debug and Release and encounter all sorts of runtime crashes that would be difficult to debug or prevent. Even with a .NET Native app that was working, it was impossible to know for sure that there weren’t some hidden bugs here and there due to incorrect trimming. .NET Native provided a double-edged sword, as it relied on lots of heuristics to try to make all .NET code “just work”, meaning it included pretty extensive fallback logic to try to make even the most aggressive reflection paths work, and it would try to automatically root .NET code for trimming if it thought it could be reflected on (e.g. it had special handling of well-known libraries such as Newtonsoft.JSON). But there was no way to statically prove that that would be the case, leading to these types of crashes you may have encountered while developing your own apps as well.

Native AOT, on the other hand, takes a drastically different approach and relies on static validation through code annotations and a set of analyzers. You can learn more about this in this blog post on AOT compatibility. Practically speaking, this means that Native AOT has “much less tolerance” than .NET Native and requires all code to be properly annotated for AOT support ahead of time, but in return for this work it provides a guarantee that if an app can be built and published with Native AOT without producing any trim/AOT warnings, then it will run exactly the same as in a normal Debug build. This also means that any problems will show up much earlier in the development phase, and you’ll be able to easily debug them during your normal dev inner loop, without needing a Release build to test.

Information

NativeAOT also has slightly different performance and binary size characteristics compared to .NET Native. We expect performance for NativeAOT on .NET 9 to be roughly equivalent to .NET Native (our benchmarks showed startup performance between ~5% when compared to .NET Native, whereas backend code not relying on WinRT interop should actually be consistently faster). As for binary size, you might notice a ~4MB regression, especially with smaller apps. This is due to .NET Native using a framework package for its runtime and class libraries (meaning all that code was installed as a separate component and shared with other UWP apps using the same version of .NET Native). NativeAOT, on the other hand, compiles all code into its output executable. This results in an increase in binary size (which should be amortized as the size of the application grows, however), but in return it also gives NativeAOT better performance, as it allows the compiler to perform inter-procedural optimizations with code from the .NET BCL, such as eg. inlining and optimizing code from the core libraries depending on the specific use in your application. Improving both performance and binary size metrics for NativeAOT and CsWinRT (the component handling all WinRT interop on modern .NET) is something that is under active development, so expect regular improvements in this area in future releases!

One more bit of information with respect to the Microsoft Store certification, if you’re interested in trying to publish an update (or a new app!) using the UWP support for .NET 9: we recommend ignoring Windows App Certification Kit failures when running the tool locally, especially regarding “unsupported Win32 APIs”. These checks are in place because UWP apps were historically subjected to a particularly strict validation of all imported Windows APIs, which would trigger automatic failure during certification if unsuccessful. This is no longer the case, and Partner Center doesn’t execute this Win32 API set validation on UWP apps anymore, relying instead on the security model provided by AppContainer itself. That is, rather than trying to detect all “unsafe” Win32 APIs and fail certification, all APIs are allowed, and AppContainer will simply make them fail at runtime if they tried to perform any operation that wasn’t allowed. This is especially relevant for Native AOT, as it includes several Win32 imports for APIs that are not in the allowlist for UWP apps, but that are completely fine to use from UWP (and in fact, work just fine). Because of this, you can still rely on WACK to perform basic validation before uploading a package to the Microsoft Store (it’s especially useful to double check that no mandatory asset is missing from the manifest, for instance), but you should not worry about false-positive errors it reports about disallowed Win32 APIs.

But wait, there’s more!

Enabling the latest .NET for UWP applications not only provides an upgrade path to existing UWP developers, but it also improves existing scenarios that were previously limited by the legacy .NET infrastructure and limitations that managed UWP apps have had from the start. Let’s take a quick look at some other benefits that the UWP support for .NET 9 brings to the table.

For those of you working on complex apps combining multiple UI-frameworks, where some controls are leveraging UWP XAML Islands (i.e. hosting UWP XAML controls inside a Win32 app), the UWP support for .NET 9 brings improved support for this scenario, thanks to the switch to the latest .NET and Native AOT! It is now possible to have a single project, using .NET 9, representing a packaged full trust (or partial trust) Win32 app, as well as the hosted UWP component to be placed in the visual tree! You can even combine everything into a single, native binary, without having to worry about the UWP components requiring a separate build toolchain that’s difficult to integrate with the rest of your application.

Here is an example showcasing how the native UWP MapControl can be hosted inside a full trust packaged Win32 app (e.g. it could be a Windows Forms app, a WPF app, a WinUI 3 app, etc.), and used just like any other controls. You can do the same with any other UWP XAML controls as well!

A UWP XAML islands example with .NET 9 and MapControl, which is made possible via the new preview UWP support for .NET 9

You can find a full sample using C++/WinRT in the WindowsAppSDK-Samples repo, which shows all the code that’s needed in detail. A C# implementation would be very close to this, with just minor differences due to different ways of doing interop with native APIs between C++ and C#. We’ll also soon be updating the samples to include a Windows App SDK app hosting XAML Islands via a UWP .NET 9 app too, so you can just use that as a reference if you’d like to experiment with this in your own app.

Tip

As mentioned in the docs, the UWP MapControl relies on Bing Maps for Enterprise, which is deprecated and will be retired. Thankfully though, the data sources for the control are fully customizable. For this demo, we used the OpenStreetMap data sources instead, which you can also leverage if you plan on using this control.

There’s even more!

Adding support for the latest version of .NET and switching from .NET Native to Native AOT also brings massive improvements to one particular scenario: using F# on UWP! While you can’t use F# for your app layer with XAML, just like WinUI 3, you can now reference dependencies or other projects that are built with F#!

.NET Native, to this day, has some hard blocks that detect F# assemblies and immediately fail compilation, and even trying to manually patch some Visual Studio files to bypass those blocks, a lot of scenarios would still simply fail to compile or work at all, because the .NET Native toolchain simply was never designed to handle many of the common patterns of F# code. There is a long standing and very popular issue in the F# repo asking for F# support for .NET Native, which has since been closed without being completed. With the UWP support for .NET 9, all of this no longer applies, as you’ll be using the same Native AOT runtime that already fully supports using F# with any other project type as well!

If you are a F# enthusiast and would like to try this out, don’t forget to share your findings and tell us about your experience! 🧪

There’s even more!

The UWP support for .NET 9 also enables one more thing that might be useful for library authors in some advanced scenarios. Like we mentioned, the new “UseUwp” property tells the .NET SDK to add a reference to the Windows.UI.Xaml.* projections for .NET, which is necessary for UWP XAML apps. However, while using these types is only allowed in UWP XAML apps, referencing these projections is something that any .NET project can do. What this means is that it is now possible to have a single .NET library (or WinRT projection assembly) including some UWP XAML types in the public API surface, and consume it from both UWP apps (or libraries) and Win32 ones.

Imagine you have a WinRT component that is consumed from multiple places, some of which might be UWP, some Win32. Let’s say you decide to add one specific API that takes or returns a UWP XAML type as well, to support a specific scenario. Previously, that would’ve been impossible: UWP XAML types simply did not exist on latest .NET, so there was no way to reference them at all. However, it is now instead possible to add a reference to them (by setting the “UseUwp” property), and still be consumed by both UWP and Win32 (which of course will not be able to actually use those specific APIs with UWP XAML types), without the need to either ship two different assemblies that only differ by a handful of APIs, or resort to other workarounds to “hide” the types from the API surface of the library (e.g. such as only taking an object or IInspectable* parameter instead of the actual type).

This is only meant for very advanced scenarios (and comes with some additional caveats, especially in case the library also references or is consumed by Windows App SDK, since CsWinRT can only project either UWP XAML or WinUI 3 types in a given process), but it is yet another benefit that comes as a side bonus from this preview support. For instance, we can take advantage of this feature in some internal libraries used by several inbox apps and Windows modules, that ship as WinRT components (meaning they could leverage this for their .NET projections), because some APIs reference UWP XAML types that could not previously be projected correctly when the latest .NET version was being used.

What’s next?

As we mentioned before, this first preview does not include a XAML designer in Visual Studio. However, we are already working on this, and thanks to Ahmed Walid, a Microsoft MVP and Windows developer, who has been helping us put together this first preview (a huge shout-out to him, thank you!), we already have a working prototype complete with the “Properties” windows as well! You can see it in action here:

The XAML designer for UWP apps targeting .NET 9

We’ll be working on integrating this prototype into an upcoming release of Visual Studio, so stay tuned! Here’s also some of the other things we’re looking into right now, and that you can expect to see available in the near future:

  • We are working with the MSTest team to add UWP support for .NET 9. We plan on reusing most of the new infrastructure that packaged WinUI 3 apps also use, meaning UWP .NET 9 apps will benefit from all the latest MSTest tooling as well, and the migration from UWP targeting .NET 9 to WinUI 3 should be especially smooth, for developers that want to fully transition to Windows App SDK.
  • WinUI 2 support is coming soon! We already have internal builds that we are testing, and we will publish a public preview of them in the near future. Of course, these will include AOT-compatible WinRT projections for .NET, just like Windows App SDK 1.6!
  • Win2D already supports UWP with .NET 9, and you can try it out today by using the latest preview version of its UWP package (1.28.0-preview1). We will be releasing a stable version with UWP support for .NET 9 shortly.
  • XamlBehaviors support is in progress. In fact, you can also check out the PR on GitHub!
  • Windows Community Toolkit support is also coming soon!

Summary

We’re so excited to help UWP developers modernize their apps and leverage the latest .NET and C# advancements, as they move toward WinUI 3 and Native AOT.

Note

Like we mentioned in the introduction, the UWP support for .NET 9 is available in preview, so expect some rough edges as we work on improving the developer experience! We hope that in the long run, this will become the preferred way for UWP apps to use .NET and C#, and that as many developers as possible will be able to upgrade their existing UWP apps from .NET Native to the latest .NET and Native AOT.

If you hit any issues, there’s multiple channels you can use to report them:

  • For CsWinRT specific issues (e.g. WinRT interop failing), use the CsWinRT repo.
  • For Microsoft Store or Partner Center related issues (e.g. certification failures), use our Discord channel.
  • For general questions, you can also find us in the UWP Community Discord server (soon to be Windows App Community). Feel free to ask for help and guidance in the appropriate channel (e.g. #dev-csharp). There’s lots of other developers from the community that can help, and plenty of Microsoft folks also hang out in the server!
  • For other general issues not related to the UWP support for .NET 9 itself, use the existing support channels. For instance, use Feedback Hub to report issues with existing UWP APIs, or the WinUI 2 repo for WinUI 2 issues, etc.

Lastly, we want to thank everyone who contributed to this preview and helped make this project happen. This was a collaborative effort between several teams across all of Microsoft, including the .NET and .NET SDK teams, the MSBuild team, the .NET Native and .NET diagnostics team, the Visual Studio team (including the owners of project templates, XAML diagnostics, and the UWP workload), the Windows App SDK and WinUI team, the Win2D team, the Windows Community Toolkit team, the XamlBehaviors team, the Edge team, and the Store team. We also want to thank two Microsoft MVPs for their contributions: Ahmed Walid, for his help prototyping a big part of the changes necessary across Visual Studio and the XAML compiler, as well as testing out early preview bits and providing extremely useful feedback for us, and Dongle, for prototyping a fork of CsWinRT with Windows.UI.Xaml support, and associated WinRT projections, which we used as reference for implementing the final changes we shipped as part of CsWinRT and the official Windows SDK projections. Thank you! 🏆

Happy coding! 🖥️

Glossary

There is very often confusion around all the various Windows technologies around UWP, in part because there are so many relevant concepts that are tightly interconnected, and the lines are often blurry between then. Let’s take this opportunity to try to provide some clarity. Here is a small summary of the main components that UWP and Windows App SDK apps interact with. Some of these components are orthogonal to each other, but still closely related:

  • MSIX: this is a packaging model used by Windows apps. It can be used by lots of different app types, including UWP, Win32, PWAs, etc., and it is usually adopted by apps published in the Microsoft Store (however, the Microsoft Store also supports unpackaged Win32 apps, and MSIX apps do not require being necessarily distributed through the Microsoft Store). The main benefits of MSIX packaging are install reliability, easy updates, clean uninstall, and more. Unlike with Win32 apps, using MSIX is a requirement for UWP apps.
  • Windows Packaging Project: this is an MSBuild project type for packaged Windows applications that was introduced years ago as part of Desktop Bridge. It can be used in advanced scenarios where the single-project MSIX architecture (i.e. tooling that can generate an MSIX package from a single project, e.g. a .csproj project) isn’t sufficient. For instance, that is the case for UWP applications that also bundle separate Win32 processes they rely on to execute some functionality. A small bit of trivia: the Microsoft Store uses this project type, as we bundle a small Win32 process we use to perform some actions outside of the UWP sandbox, you can read more about this in our blog post on the AppServices library.
  • AppContainer: this is a restrictive, capability-based process environment. It is a lightweight container that Windows can use to run apps to further control their behavior and improve security. Applications running inside an AppContainer must declare what resources they want to access (e.g. using the camera, or accessing files on disk, or using the network, etc.), and users can grant these permissions and also revoke them. Running inside AppContainer is possible for both UWP and Win32 apps. Almost all UWP apps will run in AppContainer, as that is the default configuration for them (and running a UWP app in full trust and outside AppContainer requires a custom capability that has to be explicitly granted by Microsoft to each app that wants to use it, so this is happens rarely). When you see people referring to the “UWP sandbox”, they’re most definitely referring to AppContainer, which as we said is not exclusive to UWP, and in fact is recommended for Win32 apps too, if possible. You would get the same restrictions for any Win32 app running in AppContainer as well, with minor differences.
  • UWP: this is an application model. UWP applications are tied to a CoreApplication instance, and may or may not use XAML for their UI. UWP is considered a legacy application model for modern Windows apps, and developers are encouraged to migrate to WinUI 3 for long-term support. UWP applications can run on any Windows device family that supports the UWP contract. Nowadays, this means that UWP apps will be able to run on Windows Desktop, Xbox, IoT, and HoloLens. UWP applications have access to some exclusive APIs, such as CoreWindow, and support features such as prelaunch, suspension, running under modern standby (for out-of-process background tasks), and more.
  • UWP XAML: this is a UI framework, managed by the Desktop Window Manager. It can only be used directly by UWP apps, or by Win32 apps via XAML Islands. One of the main differences between UWP XAML and other UI frameworks is that UWP XAML is composited and rendered by the same Windows component that also composites and renders the rest of Windows. This comes with both advantages and disadvantages. The main drawback of this approach is that because the whole framework is part of Windows, servicing has to be tied to new Windows versions, and it’s not possible to make new APIs (or, new controls, new styles, etc.) available on older versions of Windows (though see WinUI 2 below). Similarly, servicing bug fixes downlevel is also more complicated, as a Windows update is needed. The advantages are that because the Windows compositor has access to the entire visual tree of the application, it can leverage this to make some exclusive things possible, such as global composition. This makes it possible to create more complex visual effects in some scenarios, such as having a XAML element with an in-app acrylic brush that’s applied over a swapchain in the background. This type of advanced layering only works on UWP XAML.
  • WinUI 2: this is a UI library for UWP XAML apps, which includes several XAML controls, styles, and some new APIs. Because it’s built on top of UWP XAML, it can only be used by UWP XAML apps. Just like with WinUI 3 (see below), one of the main benefits of WinUI 2 is that it allows making new controls available, as well as providing new styles and bug fixes, to downlevel versions of Windows as well. It also allows developers to rely on a consistent visual style for their controls regardless of what version of Windows their app is running on.
  • WinUI 3: this is a complete XAML-based UI framework, that is included in Windows App SDK (see below). Unlike UWP XAML, this framework is self-contained and manages its own rendering and compositing, meaning all of it can be updated separately from Windows. It is supported for Win32 apps only. Note that as we mentioned, while Windows App SDK includes WinUI 3, using this UI framework is not mandatory when referencing Windows App SDK, and it is completely valid to use Windows App SDK from any application type that can reference it, just for the other functionality it provides.
  • Windows App SDK: this is an SDK for building Windows apps. It is made up of several components, which include lots of general purpose APIs to provide functionality to existing apps, as well as WinUI 3. Contrary to components in UWP and UWP XAML, Windows App SDK ships as a NuGet package and can be consumed like any other library, meaning that it can be versioned and updated independently of Windows. This also makes it very easy to backport new features and bug fixes to downlevel versions of Windows, as almost all functionality is just in the Windows App SDK runtime library, which can be referenced either as a framework package, or bundled in the application package (in self-contained mode).
  • Win32: this is a set of APIs for Windows applications, originally for C/C++ programs. Informally, the name “Win32” is also used to refer to “non UWP” applications, i.e. non-CoreApplication apps. For instance, Windows Forms, WPF, and WinUI 3 apps would be examples of “Win32 apps”, and this is what people often refer to when they use “Win32” as a term opposite to “UWP”. However, note that Win32 APIs can also be used by UWP apps, and the two are not mutually exclusive. Of course, there are some restrictions that apply when using Win32 apps from UWP. Some are due to different device families, e.g. you can’t use APIs such as CreateWindow to create and show a window when running on Xbox (although it will work when running on Windows Desktop, even on UWP). Some are due to AppContainer, e.g. by default you can’t just use CreateFile to open a file from an arbitrary location on the system you don’t have access to. However, note that this restriction is mostly due to AppContainer, not UWP itself, meaning a packaged partial trust Win32 app (e.g. a WinUI 3 app running under AppContainer) would also have the same issue here.
  • WinRT: this is a set of modern, object-oriented APIs for building Windows applications. They are designed to be language-agnostic (e.g. they can be consumed by any language that supports WinRT projections, such as C++, C#, JavaScript, Rust), and provide access to a wide range of functionalities and Windows capabilities, including touch input, sensors, and interacting with the Microsoft Store. The UWP platform is built on top of WinRT APIs (in fact, the name “UWP API” is often used informally to mean “WinRT API”). Note that WinRT APIs are not exclusive to UWP apps, and generally they can be used by any application type. All UWP types mentioned before, such as CoreApplication, as well as all UWP XAML types, are actually WinRT APIs. Windows App SDK itself is also a WinRT component, and almost all APIs it exposes are using the WinRT contract.

TLDR: in general, a “UWP app” is a CoreApplication app, packaged with MSIX, running under AppContainer, using a combination of WinRT and Win32 APIs. If it is a XAML app, it uses the UWP XAML UI framework, and it can optionally use the WinUI 2 library as well.

We hope that this small summary will prove useful in making the relationships between all of these components a bit easier to understand. With this, you can also now see where the UWP support for .NET 9 comes in: it targets UWP apps (possibly using UWP XAML and WinUI 2 as well), and it allows you to simply swap the .NET runtime they use from .NET Native to Native AOT, which also includes upgrading to the latest version of .NET and C#.

Note

We’re working on improving the official documentation to also provide a single place to easily access all the information from this glossary, and more. We will update this section with a link to that new documentation when it becomes available on Microsoft Learn.

Author

Sergio Pedri
Senior Software Engineer

I'm a Senior Software Engineer at Microsoft, working on the new Microsoft Store app for Windows 11 and Windows 10, and the maintainer of the .NET Community Toolkit, a suite of open source libraries to help all .NET developers. I started writing Windows and .NET apps in 2013 with Silverlight and later WinRT, and then moved to UWP. I'm passionate about open source software and a member of the .NET Foundation since 2020, and I regularly contribute to several projects on GitHub (such as ...

More about author

15 comments

  • Mike M

    Will Native AOT of .NET 9 for UWP be able work with (other) existing dependencies such as “Microsoft.Azure.Mobile.Client” and “Microsoft.ApplicationInsights.WindowsApps”; which target uap10.0. As they use Newtonsoft.Json internally for JSON.

  • Luca Piccirillo

    This is not only a great news, but actually the best overview, summary, guideline, explanation, motivation and history of last twelve years of Windows app development scene. Amazing!

    I feel very sad in seeing the awesome platform-specific innovations behind UWP to be often in contrast with serviceability of the whole development ecosystem.

    This is a gold mine --> "UWP applications have access to some exclusive APIs, such as CoreWindow, and support features such as prelaunch, suspension,...

    Read more
  • Carlo Mendoza · Edited

    First, thank you very much!

    Note to others: you will need to enable “use previews of .NET SDK” in Visual Studio.

    [moved the rest to github]

  • Carl Scarlett

    This is amazing news for us UWP app developers who can’t migrate to WinUI yet, and lights up some opportunities that just may make it possible. It’s been an extremely long and nervous wait to see if we’ve been abandoned, and a huge relief to see we haven’t been. Thank you so much to everyone who has worked on this. Such fantastic news!

  • James Rolfe

    Is it possible to migrate VB UWP projects to .NET 9? I work for a Japanese company. We have some internal tools written in VB, and they are UWP apps. The target framework of these projects are too low. The dependencies are nearly limited to .NET Standard 2.0. So, it's difficult to share the code with our Windows Forms projects. But we can't migrate these projects to other UI frameworks in limited time. Because they...

    Read more
    • Sergio PedriMicrosoft employee Author

      The new version of the XAML compiler only supports C# projects for .NET 9, so you cannot directly migrate a UWP app with VB.NET to .NET 9 leaving all code-behind in VB.NET. However, it's possible to use VB.NET for any libraries and other projects you use in your app (same with F#). In short: your main app project, and projects with XAML content, should be using C#. Anything else (eg. any code that is just...

      Read more
      • James Rolfe

        Thanks for your reply. So, for VB projects, UWP for .NET 9 has similar limitations as WinUI 3. Do you have plans to open source the XAML compiler? We can try to convert C# source generators to VB source generators with GitHub Copilot. Then, use the modified XAML compiler in our projects to remove the limitations. We won't switch to C# for consuming .NET 9 libraries, because these UWP projects were ported from Windows Forms...

        Read more
  • Johan Mulder

    Thanks MS and team. Can’t believe this !! Sergio I must give you credit here. From Mvvm to UWP with AOT and .NET 9. Whatever you touch turns into gold and these things are difficult and epic. Well done!!

  • MH Rastegari

    So happy to see UWP still getting support! 🙂

  • PandaSharp

    Omg omg omg I had to re-read the title 10 times… This is the best news for the last ~5 years as a #windows dev and user #uwp #notdead

  • 蒂夫 史

    I love UWP.
    I am happy to see these changes!

  • Huo Yaoyuan

    I have just migrated my last UWP application to WinUI 3 several months ago. It was already simple because most UI features I depended was implemented.
    Finally seeing there’s work in the UWP space to make it not orphaned.