6

To be able to investigate an issue reported for one of my apps, I need to know the (runtime) environment in which my application runs on the user's side. Besides application's version and operating system's version, I also want to display the .NET CLR version and (if possible) the .NET Framework version to the user so the user can report these information back to me.

I found several solutions for detecting installed .NET Frameworks, but this is not what I need.

I don't care (at first) what other software is installed on the user's computer. And a .NET Framework installation that is actually not used for running my application is by definition other software, not related software.

To cover the CLR version requirement, I found Environment.Version.ToString() to be usefull.

However, reading the documentation make me anxious. The Remarks section of the Environment.Version documentation points out, that

For the .NET Framework 4.5 and later, we do not recommend using the Version property to detect the version of the runtime[...]

I understand CLR in something like the API, and the Framework in something like the components and actual logic that can be updated. So knowing the CLR version is a good start, but the Framework version may be also required as it can point out incompatibilities due to bugs in the actual Framework (logic). An error in my application can be a result of a bug in the Framework so there is no bug (but possible workaround potential) in my application. This can drastically speed up the debugging process.

With the remarks about Environment.Version in mind, what can I safely use to get the CLR version for application that runs on .NET Framework version 4.0 up to .NET Framework version 4.7.2?

Is there any way to detect the the .NET Framework version (components and logic) that is used to running my application? Maybe via reflecting the loaded assemblies and take the assembly version from specific assemblies, but is such an approach reliable?

burnersk
  • 3,320
  • 4
  • 33
  • 56
  • .NET 4.0+ always uses the CLR 4 because it's an in-place upgrade of the previous version. https://learn.microsoft.com/en-us/dotnet/standard/clr#clr-versions – kapsiR Mar 26 '19 at 07:53
  • @kapsiR : Point; but what about a future .NET 5.0 (e.g. having CLR 5)? Why is there a warning, not to use Environment.Version to detect CLR? – burnersk Mar 26 '19 at 07:54
  • From reference source: `Starting with 4.6 we switched to a file versioning scheme that matched the product version. In order to preserve compatibility with existing libraries, this needs to be hard-coded` https://referencesource.microsoft.com/#mscorlib/system/environment.cs,7cf342fd97cdf4c7 – kapsiR Mar 26 '19 at 08:04
  • @kapsiR : Thanks, so the outcome is to load (find in loaded assemblies) the `mscorlib.dll` and get the `AssemblyFileVersionAttribute`, correct? – burnersk Mar 26 '19 at 08:06
  • No, I would query the registry for the installed version as you already mentioned above: https://learn.microsoft.com/en-us/dotnet/framework/migration-guide/how-to-determine-which-versions-are-installed?view=netframework-4.7.2#find-newer-net-framework-versions-45-and-later – kapsiR Mar 26 '19 at 08:13
  • @kapsiR : And it is ensured, that only the most current installed .NET Framwork version is used to run the application? Or the targeted .NET Framework from the application's manifest (and if not found the most current installed)? I can't find any information about which version is actually used. – burnersk Mar 26 '19 at 08:18
  • Probably the best way is to check for a specific feature: https://stackoverflow.com/a/8543850 – kapsiR Mar 26 '19 at 08:27
  • 1
    @burnersk there won't be any .NET 5.0. The next version is .NET Core which is a completely different runtime and compilation target. – Panagiotis Kanavos Mar 26 '19 at 08:36

1 Answers1

1

Based on the comments about file versioning you could do something like this:

var strType = typeof(System.String);
var assemblyUri = strType.Assembly.CodeBase;
var versionInfo = FileVersionInfo.GetVersionInfo(new Uri(assemblyUri).LocalPath);

That gets you the FileVersionInfo for the assembly that contains your current runtime's System.String type, which seems pretty definitive to me.

MarcE
  • 3,586
  • 1
  • 23
  • 27
  • 1
    Why indirect via `GetAssembly` rather than just using the `Assembly` property of the type in hand? – Damien_The_Unbeliever Mar 26 '19 at 08:37
  • Because I haven't yet had my morning coffee and forgot about that property! I'll edit the answer... – MarcE Mar 26 '19 at 08:38
  • 1
    Do not use this, as it gives inconsistent results (e.g. can detect .Net Framework 4.7.2 whereas only 4.6 is installed). See https://stackoverflow.com/a/51472697/8861729 – Indigo Apr 17 '21 at 17:04