There should be APIs to get the actual .NET Version and the commit SHA for .NET Core. The version APIs have been a weak point of the product since .NET Core 1.0. If we're going to change existing behavior a major version would be a good time!
In particular, Environment.Version and RuntimeInformation.FrameworkDescription seem nearly useless in the majority of cases. It is particularly cute that they return different values. At least they agree on 4.x!
The OS Version and Bitness APIs are included for completeness. The OS version APIs could likely be improved in some way, but I don't have a specific need for that.
This is what I can produce today:
C:\testapps\versioninfo>dotnet run
.NET Core version:
Environment.Version: 4.0.30319.42000
RuntimeInformation.FrameworkDescription: .NET Core 4.6.27322.0
RichHack.Version: 3.0.0-preview-27324-5
RichHack.CommitUrl: https://github.com/dotnet/coreclr/tree/b9e88989458e24fa9764e045917b141e3338eae7
OS Version
Environment.OSVersion: Microsoft Windows NT 6.2.9200.0
RuntimeInformation.OSDescription: Microsoft Windows 10.0.17763
Bitness
RuntimeInformation.OSArchitecture: X64
RuntimeInformation.ProcessArchitecture: X64
Environment.Is64BitOperatingSystem: True
Environment.Is64BitProcess: True
C:\testapps\versioninfo>docker run --rm -it -v C:\testapps\versioninfo:/app -w /app microsoft/dotnet:3.0-sdk-alpine dotnet run
.NET Core version:
Environment.Version: 4.0.30319.42000
RuntimeInformation.FrameworkDescription: .NET Core 4.6.27322.0
RichHack.Version: 3.0.0-preview-27324-5
RichHack.CommitUrl: https://github.com/dotnet/coreclr/tree/b9e88989458e24fa9764e045917b141e3338eae7
OS Version
Environment.OSVersion: Unix 4.9.125.0
RuntimeInformation.OSDescription: Linux 4.9.125-linuxkit dotnet/corefx#1 SMP Fri Sep 7 08:20:28 UTC 2018
Bitness
RuntimeInformation.OSArchitecture: X64
RuntimeInformation.ProcessArchitecture: X64
Environment.Is64BitOperatingSystem: True
Environment.Is64BitProcess: True
I updated the code, and made it more focused on the key scenario and switched to approved patterns (modulo the fact that my code will crash if the AssemblyInformationalVersionAttribute string is not maintained):
Existing behavior:
C:\testapps\versioninfo>dotnet run
.NET Core version:
Environment.Version: 4.0.30319.42000
RuntimeInformation.FrameworkDescription: .NET Core 4.6.27415.71
CoreFX Build: 4.7.0-preview4.19113.15
CoreFX Hash: add4cacbfb7f7d3f5f07630d10b24e38da4ad027
Code: https://gist.github.com/richlander/f5849c6967c66d699301f75101906f99
Desired behavior for a preview:
C:\testapps\versioninfo>dotnet run
.NET Core version:
Environment.Version: 3.0.0
RuntimeInformation.FrameworkDescription: .NET Core 3.0.0-preview4.19113.15
CoreFX Build: 3.0.0-preview4.19113.15
CoreFX Hash: add4cacbfb7f7d3f5f07630d10b24e38da4ad027
Desired behavior for a release build:
C:\testapps\versioninfo>dotnet run
.NET Core version:
Environment.Version: 3.0.2
RuntimeInformation.FrameworkDescription: .NET Core 3.0.2
CoreFX Build: 3.0.2
CoreFX Hash: dda4cacbfb7f7d3f5f07630d10b24e38da4ad027
Note: I have documented this with CoreFX since it has implemented the new format for AssemblyInformationalVersionAttribute. CoreCLR has not done that yet, but will. If both were in place, I'd include both in my sample.
Note: There is no way to get this information for the actual CoreCLR runtime. The build and hash values for System.Private.CoreLib.dll and CoreCLR are expected to be uniform 99% of the time.
Related dotnet/runtime#20400 dotnet/runtime#25483 dotnet/runtime#26780 dotnet/runtime#26833
The Directory.GetParent(typeof(object).Assembly.Location).Name hack is what I've been using so far, but it does not work for self-contained deployments. The runtime itself should know its version, not infer it from where or how it's being run.
@loop-evgeny - also note that hack won't work in any "hammer servicing" scenarios. (I can't find great documentation on what "hammer servicing" is except for https://github.com/dotnet/core-setup/blob/be4e2eb3709ab5b307ff581f222fd2a4c7a2dc94/Documentation/design-docs/host-probing.md#probing-paths explains it a little. Basically, it is an ability for .NET Core assemblies to be patched without shipping a whole new X.Y.Z shared framework.)
"hammer servicing" scenarios
Hammer servicing works on per file granularity. The only way to detect it is to look at file version of the particular file you are interested in. None of the APIs discussed here or related issues would help you with that.
@jkotas - I was referring to @loop-evgeny's "hack" above:
Directory.GetParent(typeof(object).Assembly.Location).Name
If System.Private.CoreLib.dll was serviced, the location of that assembly would no longer be in a folder with the FX version number. Relying on the location of where typeof(object).Assembly lives, is probably not a good idea in general.
FYI: I updated the issue with an actual proposal.
This is all fixed now.
I validated with the latest master build that RuntimeInformation.FrameworkDescription is now providing the new behavior. I will report back when Environment.Version is working as expected.
Great to see this fixed! Could I just confirm that this will work even for self-contained deployments?
Yes, it will work for self-contained deployments.
From this morning's master build at dotnet/core-sdk. The new changes are in place.
C:\testapps\versioninfo>\Users\rlander\Downloads\dotnet-sdk-latest-win-x64\dotnet.exe run
.NET Core version:
Environment.Version: 3.0.0
RuntimeInformation.FrameworkDescription: .NET Core 3.0.0-preview4-27425-5
CoreCLR Build: 3.0.0-preview4.27425.72
CoreCLR Hash: 84f0ae886cc659fabd8d8b499861383bb801fa08
CoreFX Build: 3.0.0-preview4.19123.2
CoreFX Hash: 327def063eb5eddb723edcee84815d9495b4021c
If anyone is unsure what to do with the hashes, try these two links, using the hashes above:
Note: The links render in an unfortunate way for this purpose. Hover over the links (or just click on them) and you'll see that the linked hashes match the hashes above. It is now very easy to discover the commit that a given binary was built from and you can go and check it out.
Same thing with a self-contained build:
C:\testapps\versioninfo\bin\Debug\netcoreapp3.0\win-x64>versioninfo.exe
.NET Core version:
Environment.Version: 3.0.0
RuntimeInformation.FrameworkDescription: .NET Core 3.0.0-preview4-27425-5
CoreCLR Build: 3.0.0-preview4.27425.72
CoreCLR Hash: 84f0ae886cc659fabd8d8b499861383bb801fa08
CoreFX Build: 3.0.0-preview4.19123.2
CoreFX Hash: 327def063eb5eddb723edcee84815d9495b4021c
Most helpful comment
Same thing with a self-contained build: