.NET8/9 – Testing different Build/Deployment modes – Part 5

Abstract: We practically show examples of 15 different .NET8/9 build modes, including Framework-Dependent and Framework-Independent, how to bundle an app into a single file, how to trim app bundles from unused libraries, and how to build an Ahead-of-time (AOT) precompiled app.

1. .NET8/9 toolset supports different build/publish/deployment modes

I was experimenting with different project properties/flags, and I developed several proof-of-concept build projects showcasing different build/publish/deployment modes available in .NET8/9, using Microsoft tools.

1.1. Articles in this series

For technical reasons, I will organize this text into several articles.

  • .NET8/9 – Testing different Build/Deployment modes – Part 1
  • .NET8/9 – Testing different Build/Deployment modes – Part 2
  • .NET8/9 – Testing different Build/Deployment modes – Part 3
  • .NET8/9 – Testing different Build/Deployment modes – Part 4
  • .NET8/9 – Testing different Build/Deployment modes – Part 5
  • .NET8/9 – Testing different Build/Deployment modes – Part 6

2. Some tools

Here are some tools that are useful in dealing with .NET build issues.

2.1. Tools to find versions of .NET SDK installed

There is a way to find which .NET SDKs are installed.

.NET SDKs

Window powershell

2.2. Tools to uninstall .NET SDK

You need to install this tool first. Find it on the internet.

Uninstall .NET SDK

2.3. Finding .NET SDK version for .NET Runtime

It can be confusing, but .NET SDK has different version numbers from .NET Runtime. But, all can be easily seen at the Microsoft website.

You need .NET SDK because of the “dotnet” tool to build apps.

Dotnet

Microsoft

2.4. Using Dotnet restore

I needed this command, too.

Dotnet restore

2.5. Using global.json

With this global.json file, you can control which version of the .NET SDK project will use. I need this because in point of time, my .NET 8 projects started to use dotnet build command from .NET9 SDK. This is the way to control it explicitly. The problem is that when you upgrade the .NET SDK version, you need to manually change each global.json file.

Global.json

2.6. Using dotnet workload

You might need this command.

Workload updated

3. Breaking changes in .NET build tools 8.0.0 to 8.0.11

These project settings all worked well somewhere around .NET 8.0.0. Later, with the upgrade of .NET runtime to later versions of .NET 8.0 and .NET 9.0 and an upgrade to Visual Studio, some of those projects stopped working. It looks like they introduced BREAKING CHANGES in the build tools. Logic is still sound and build types are the same, just the build tools started to behave a bit differently. New build configurations and build scripts are needed.

I think I can locate the change in behavior somewhere between (.NET Framework 8.0.0/.NET SDK 8.0.100) and (.NET Framework 8.0.11/.NET SDK 8.0.404). Not all, but some project builds failed.

3.1. Error 1

I started to get the following errors.

When running the application.

A fatal error was encountered. The library 'hostpolicy.dll' required to execute the application was not found in 'C:\Program Files\dotnet\'.

Failed to run as a self-contained app.

- The application was run as a self-contained app because 'C:\tmpNetBundle\BundleExample02_NET90\ConsoleApp2C\SelfContained_SingleFile_win-x64\ConsoleApp2C.runtimeconfig.json' was not found.

- If this should be a framework-dependent app, add the 'C:\tmpNetBundle\BundleExample02_NET90\ConsoleApp2C\SelfContained_SingleFile_win-x64\ConsoleApp2C.runtimeconfig.json' file and specify the appropriate framework.

PS C:\tmpNetBundle\BundleExample02_NET90\ConsoleApp2C\SelfContained_SingleFile_win-x64>

3.2. Error 2

I started to get the following errors.

During build

error MSB4018: The "GenerateBundle" task failed unexpectedly. 
[C:\tmpNetBundle\BundleExample01_NET_8.0.0_SDK_8.0.100\ConsoleApp2\ConsoleApp2.csproj]

error MSB4018: System.IO.FileNotFoundException: Could not find file 
'C:\tmpNetBundle\BundleExample01_NET_8.0.0_SDK_8.0.100\ConsoleApp2\obj\Release\net8.0-windows\win-x64\singlefilehost.exe'.

3.3. Resolution 1

It looks like the flag <PublishSingleFile>true</PublishSingleFile> in the project file .csproj stopped to work in some cases. After that, I relied on that flag in my build scripts.

No problem. We can anticipate that thing just when we know what to expect.

3.4. Resolution 2

It looks like the build process invoked “dotnet publish” from .NET SDK 9.* for projects that I was building for .NET 8.* framework.

So, I decided to use a global.json file to explicitly specify which SDK I want to use.

4. To be continued

This will be continued in the next article of the series.

5. References

[1] .NET application publishing overview

https://learn.microsoft.com/en-us/dotnet/core/deploying/

[2] Self-contained deployment runtime roll forward

https://learn.microsoft.com/en-us/dotnet/core/deploying/runtime-patch-selection

[3] https://www.red-gate.com/products/smartassembly/

[4] https://learn.microsoft.com/en-us/dotnet/core/deploying/single-file/overview?tabs=cli#api-incompatibility

[5] https://www.jetbrains.com/decompiler/

[7] https://devblogs.microsoft.com/dotnet/conversation-about-ready-to-run/