![](/user_photo/_userpic.png)
- •Table of Contents
- •About the Author
- •Acknowledgments
- •Introduction
- •Version Support
- •Supported Versions
- •A Unified Platform
- •Roadmap
- •Supported Operating Systems
- •Command Line Interface
- •Desktop Development
- •Blazor
- •MAUI
- •Wrapping Up
- •.NET 6 Architecture
- •Runtimes
- •CoreCLR
- •Mono
- •WinRT
- •Managed Execution Process
- •Desktop Packs
- •Wrapping Up
- •Dotnet New
- •Dotnet Restore
- •NuGet.config
- •Dotnet Build
- •Dotnet Publish
- •Dotnet Run
- •Dotnet Test
- •Using the CLI in GitHub Actions
- •Other Commands
- •Wrapping Up
- •WinAPI
- •WinForms
- •STAThread
- •WinForms Startup
- •DPI Mode
- •Responding to Scale Events
- •Visual Styles
- •Text Rendering
- •The Message Loop
- •The Form Designer
- •WPF Startup
- •XAML Layout
- •Visual Tree
- •Data Binding
- •Windows App SDK
- •Building a Windows App SDK application
- •Using Windows APIs with Windows App SDK
- •Packaging
- •Migrating to .NET 6
- •Upgrade Assistant
- •Wrapping Up
- •Blazor WebAssembly
- •Creating a Blazor Wasm Project
- •Blazor Progressive Web Apps
- •Exploring the Blazor Client Project
- •Blazor in .NET 6
- •Blazor Component System
- •Creating Blazor Pages
- •Running a Blazor App
- •Blazor Server
- •SignalR
- •Blazor Desktop
- •Wrapping Up
- •Project Structure
- •Exploring MAUI
- •The Cross-Platform World
- •Application Lifecycle
- •MVVM
- •MVVM Toolkit
- •Wrapping Up
- •Model-View-Controller
- •Routing
- •Views
- •Controllers
- •Controller-Based APIs
- •Minimal APIs
- •Wrapping Up
- •Web Apps
- •Creating an App Service
- •Static Web Apps
- •Web App for Containers
- •Docker
- •Azure Functions
- •Deploying Azure Functions
- •Wrapping Up
- •Record Types
- •Monolith Architecture
- •Microservices
- •Container Orchestration
- •Kubernetes
- •Docker Compose
- •Dapr
- •Installing Dapr
- •Dapr State Management
- •Wrapping Up
- •Roslyn
- •Compiler API
- •Diagnostic API
- •Scripting API
- •Workspace API
- •Syntax Tree
- •Roslyn SDK
- •Source Generators
- •Writing a Source Generator
- •Debugging Source Generators
- •Wrapping Up
- •Garbage Collector
- •The Heap
- •The Stack
- •Garbage Collection
- •A Look at the Threadpool
- •Async in .NET 6
- •Await/Async
- •Cancellations
- •WaitAsync
- •Conclusion
- •Index
![](/html/75672/2303/html_CACnH9VZ6O.sqXh/htmlconvd-Yz4fCu35x1.jpg)
Chapter 2 Runtimes and Desktop Packs
WinRT
The Windows Runtime, or WinRT, is the runtime used for Universal Windows Platform Applications, or UWP. UWP was originally meant to deliver a “build once, run on all Windows 10 devices.” These devices included computers, tablets, smartphones, Xbox, Hololens, and embedded devices. WinRT applications can be built using C# or C++ and XAML. WinRT is not a runtime in the strict sense of the word. It’s more like an interface on top of the Win32 API.
Managed Execution Process
The managed execution process is the process that is followed to get from code to a running application. It consists of three steps.
Figure 2-2. Managed execution process
First step is compiling to the Microsoft Intermediate Language, or MSIL. For this, we will need a compiler that can compile the language we’re writing our code in to intermediate language.
The second step is compiling the MSIL code into native code. There are two ways to do this.
The first one is using the Just-In-Time, or JIT compiler. The JIT compiler is supplied by the runtime, making JIT compilation possible on different architectures and operating system. If there is a .NET runtime on the platform, there is a JIT compiler. JIT compilation is not a one-shot process; it happens continuously as your application is being used; this is by design to keep in mind that not all code in the MSIL will end up being called. By JIT compiling on the go, the runtime limits the number of resources your application is using. Once a piece of MSIL is compiled into native code, it is stored in memory and does not need to recompile if the application is running.
24
![](/html/75672/2303/html_CACnH9VZ6O.sqXh/htmlconvd-Yz4fCu36x1.jpg)
Chapter 2 Runtimes and Desktop Packs
The second way to compile MSIL into native code is doing it ahead of time (AOT) using .NET’s ahead-of-time compiler called CoreRT. Ahead of time compilation means that the full set of MSIL instructions get translated into native code before anything
is being executed, usually during installation of software. In .NET AOT compilation is handled by a tool called the native image generator, or Ngen. Ngen compiles all MSIL in an assembly into native code; that native code gets persisted on disk so that when a user launched your application, there is no more JIT compilation, resulting in a faster application.
Figure 2-3. Ahead-of-time compilation
An important step in the compilation step of the managed execution process for both JIT and AOT is code verification. Code verifications makes sure that the code being compiled into native is safe; it protects the system from malicious behavior in software. The compiler takes the MSIL and treats it as unsafe by default. It will verify that the MSIL was correctly generated, that no memory locations can be accessed that shouldn’t be accessed, that all type references are compatible, and so on. Note that this verification can be disabled by system administrator.
The final step in the managed execution process is running the code. This is where the operating system takes the native code, either from the AOT compiler or from the JIT compiler, and executes the instructions. While the application is being executed, the runtime will trigger services like garbage collection, code verification, and so on.
Desktop Packs
.NET 6 furthers Microsoft’s cross-platform, open-source journey that they started in 2014. While it all started with cloud and Web, we now have support for Windows desktop applications written in WPF or WinForms. But since Windows is not cross-platform
and both WinForms and WPF are too integrated in Windows to make it cross-platform, there had to be a solution to make those frameworks work while still maintaining the
25
![](/html/75672/2303/html_CACnH9VZ6O.sqXh/htmlconvd-Yz4fCu37x1.jpg)
Chapter 2 Runtimes and Desktop Packs
cross-platform mindset. To get the Windows only assemblies into the framework, they would have to either make .NET tied into one operating system again, or make different flavors of .NET, or put those assemblies into packs that can be optionally added to an application. That third option is exactly what they did. Figure 2-2 shows how the .NET 6 architecture is layered to have a common base library called CoreFX but can still have specific targets.
Figure 2-4. .NET 6 layered architecture
On the image we can clearly see that .NET is still very much cross-platform, but should we want to add Windows-only code, for example, we can by referencing a specific
.NET implementation through a Target Framework Moniker, or TFM.
Listing 2-1 shows setting the Target Framework Moniker or TFM to .NET 6 with Windows support and the UseWPF tag in the csproj file that adds support for WPF in a
.NET 6 project.
Listing 2-1. Adding WPF support
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<OutputType>WinExe</OutputType> <TargetFramework>net6.0-windows</TargetFramework> <Nullable>enable</Nullable> <UseWPF>true</UseWPF>
</PropertyGroup>
</Project>
26
Chapter 2 Runtimes and Desktop Packs
For comparison, Listing 2-2 shows the project file for a .NET 6 WinForms project.
Listing 2-2. Adding WinForms support
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<OutputType>WinExe</OutputType> <TargetFramework>net6.0-windows</TargetFramework> <UseWindowsForms>true</UseWindowsForms>
</PropertyGroup>
</Project>
The default TFM for .NET 6 is net6.0. Referencing that TFM means you will get access to all the common, cross-platform APIs. However, should you have the need to have platform-specific APIs, like, for example, the notification system on Android or iOS, you can use OS-specific Target Framework Monikers. In general if you are building a class library or an ASP.NET project, net6.0 should suffice. For other types of projects,
.NET 6 includes the following TFMs:
•\ net6.0
•\ net6.0-Android
•\ net6.0-ios
•\ net6.0-macos
•\ net6.0-maccatalyst
•\ net6.0-tvos
•\ net6.0-Windows
Creating a new WPF or WinForms project will automatically set the TFM to net6.0-windows.
The WPF and WinForms project templates include a reference to Microsoft. WindowsDesktop.App.WPF or Microsoft.WindowsDesktop.App.WinForms. These are called Desktop Packs.
27
![](/html/75672/2303/html_CACnH9VZ6O.sqXh/htmlconvd-Yz4fCu39x1.jpg)
Chapter 2 Runtimes and Desktop Packs
In the solution explorer, you can find the desktop pack under Dependencies, Frameworks, as shown in Figure 2-3.
Figure 2-5. The WPF Desktop pack
28