Skip to content

Commit 009de78

Browse files
authored
ContentRootPath breaking change (#29971)
1 parent 74aae68 commit 009de78

File tree

3 files changed

+63
-0
lines changed

3 files changed

+63
-0
lines changed

docs/core/compatibility/7.0.md

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -52,6 +52,12 @@ If you're migrating an app to .NET 7, the breaking changes listed here might aff
5252
| - | :-: | :-: | - |
5353
| [Multi-level lookup is disabled](deployment/7.0/multilevel-lookup.md) || ✔️ | Preview 4 |
5454

55+
## Extensions
56+
57+
| Title | Binary compatible | Source compatible | Introduced |
58+
| - | :-: | :-: | - |
59+
| [ContentRootPath for apps launched by Windows Shell](extensions/7.0/contentrootpath-hosted-app.md) || ✔️ | Preview 6 |
60+
5561
## Networking
5662

5763
| Title | Binary compatible | Source compatible | Introduced |
Lines changed: 49 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,49 @@
1+
---
2+
title: "Breaking change: ContentRootPath for apps launched by Windows Shell"
3+
description: Learn about the .NET 7 breaking change in .NET extensions where the 'ContentRootPath' property no longer defaults to the current directory for apps launched by Windows Shell or services.exe.
4+
ms.date: 06/22/2022
5+
---
6+
# ContentRootPath for apps launched by Windows Shell
7+
8+
The <xref:Microsoft.Extensions.Hosting.IHostEnvironment.ContentRootPath?displayProperty=nameWithType> property represents the default directory where *appsettings.json* and other content files are loaded in a hosted application, including ASP.NET apps. This property's value defaults to <xref:System.Environment.CurrentDirectory?displayProperty=nameWithType>, which is the current working directory of the application. This behavior allows the same app to be executed under different working directories and use the content from each directory.
9+
10+
When a Windows process (either application or service) is launched without specifying a working directory, the working directory of the process that [created it](/windows/win32/api/processthreadsapi/nf-processthreadsapi-createprocessa) is used. The working directory of Windows Shell or *services.exe* is *%windir%\system32* (or the `System` special folder). When either of those processes launches a hosted app, the `ContentRootPath` property is set to *%windir%\system32*.
11+
12+
This behavior is confusing and causes hosted applications to fail, because the application tries to load files from the *%windir%\system32* directory, but it doesn't exist. For example, the *appsettings.json* file is not found at run time and the settings aren't applied.
13+
14+
Starting with .NET 7, when a hosted application is launched with the current directory set to the `System` special folder, it defaults the `ContentRootPath` property to <xref:System.AppContext.BaseDirectory?displayProperty=nameWithType>.
15+
16+
## Version introduced
17+
18+
.NET 7 Preview 6
19+
20+
## Previous behavior
21+
22+
<xref:Microsoft.Extensions.Hosting.Host.CreateDefaultBuilder%2A?displayProperty=nameWithType> defaulted the <xref:Microsoft.Extensions.Hosting.IHostEnvironment.ContentRootPath> property to <xref:System.Environment.CurrentDirectory?displayProperty=nameWithType> regardless of the value of the current directory.
23+
24+
## New behavior
25+
26+
<xref:Microsoft.Extensions.Hosting.Host.CreateDefaultBuilder%2A?displayProperty=nameWithType> no longer defaults the <xref:Microsoft.Extensions.Hosting.IHostEnvironment.ContentRootPath> property to the current directory if it's the `System` special folder on Windows. Instead, the base directory of the application is used.
27+
28+
## Type of breaking change
29+
30+
This change can affect [binary compatibility](../../categories.md#binary-compatibility).
31+
32+
## Reason for change
33+
34+
App developers weren't expecting <xref:Microsoft.Extensions.Hosting.IHostEnvironment.ContentRootPath> to be *C:\Windows\system32* when their application was launched by Windows in certain cases (for example, when the app was packaged as an MSIX or started from the Start Menu). In these cases, it's better to default the <xref:Microsoft.Extensions.Hosting.IHostEnvironment.ContentRootPath> property to the base directory of the application.
35+
36+
## Recommended action
37+
38+
If you want to use the previous behavior, you can set the `ContentRootPath` property explicitly when creating the <xref:Microsoft.Extensions.Hosting.IHostBuilder>:
39+
40+
```csharp
41+
Host
42+
.CreateDefaultBuilder()
43+
.UseContentRoot(Environment.CurrentDirectory)
44+
....
45+
```
46+
47+
## Affected APIs
48+
49+
- <xref:Microsoft.Extensions.Hosting.Host.CreateDefaultBuilder%2A?displayProperty=fullName>

docs/core/compatibility/toc.yml

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -67,6 +67,10 @@ items:
6767
items:
6868
- name: Multi-level lookup is disabled
6969
href: deployment/7.0/multilevel-lookup.md
70+
- name: Extensions
71+
items:
72+
- name: ContentRootPath for apps launched by Windows Shell
73+
href: extensions/7.0/contentrootpath-hosted-app.md
7074
- name: Networking
7175
items:
7276
- name: AllowRenegotiation default is false
@@ -919,6 +923,10 @@ items:
919923
href: /ef/core/what-is-new/ef-core-3.x/breaking-changes?toc=/dotnet/core/compatibility/toc.json&bc=/dotnet/breadcrumb/toc.json
920924
- name: Extensions
921925
items:
926+
- name: .NET 7
927+
items:
928+
- name: ContentRootPath for apps launched by Windows Shell
929+
href: extensions/7.0/contentrootpath-hosted-app.md
922930
- name: .NET 6
923931
items:
924932
- name: AddProvider checks for non-null provider

0 commit comments

Comments
 (0)