New in .NET 10.0 [17]: NuGet packages and settings for File-based Apps
Information that is usually in the .csproj project file for normal .NET projects is set in File-based Apps using a preprocessor directive.
(Image: Pincasso/Shutterstock)
- Dr. Holger Schwichtenberg
Directly translating and starting C# files Microsoft calls File-based Apps. For information usually found in the .csproj project file, Microsoft has introduced its own syntax for File-based Apps.
The syntax begins with the hash symbol # (a preprocessor directive in C#) followed by a colon (a directive to be ignored from the C# compiler's perspective):
- Setting the SDK:
#:sdk Microsoft.NET.Sdk.Web. When specifying the SDK, from Preview 6 onwards, you can also specify the version number after @, for example#:sdk Aspire.AppHost.Sdk@9.3.1 - Reference to a NuGet package:
#:package Console@0.48.* - Reference to projects:
#:project ./ClassLib/ClassLib.csproj - Build properties, e.g., version number:
#:property Version=1.1.2(before Preview 6, without an equals sign, but with a space as a separator) - By default, File-based Apps use the NativeAOT compiler. If you disable it with
#:property PublishAot=false, the Just-In-Time compiler is used.
Videos by heise
Further features of File-based Apps include:
- You can create a .settings.json file in the same folder with the settings for the File-based App.
- You can create a launch profile for the File-based App in the .run.json file in the same folder.
- You can execute
dotnet build Filename.csordotnet restore Filename.cs. - You can compile such File-based Apps into an executable file (.EXE) with
dotnet publish cs. - Since Preview 6, within a File-based App, developers can determine the location of the file with
AppContext.GetData("EntryPointFileDirectoryPath")and the full path to the executed C# file withGetData("EntryPointFilePath"). However, this only works with File-based Apps, not in normal, project-based C# applications.
However, in .NET 10.0, there is no way yet to directly include another .cs file in a File-based App. This is planned for .NET 11.0.
The following code shows an example of a File-based App with two referenced NuGet packages:
#!/usr/bin/env dotnet
#region Einstellungen fĂĽr File-based App
// https://www.nuget.org/packages/humanizer/
#:package Humanizer@2.14.1
// https://www.nuget.org/packages/Spectre.Console/
#:package Spectre.Console@0.*
#:property LangVersion=preview
#:property Version=1.2.0
#:project ./ClassLibrary/ClassLibrary.csproj
#endregion
using Spectre.Console;
using Humanizer;
var title = "C# Script v" + System.Reflection.Assembly.GetExecutingAssembly().GetName().Version +
" mit " + System.Runtime.InteropServices.RuntimeInformation.FrameworkDescription + "\n" +
AppContext.GetData("EntryPointFilePath");
// Header
AnsiConsole.Write(
new Panel(title)
.Header("[yellow]File-based App[/]", Justify.Center)
.Border(BoxBorder.Rounded)
.BorderStyle(new Style(foreground: Color.Green))
.Padding(1, 1, 1, 1)
);
// Parameter auflisten
foreach (var arg in args)
{
Console.WriteLine($"Argument: {arg}");
}
Console.WriteLine();
// Daten
(Data net80, Data net90, Data net10) = GetData();
// Textausgabe in Wochen
var dotNet8Released = DateTimeOffset.Parse(net80.Release);
TimeSpan dotNet8Since = DateTimeOffset.Now - dotNet8Released;
Console.WriteLine($"It has been {dotNet8Since.Humanize()} since .NET {net80.Version} was released.");
var dotNet9Released = DateTimeOffset.Parse(net90.Release);
TimeSpan dotNet9Since = DateTimeOffset.Now - dotNet9Released;
Console.WriteLine($"It has been {dotNet9Since.Humanize()} since .NET {net90.Version} was released.");
var dotNet10Released = DateTimeOffset.Parse(net10.Release);
TimeSpan dotNet10Since = DateTimeOffset.Now - dotNet10Released;
Console.WriteLine($"{dotNet10Since.Humanize()} since .NET {net10.Version} release.");
Console.WriteLine();
// Zeichne Balken für die Anzahl der Tage seit der Veröffentlichung
var bar = new BarChart()
.Width(100)
.AddItem("Days since .NET 8.0 release", dotNet8Since.TotalDays, Color.Red)
.AddItem("Days since .NET 9.0 release", dotNet9Since.TotalDays, Color.Blue)
.AddItem("Days since .NET 10.0 release", dotNet10Since.TotalDays, Color.Purple);
AnsiConsole.Write(bar);
Console.WriteLine();
// Lokale Funktion
static (Data, Data, Data) GetData()
{
var net80 = new Data
{
Version = "8.0",
Release = "2023-11-14"
};
var net90 = new Data
{
Version = "9.0",
Release = "2024-11-12"
};
var net10 = new Data
{
Version = "10.0",
Release = "2025-11-11"
};
return (net80, net90, net10);
}
// Datenklasse
class Data
{
public required string Version { get; set; }
public string Release { get; set; }
}
(dahe)