.NET Framework allows us to create applications for various platforms and devices. With each new version, .NET introduces new features and fixes, while rarely including changes that could cause compatibility issues. Therefore, upgrading a .NET project to a newer version usually results in it functioning without problems.
However, it can be useful to be able to programmatically determine .NET version information for logging, debugging, and other purposes.
Let’s dive in.
.NET Versioning Structure
.NET has multiple version names associated with it, such as the Software Development Kit (SDK), and the Common Language Runtime (CLR).
We are going to learn how to find out some of these .NET version names using C# code. The methods we’re going to use work on any platform that supports .NET, such as Windows, Linux, macOS, Android, and iOS. These methods return strings with relevant information that we will parse to get specific details.
With that said, let’s explore the various ways of getting various version information using a number of methods.
How to Determine the .NET Version of Another Assembly
To programmatically get the .NET version of an external assembly, we first have to load it. Then, we find the assembly named System.Runtime
from its referenced assemblies. Finally, we call its Version
property to get our result:
public static string GetAssemblyDotNetVersion(string assemblyFile) { var assembly = Assembly.LoadFrom(assemblyFile); var references = assembly.GetReferencedAssemblies(); var version = references.FirstOrDefault(x => x.Name == "System.Runtime"); return version?.Version?.ToString() ?? ""; }
When calling the method we need to provide the path to the assembly file:
// var path = "path/to/the .NET assembly in question"; var path = "HowToDetermineDotNetVersionProgramaticallyDemo.dll"; Console.WriteLine(GetAssemblyDotNetVersion(path)); // output: 7.0
After executing the code and examining the output, we will find that the version number for the project included with this article is 7.0
. However, this approach can be applied to any project to retrieve its version number.
How to Get the Target Framework
In .NET, the Target Framework is a specific version of the .NET Framework that an application is built against. It specifies the set of APIs that are available to our app or library. We use a Target Framework Moniker (TFM) to specify the target framework. The long form of TFM for .NET 5.0 is ".NETCoreApp,Version=v5.0"
and for .NET Framework 4.0 is ".NETFramework,Version=v4.0"
. The short form of TFM for .NET 5.0 is "net50"
and for .NET Framework 4.0 is "net40"
:
public static string GetTargetFrameworkName() { return Assembly .GetEntryAssembly()? .GetCustomAttribute<TargetFrameworkAttribute>()? .FrameworkName; }
When we call the method and write the return value to the console, the version of the target framework will be displayed:
Console.WriteLine(GetTargetFrameworkName()); // output: .NET Core 5.0
If we run the same code in a different project, the observed result might be different.
How to Get the CLR Version
The CLR is the virtual machine component that manages the execution of .NET applications within the framework. In previous versions of the .NET Framework (4 through 4.6), the CLR version was 4.0.30319.4xxxxx, where xxxxx was a number less than 20002.
With the introduction of .NET Core and its evolution into the unified .NET platform from .NET 5+ onwards, a single product version is used, which matches both the CLR and the framework description.
However, we can still use the Version
property of the System.Environment
class to get the CLR version programmatically. This method returns a Version
object that contains the major, minor, build, and revision numbers of the CLR, regardless of the version merging:
public static string GetEnvironmentVersion() { return Environment.Version.ToString(); }
Executing this method will give us the .NET runtime version:
Console.WriteLine(GetEnvironmentVersion()); // output: 7.0
If we use the same approach in another project, our observed output might be different.
How to Get the .NET Framework Description
The ‘.NET Framework Description’ is a string that identifies the specific version of the .NET technology stack on which an application is running. This information is useful for determining whether the project is using ‘.NET Core v3.0,’ ‘.NET Framework v4.5,’ or another version. To determine .NET Description version programmatically using C#, we can use the FrameworkDescription
property from the System.Runtime.InteropServices.RuntimeInformation
class.
By parsing the result of this property, we can extract the necessary information about the .NET runtime and SDK that the application is using:
public static string GetFrameworkDescription() { return System .Runtime .InteropServices .RuntimeInformation .FrameworkDescription; }
Calling this method will give us the information about the .NET arrangement under which the application is running:
Console.WriteLine(GetFrameworkDescription()); // output: .NET 7.0 var parts = GetFrameworkDescription().Split(" "); var name = parts[0]; Console.WriteLine(name); // output: .NET var version = parts[1]; Console.WriteLine(version); // output: 7.0
Using the same technique in other projects would allow us to get their respective versions.
How to Get the .NET Core Version
To determine the version of .NET Core that our assembly is using, we can parse the install path of the System.Runtime.GCSettings
class found in the System.Runtime
namespace. The install path includes a folder named "Microsoft.NETCore.App"
, which contains a subfolder with the .NET Core version as its name. For instance, if the assembly is using .NET Core 3.1, the folder name would be "3.1.0"
:
public static string GetNetCoreVersion() { var assembly = typeof(System.Runtime.GCSettings).GetTypeInfo().Assembly; var assemblyPath = assembly.Location.Split(new[] { '/', '\\' }, StringSplitOptions.RemoveEmptyEntries); int netCoreAppIndex = Array.IndexOf(assemblyPath, "Microsoft.NETCore.App"); if (netCoreAppIndex > 0 && netCoreAppIndex < assemblyPath.Length - 2) return assemblyPath[netCoreAppIndex + 1]; return ""; }
Using this approach allows us to see the particular .NET Core version executing the application:
Console.WriteLine(GetNetCoreVersion()); // output: 3.1.0
Of course, the version number that we get will depend on the .NET Core iteration the library is built against.
How to Get the .NET SDK Versions on Our System
The Process
class in C# allows us to execute the dotnet
command-line tool with the "–list-sdks"
option. This displays all the .NET SDK versions and their respective installation paths on our system. We can then extract the necessary information by parsing the resulting string:
public static string GetDotNetSdkVersionsInstalled() { var process = new Process(); process.StartInfo.FileName = "dotnet"; process.StartInfo.Arguments = "--list-sdks"; process.StartInfo.RedirectStandardOutput = true; process.Start(); var output = process.StandardOutput.ReadToEnd(); process.WaitForExit(); return output; }
Calling the function from within our code will fetch a string containing the installed SDKs. We could then manipulate the strings to extract individual properties:
Console.WriteLine(GetDotNetSdkVersionsInstalled()); // output: // ... // 7.0.100 [/usr/local/share/dotnet/sdk] // ... public static ICollection<(string version, string installPath)> GetInstalledSdkVersionsCollection() { return GetDotNetSdkVersionsInstalled() .Split(Environment.NewLine) .Select(x => x.Split(' ')) .Where(x => x.Length == 2) .Select(x => (version: x[0], installPath: x[1])) .ToArray(); } foreach (var (version, installPath) in GetInstalledSdkVersionsCollection()) { Console.WriteLine($"SDK version: {version} Install path: {installPath}"); } // output: // ... // SDK version: 7.0.100 Install path: [/usr/local/share/dotnet/sdk] // ...
The list of installed SDKs will vary between various systems.
How to Determine .NET Runtime Versions on Our System
To obtain all the .NET runtime versions on our system, we can utilize the Process
class in C# to execute the dotnet
command-line tool, similar to the previous section. This time, we use the "–list-runtimes"
option. We can then capture and analyze the output string to extract the information we require:
public static string GetDotNetRuntimeVersionsInstalled() { var process = new Process(); process.StartInfo.FileName = "dotnet"; process.StartInfo.Arguments = "--list-runtimes"; process.StartInfo.RedirectStandardOutput = true; process.Start(); var output = process.StandardOutput.ReadToEnd(); process.WaitForExit(); return output; }
Once called, the method will return a summary of installed runtime versions as a single string that we can further split to get individual entries:
Console.WriteLine(GetDotNetRuntimeVersionsInstalled()); // output: // ... // Microsoft.NETCore.App 7.0.1 [/usr/local/share/dotnet/shared/Microsoft.NETCore.App] //... static ICollection<(string name, string version, string installPath)> GetInstalledDotNetRuntimeVersionsCollection() { return GetDotNetRuntimeVersionsInstalled() .Split(Environment.NewLine) .Select(x => x.Split(' ')) .Where(x => x.Length == 3) .Select(x => (name: x[0], version: x[1], installPath: x[2])) .ToArray(); } foreach (var (name, version, installPath) in GetInstalledDotNetRuntimeVersionsCollection()) { Console.WriteLine($"Runtime name: {name} Version: {version} Install path: {installPath}"); } // output: // ... // Runtime name: Microsoft.NETCore.App // Version: 7.0.1 // Install path: [/usr/local/share/dotnet/shared/Microsoft.NETCore.App] // ...
The list of installed runtimes will vary between various systems.
Conclusion
In conclusion, this article has provided a comprehensive guide on how to determine .NET version information in our projects using C# code. We have learned how to obtain version information about the CLR, .NET Framework description, .NET Core, and the SDKs on our system through various methods and properties within .NET. These methods are useful for debugging, testing, compatibility, and version identification. Additionally, we can display or log the .NET version information in our projects using these methods. This knowledge empowers us to work with .NET versions confidently and efficiently.