-
Notifications
You must be signed in to change notification settings - Fork 4.9k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Make Environment.Version return the actual runtime version #3271
Comments
One challenge I just realized exists with using Environment.Version is the fact that it won’t support pre-releases since it’s a Version (not semantic version) |
From the host side, would implementing just (1) below work? See also additional options (2) and (3). Minimal implementation: This will work for both self-contained and framework-dependent applications. Using mscorelib.dll fileVersion is what Environment.Version is based on but now hard-codes (immutable and currently never changes). However FX_FILE_VERSION would be based on the actual fileVersion - e.g. for 2.1.2 it would be "4.6.26629.1" and for 2.1.3, it would be "4.6.26726.4". Note that assemblyVersion doesn't change from release to release so we use fileVersion instead. If we want a nice "product" version (e.g. 3.0.0-preview1) we could either assume a mapping from FX_FILE_VERSION to product version that we could either doc or implement somewhere, or we could expose another appdomain variable that would only work with framework-dependent: Finally if we want all framework versions: |
I do not think we want this version. It is the version that the app was built against. I think we want the version that the app is actually running on. |
For self-contained this should be the same; I'm assuming that to get a newer version of the coreclr requires the app to be re-built\published which will re-generate the deps.json. |
Yes Yes Yes.
We want the resolved version that the host policy ended up running on. Not build time dependencies. Not the file version but the actual runtime version that shows up when you |
I think there is a misunderstanding. For framework-dependent, we would obtain the mscorlib.dll fileVersion from the Microsoft.NETCore.App.deps.json that we're running against. Yes it was assigned during build-time, but the set of files for a given framework version is immutable. For self-contained, the app is running on the framework version it was built against. @dsplaisted is the app's deps.json updated with the appropriate fileVersion\assemblyVersion of framework assemblies when the app is re-built and automatically taking the latest framework patch? (I assume it is). The exception is the "hammer" servicing, which we haven't used yet. Note on Unix, since there isn't really a OS-level "file version" we would have to rely on the deps.json information, unless we want to crack open the assembly at run-time to look for the attribute but this has it's own set of technical issues when done from the host (before the CLR is initialized). Thus the CLR would likely need to do it, not the host. |
Also feature (1) asserts a "minimum" implementation (exposing fileVersion of mscorlib.dll) since the runtime version (e.g. "3.0.0-preview1") could be inferred from this, and that is what Environment.Version is based on (used to anyway, before it became hard-coded). There are also options (2) and (3) above that can return the more easily consumable runtime versions, but that wouldn't work for self-contained until someone writes the mapping that would be needed in (1), which is mapping fileVersion(mscorlib.dll) -> frameworkVersion(Microsoft.NETCore.App) |
Another option to consider, if we require the nice "framework version" for both standalone and self-contained would be to add that version information to the app's runtimeconfig.json for self-contained since today there is no framework reference (since it's "standalone" and doesn't need to look up the shared runtime). That would require some tooling changes and a way to add that information to runtime.config without making the standalone app turn into framework-dependent, because the raw presence of the framework information today makes the app use the shared framework. |
If we wanted to return CoreLib file version, we (or anybody else) can just do that. There is no cooperation with the host required. CoreLib is always opened by the runtime. The problem with CoreLib file version is that it is a useless piece of information on its own. As you have pointed out, you have to have infinitely growing table to map it to the netcoreapp version that you can reason about.
For self-contained apps, .deps.json has Microsoft.NETCore.App version that the app is bundled with (e.g. Microsoft.NETCore.App/2.1.2). |
Yes for self-contained we can read the deps.json for Microsoft.NETCore.App version, which today is a package version but should match the actual framework version. However if we want the versions from all frameworks (option 3) then that wouldn't work since we wouldn't want to "hard-code" the various framework package names in the host. So would just option (2) work: For framework-dependent, we just get the version that we are using. For self-contained, we get the version by looking for the version specified by "Microsoft.NETCore.App" in the app's deps.json file. Whether it is exposed through a managed API is TBD. We can't use Environment.Version for compat, plus we need a string not a System.Version type. |
I have an implementation of (2) at dotnet/core-setup#4470 |
@davidfowl commented on Mon Jul 16 2018
Today on a .NET Core 2.1.0 project printing
Environment.Version
prints out4.0.30319.42000
which is a hard coded constant in the runtime https://github.com/dotnet/coreclr/blob/ce0a2617d40bc217b8e0a2137e340afe585afcb1/src/System.Private.CoreLib/src/System/Environment.cs#L277. This should print out the actual runtime version based on the policy applied by the host (like 2.1.1 if that's what runtime version is actually being used).This also needs to be used as the version logged into the event log when there's an unhandled exception reported by the runtime. Today is a bogus version which isn't very useful.
@weshaggard commented on Mon Jul 23 2018
Today we don't have the "marketing version" (i.e. 2.1.1) embedded anywhere that we can consume so the best we could really do would be to return the file version of corelib.
@jkotas commented on Mon Jul 23 2018
The host knows this version - it can pass it to the runtime as key-value pair.
@weshaggard commented on Mon Jul 23 2018
I assume it only knows it for applications running on the shared framework correct? What should we return for standalone applications?
@jkotas commented on Mon Jul 23 2018
All applications have it in .deps.json file.
@weshaggard commented on Mon Jul 23 2018
I assume you are referring to the package version for Microsoft.NETCore.App (or runtime.[rid].Microsoft.NETCore.App) then? If so yes that may work for now but that may not be in the deps file in the future but we could probably ensure some version remains for this purposes.
@abbotware commented on Mon Jul 23 2018
I've been looking for away to get the RuntimeFrameworkVersion, so I tried all the API's that I could find (#31249) and none seemed to return anything useful - Any programmatic way to get the 'marketing version' would be good enough for me.
@weshaggard is there is a 1:1 mapping for 'corelib version' to 'marketing version' ? If yes, then could a lookup table be constructed?
Regarding versions returned from API calls, I am kinda curious though why the difference in System.Runtime.InteropServices.RuntimeInformation.FrameworkDescription:
.NET Core 4.6.26614.01
and Environment.Version:4.0.30319.42000
If one of those could be used to map back to the RuntimeFrameworkVersion, then there is at least a workaround for now?
@davidfowl commented on Tue Jul 24 2018
The host needs to pass the value to the runtime, the property would then read an AppContext property (or something similar) to get the actual version.
The host already does this for the deps file path in order to pass it to the DependencyModel API. https://github.com/dotnet/core-setup/blob/84fa44f892b42ad9235e4ecb756975d8c8f46f1f/src/corehost/cli/hostpolicy.cpp#L104
We just need to do this for the version as well.
@weshaggard commented on Tue Jul 24 2018
Yes the corelib version is 1:1 with the marketing version but doesn't exactly match it. If you workaround this for now you can get the version of corelib the same way we do for FrameworkDescription https://github.com/dotnet/corefx/blob/master/src/System.Runtime.InteropServices.RuntimeInformation/src/System/Runtime/InteropServices/RuntimeInformation/RuntimeInformation.cs#L28.
@davidfowl I agree the host can pass the value to the runtime it is just a matter of how it gets it in the various cases as well as what this API would do for custom hosts. We have to cover all the cases.
@davidfowl commented on Tue Jul 24 2018
Sure, just make it a contract. We look at a specific AppContext variable which is controlled by the host. In absence of that, we show something that doesn't mean much to you (the CLR file version or something).
@steveharter commented on Tue Jul 24 2018
Talked to @davidfowl a bit. I think the most straightforward way to do this is for the hostpolicy to add a couple AppContext\AppDomain variables like "FRAMEWORK_NAMES" and "FRAMEWORK_VERSIONS". They would list each framework and found\actual version (not requested version) separated by a delimiter.
We already do similar things with "FX_DEPS_FILE" that is picked up later by the CLI.
This information could we wrapped by a managed class in the future (Environment or otherwise).
@steveharter commented on Tue Jul 24 2018
Adding a "FRAMEWORK_NAMES" and "FRAMEWORK_VERSIONS" would not work for standalone; we would need a mapping from deps.json version as explained earlier or some other mechanism depending on what info we want
@steveharter commented on Tue Jul 24 2018
Overlaps a bit with https://github.com/dotnet/core-setup/issues/4112 for logging this information
@abbotware commented on Tue Jul 24 2018
@steveharter does 'standalone' = 'self contained deployment' (SCD) ? (In my case I am using an Ubuntu SNAP to deploy .Net Core + my App + Native libs on Linux)
@davidfowl commented on Tue Jul 24 2018
@weshaggard @jkotas If we change this property to be useful does that count as a breaking change? Specifically because it would go backwards?
@weshaggard commented on Tue Jul 24 2018
Every change is a breaking change :) however if we don't have any evidence that it will break people then we will assume it is not a breaking change. If enough folks get broken then we may change our mind about how we fix it.
@steveharter commented on Tue Jul 24 2018
Yes.
From the host perspective, the easiest implementation for both self-contained and framework-dependent would be to simply add a "FX_DEPS_FILES" context variable, similar to existing "FX_DEPS_FILE", but lists the path to the app's deps.json, every framework deps.json and perhaps those specified by additional-deps as well. For self-contained, there would only be one deps.json.
Then the managed layer would need to read each deps file and use a json parser (probably just use DependencyModel like this) to obtain the desired framework(s) by name and report back on the version.
Besides being simpler for the host, an advantage would also allow the managed layer to report on any types of other dependencies, including non-frameworks, assembly versions, etc if those were useful for logging.
The disadvantage is that it creates a dependency on the deps.json for the managed layer, which can change over time.
When we decide on a plan, I'll move this issue over to core-setup.
@jkotas commented on Wed Jul 25 2018
I do not think we would want to create dependency from
Environment.Version
(very low-level API) to DepenendencyModel.@davidfowl commented on Wed Jul 25 2018
I'd prefer we just set the version data direction in the host properties instead of using the deps file. Agree with @jkotas, we can't take a dependency in mscorlib on
deps.json
. It should be host agnostic.The text was updated successfully, but these errors were encountered: