There have been numerous requests around being able to customize how/where the
.NET root path will be determined for an application. This document describes
a proposed mechanism for basic configuration of how apphost will search for
the .NET install location.
Goals:
- Enable developers to build an app and configure it such that it can:
- Only consider global .NET installs
- Always look at a relative path for a .NET install
- Create a building block for a fuller, SDK-supported experience that should fit in regardless of where we land for the full experience
Non-goals:
- SDK support for layout and deployment of the app with a runtime files in a corresponding relative path
- SDK and project system experience for building a set of applications using the same custom runtime install location
Related:
- dotnet/runtime#2572
- dotnet/runtime#3453
- dotnet/runtime#53834
- dotnet/runtime#64430
- dotnet/runtime#70975
- dotnet/runtime#86801
The current state is described in detail in install-locations and install-locations-per-architecture
At a high level, the process and priority for apphost determining the install
location is:
- App-local
- Look for the runtime in the app's folder (self-contained apps)
- Environment variables
- Read the
DOTNET_ROOT_<arch>andDOTNET_ROOTenvironment variables
- Read the
- Global install (registered)
- Check for a registered install - registry key on Windows or an install location file on non-Windows
- Global install (default)
- Fall back to a well-known default install location based on the platform
Every apphost already has a placeholder that gets rewritten to contain the app
binary path during build (that is, dotnet build). This proposal adds another
placeholder which would represent the optional configuration of search locations
and app-relative path to an install location. Same as existing placeholder, it
would conditionally be rewritten based on the app's settings. This rewrite would
only be done on publish of the app currently.
This is similar to the proposal in dotnet/runtime#64430,
but with additional configuration of which search locations to use.
Some applications do not want to use all the default search locations when they are deployed - for example, dotnet/runtime#86801.
We can allow selection of which search locations the apphost will use. When
search locations are configured, only the specified locations will be searched.
The search location could be specified via a property in the project:
<AppHostDotNetSearch>Global</AppHostDotNetSearch>where the valid values are AppLocal, AppRelative, EnvironmentVariables, or
Global. Multiple values can be specified, delimited by semi-colons.
When a value is specified, only those locations will be used. For example, if
Global is specified, apphost will only look at global install locations, not
app-local, at any app-relative path, or at environment variables.
When a relative path is written into an apphost which is configured to look
at it, that path will be used as the .NET
install root when running the application.
The install location could be specified via a property in the project:
<AppHostRelativeDotNet>./relative/path/to/runtime</AppHostRelativeDotNet>Setting this implies AppHostDotNetSearch=AppRelative. This means that only the
relative path will be considered. If a .NET install is not found at the relative
path, other locations - environment variables, global install locations - will
not be considered and the app will fail to run.
AppHostDotNetSearch could also be explicitly set to include a fallback - for
example, AppHostDotNetSearch=AppRelative;Global would look at the relative
path and, if it is not found, the global locations. If AppHostDotNetSearch is
explicitly set to a value that does not include AppRelative, then setting
AppHostRelativeDotNet is meaningless - the SDK will not write the relative
path into the apphost and the apphost will not check for a relative path.
The path must not be rooted and will be written into the apphost unmodified.
At run time, the path will be considered relative to the app location - that is,
it is appended to the location of the apphost itself. The app relies on file
system APIs of the underlying OS to determine if the path is valid and exists.
When running C:\dir\app.exe or /home/dir/app with AppHostRelativeDotNet set to:
my_dotnet: the app will look atC:\dir\my_dotnetor/home/dir/my_dotnet./my_dotnet: the app will look atC:\dir\my_dotnetor/home/dir/my_dotnet../my_dotnetthe app will look atC:\my_dotnetor/home/my_dotnet
At a high level, the updated process and priority for apphost determining the
install location would be:
- App-local, if search location not configured
- Look for the runtime in the app's folder (self-contained apps)
- App-relative, if specified as a search location
- Use the path written into
apphost, relative to the app location
- Use the path written into
- Environment variables, if search location not configured or if set as a
search location
- Read the
DOTNET_ROOT_<arch>andDOTNET_ROOTenvironment variables
- Read the
- Global install (registered), if search location not configured or if set as
a search location
- Check for a registered install - registry key on Windows or a install location file on non-Windows
- Global install (default), if search location not configured or if set as a
search location
- Fall back to a well-known default install location based on the platform
By default - that is, without any configured install location options - the effective behaviour remains as in the current state.
This proposal writes the install location options in the apphost on publish.
Without SDK support for constructing the layout, updating on build would cause
the app to stop working in inner dev loop scenarios (running from output folder,
dotnet run, F5) unless they create a layout with the runtime in the expected
location relative to the app output as part of their build. This introduces a
difference between build and publish for apphost (currently, it is the
same between build and publish - with the exception of single-file, which is
only a publish scenario), but once SDK support is added it can be reconciled.
This proposal is only for apphost. It is not relevant for singlefilehost, as
that has the runtime itself statically linked. Other hosts (comhost, ijwhost)
are also not included. In theory, other hosts could be given the same treatment,
but we do not have feedback for scenarios using them. They also do not have the
app-local search or the existing requirement of being partially re-written via a
known placeholder. Changing them would add significant complexity without a
compelling scenario. If we see confusion here, we could add an SDK warning if
AppHostRelativeDotNet or AppHostDotNetSearch is set for those projects.