Skip to content

Commit 8a68942

Browse files
authored
Update feature switch runtime configuration doc (#7765)
1 parent 2c59306 commit 8a68942

File tree

1 file changed

+73
-82
lines changed

1 file changed

+73
-82
lines changed

docs/WinformsRuntimeConfiguration.md renamed to docs/runtime-configuration.md

Lines changed: 73 additions & 82 deletions
Original file line numberDiff line numberDiff line change
@@ -1,98 +1,87 @@
1-
# Support for application runtime configuration in WinForms applications
1+
# Support for application runtime configuration in Windows Forms applications
22

33
## Overview
4-
\
5-
NET Winforms applications currently have [limited application
4+
5+
.NET Windows Forms applications currently have limited [application
66
configurations](https://aka.ms/applicationconfiguration) capabilities that are defined via MSBuils properties and are emitted into source code using source
77
generators at compile time. This document outlines expansion of those application-wide configurations further to cover runtime config options for .NET Windows Forms applications.
88

9-
## Runtime configuration in .NET Framework applications
10-
\
11-
.NET Framework Windows Forms applications use app.config to define runtime configurations and application-wide settings. Following are the various sections in the app.config that define application's runtime behavior.
9+
## .NET Framework runtime configuration
10+
11+
.NET Framework Windows Forms applications use `app.config` to define runtime configurations and application-wide settings. The following are the various sections in the app.config that define the application's runtime behavior.
1212

1313
### AppContext switches
1414

15-
These settings are used to opt-in or opt-out of a particular feature from WinForms runtime. Please refer to the [AppContext Switches](https://docs.microsoft.com/dotnet/framework/configure-apps/file-schema/runtime/appcontextswitchoverrides-element) documentation for more information
15+
These settings are used to opt-in or opt-out of a particular feature from Windows Forms runtime. Refer to the [AppContext Switches](https://docs.microsoft.com/dotnet/framework/configure-apps/file-schema/runtime/appcontextswitchoverrides-element) documentation for more information.
1616

17-
```XML
17+
```xml
1818
<configuration>
19-
<runtime>
20-
<AppContextSwitchOverrides value="Switch.System.Globalization.NoAsyncCurrentCulture=true" />
21-
</runtime>
19+
<runtime>
20+
<AppContextSwitchOverrides value="Switch.System.Globalization.NoAsyncCurrentCulture=true" />
21+
</runtime>
2222
</configuration>
2323
```
24-
### System.Windows.Forms.ApplicationConfigurationSection
24+
### `System.Windows.Forms.ApplicationConfigurationSection` section
2525

26-
This was introduced in .NET Framework 4.7 and is primarily used by Winforms runtime to enable high Dpi and other accessibility improvements. Please refer to the [ApplicationConfigurationSection](https://docs.microsoft.com/dotnet/framework/configure-apps/file-schema/winforms/windows-forms-add-configuration-element) documentation for more information.
26+
This was introduced in .NET Framework 4.7, and it is primarily used by Windows Forms runtime to enable high DPI and other accessibility improvements. Please refer to the [ApplicationConfigurationSection](https://docs.microsoft.com/dotnet/framework/configure-apps/file-schema/winforms/windows-forms-add-configuration-element) documentation for more information.
2727

28-
```XML
28+
```xml
2929
<configuration>
3030
<System.Windows.Forms.ApplicationConfigurationSection>
31-
...
31+
<!-- content -->
3232
</System.Windows.Forms.ApplicationConfigurationSection>
3333
</configuration>
3434
```
3535

36-
### App settings from Settings designer/editor page
37-
38-
Unlike above, these settings are used by the user application. These are commonly defined via the Settings designer in Visual Studio, which intern serialize them into the app.config file. Please refer to the [Application Settings](https://docs.microsoft.com/dotnet/desktop/winforms/advanced/using-application-settings-and-user-settings?view=netframeworkdesktop-4.8) documentation for more information.
39-
```XML
40-
<userSettings>
41-
<WinFormsApp2.Properties.Settings>
42-
<setting name="ButtonName" serializeAs="String">
43-
<value>LocalButton</value>
44-
</setting>
45-
</WinFormsApp2.Properties.Settings>
46-
</userSettings>
47-
<applicationSettings>
48-
<WinFormsApp2.Properties.Settings>
49-
<setting name="BoxName" serializeAs="String">
50-
<value>LocalBox</value>
51-
</setting>
52-
</WinFormsApp2.Properties.Settings>
53-
</applicationSettings>
36+
### Application-wide and user-specific settings
37+
38+
These are commonly defined via the Settings designer in Visual Studio, which serializes those into `app.config`. Refer to the [Application Settings](https://docs.microsoft.com/dotnet/desktop/winforms/advanced/using-application-settings-and-user-settings) documentation for more information.
39+
40+
```xml
41+
<userSettings>
42+
<WinFormsApp2.Properties.Settings>
43+
<setting name="ButtonName" serializeAs="String">
44+
<value>LocalButton</value>
45+
</setting>
46+
</WinFormsApp2.Properties.Settings>
47+
</userSettings>
48+
49+
<applicationSettings>
50+
<WinFormsApp2.Properties.Settings>
51+
<setting name="BoxName" serializeAs="String">
52+
<value>LocalBox</value>
53+
</setting>
54+
</WinFormsApp2.Properties.Settings>
55+
</applicationSettings>
5456
```
5557

5658

57-
## Winforms runtime configuration in .NET applications
58-
\
59-
app.config has limited support in .NET due to performance and reliability reasons. .NET runtime and other .NET teams use runtimeconfig.json to define .NET runtime configurations and appsettings.json to define application-level settings. In this proposal, we are leveraging runtimeconfig.json to define WinForms runtime configurations.
59+
## .NET 7+ runtime configuration
60+
61+
`app.config` has limited support in .NET due to performance and reliability reasons. .NET runtime and other .NET teams use `runtimeconfig.json` to define .NET runtime configurations and `appsettings.json` to define application-level settings. In this proposal, we are leveraging `runtimeconfig.json` to define Windows Forms runtime configurations.
6062

61-
While this proposal is focusing on providing an alternative solution for existing configuration sections `AppContextSwitchOverrides` and `System.Windows.Forms.ApplicationConfigurationSection` that are primarily used for specifying feature flags impacting winforms runtime behavior, we will be looking into alternatives for `Application Settings` that doesn't require app.config in the upcoming releases of .NET.
63+
While this proposal is focusing on providing an alternative solution for existing configuration sections `AppContextSwitchOverrides` and `System.Windows.Forms.ApplicationConfigurationSection` that are primarily used for specifying feature flags impacting Windows Forms runtime behavior, we will be looking into alternatives for `Application Settings` that doesn't require `app.config` in the future releases of .NET.
6264

6365

6466
### Goals:
6567

66-
- A replacement for `AppContextSwitchOverrides` and `System.Windows.Forms.ApplicationConfigurationSection` of app.config.
67-
- Users should be able to update/modify Winforms applications runtime configurations without recompiling the application.
68-
- The existing applications should be able to seamlessly upgrade to the new configuration model when targeting the latest .NET runtiem.
69-
- The existing [application configuration MSBuild properties](https://aka.ms/applicationconfiguration) continue to work.
68+
- A replacement for `AppContextSwitchOverrides` and `System.Windows.Forms.ApplicationConfigurationSection` of `app.config`.
69+
- Users should be able to update/modify Windows Forms applications runtime configurations without recompiling the application.
70+
- The existing applications should be able to seamlessly upgrade to the new configuration model when targeting .NET 7+ runtime.
71+
- The existing [application configuration MSBuild properties](https://aka.ms/applicationconfiguration) continue to work.
7072

7173
### Out of scope:
7274

73-
App settings that are serialized by the Settings designer/editor page. Applications should continue to use the current model.
74-
- Dynamic/real-time (re-)loading of configuration values from runtimeconfig.json.
75-
- Unification of comple/runtime configurations into one place, runtimeconfig.json.
75+
- App settings that are serialized by the Settings designer/editor page. Applications should continue to use the current model.
76+
- Dynamic/real-time (re-)loading of configuration values from `runtimeconfig.json`.
77+
- Unification of comple/runtime configurations into one place, e.g., `runtimeconfig.json`.
7678

7779

78-
#### Syntax of runtimeConfig.template.Json.
79-
80-
```xml
81-
{
82-
"configProperties": {
83-
"System.Globalization.UseNls": true,
84-
"System.Net.DisableIPv6": true,
85-
"System.GC.Concurrent": false,
86-
"System.Threading.ThreadPool.MinThreads": 4,
87-
"System.Threading.ThreadPool.MaxThreads": 25
88-
}
89-
}
90-
```
91-
92-
Windows Forms switches will be added to [`configProperties` section](https://docs.microsoft.com/dotnet/core/runtime-config) with the rest of the .NET switches. To avoid name conflics Windows Forms specific switches will be prefixed with `System.Windows.Forms`:
80+
### Design proposal
9381

82+
Windows Forms switches will be added to **`runtimeConfig.template.json`** to the [`configProperties` section](https://docs.microsoft.com/dotnet/core/runtime-config) with the rest of the .NET switches. To avoid name conflics Windows Forms specific switches will be prefixed with `System.Windows.Forms`:
9483

95-
```xml
84+
```json
9685
{
9786
"configProperties": {
9887
"System.Globalization.UseNls": true,
@@ -101,21 +90,23 @@ Windows Forms switches will be added to [`configProperties` section](https://doc
10190
"System.Threading.ThreadPool.MinThreads": 4,
10291
"System.Threading.ThreadPool.MaxThreads": 25,
10392

104-
<!-- Windows Forms specific switches -->
93+
// Windows Forms specific switches
10594
"System.Windows.Forms.ScaleTopLevelFormMinMaxSizeForDpi": true,
106-
"System.Windows.Forms.<CustomEnumProperty>": "EnumValue"
95+
"System.Windows.Forms.CustomEnumProperty": "EnumValue"
10796
}
10897
}
10998
```
11099

111100

112-
### Reading Winforms runtime configurations:
113-
\
114-
When a project is [built](https://docs.microsoft.com/en-us/dotnet/core/runtime-config/#runtimeconfigjson), an _[appname].runtimeconfig.json_ file is generated in the output directory. If a _runtimeconfig.template.json_ file exists in the same folder as the project file, any configuration options it contains are inserted into the _[appname].runtimeconfig.json_ file.
115-
This proposal focuses primarily on enabling the runtime configurations for WinForms applications. A support for analyzers and source generators may be considered in the future .NET releases. We will revisit this implementation to improve user-experience further, as we make progress.
116-
For example, the content of _[appname].runtimeconfig.json_ generated from above content:
101+
#### Reading Windows Forms runtime configurations
102+
103+
When a project is [built](https://docs.microsoft.com/dotnet/core/runtime-config/#runtimeconfigjson), an `[appname].runtimeconfig.json` file is generated in the output directory. If a `runtimeconfig.template.json` file exists in the same folder as the project file, any configuration options it contains are inserted into the `[appname].runtimeconfig.json` file.
104+
105+
This proposal focuses primarily on enabling the runtime configurations for Windows Forms applications. A support for analyzers and source generators may be considered in the future .NET releases. We will revisit this implementation to improve user-experience further, as we make progress.
106+
107+
For example, the content of `[appname].runtimeconfig.json` generated from above content:
117108

118-
```XML
109+
```json
119110
{
120111
"runtimeOptions": {
121112
"tfm": "net7.0",
@@ -135,29 +126,31 @@ For example, the content of _[appname].runtimeconfig.json_ generated from above
135126
"System.GC.Concurrent": false,
136127
"System.Threading.ThreadPool.MinThreads": 4,
137128
"System.Threading.ThreadPool.MaxThreads": 25,
129+
138130
"System.Windows.Forms.ScaleTopLevelFormMinMaxSizeForDpi": true,
139-
"System.Windows.Forms.<StringProperty>": "string"
140-
"System.Windows.Forms.<CustomProperty>": "CustomValue"
131+
"System.Windows.Forms.StringProperty": "string",
132+
"System.Windows.Forms.CustomProperty": "CustomValue"
141133
}
142134
}
143135
}
144136
```
145137

146-
The target framework information added to _[appname].runtimeconfig.json_ file always match with the application target framework irrespective of runtime/SDK installed on the machine or runtime used ([roll-forward scenarios](https://docs.microsoft.com/dotnet/core/versions/selection#framework-dependent-apps-roll-forward)) by the Windows Forms application.
138+
The target framework information added to `[appname].runtimeconfig.json` file always match with the application target framework irrespective of runtime/SDK installed on the machine or runtime used ([roll-forward scenarios](https://docs.microsoft.com/dotnet/core/versions/selection#framework-dependent-apps-roll-forward)) by the Windows Forms application.
139+
140+
#### .NET runtime support in reading `runtimeconfig.json`
147141

148-
### .NET runtime support in reading runtimeconfig.json:
149-
\
150-
WinForms is leveraging the [support](https://github.com/dotnet/runtime/blob/5098d45cc1bf9649fab5df21f227da4b80daa084/src/native/corehost/runtime_config.cpp) provided by .NET runtime in reading the _[appname].runtimeconfig.json_ file, and thus get all plumbing required for various hosting and environment scenarios.
151-
WinForms adds the following wrapper on top of .NET runtime implementation to improve the performance by caching configuration options, and also by defining custom defaults values for the WinForms specific feature flags. This wrapper is very similar to the [.NET runtime's implementation](https://github.com/dotnet/runtime/blob/04dac7b0fede29d44f896c5fd793754f83974175/src/libraries/System.Private.CoreLib/src/System/AppContextConfigHelper.cs).
152-
The below example illustrates how to define `ScaleTopLevelFormMinMaxSizeForDpi` feature flag, opt-in by default, if an application is running on Windows 10 and is targeting .NET 8:
142+
The Windows Forms runtime is leveraging the [support](https://github.com/dotnet/runtime/blob/5098d45cc1bf9649fab5df21f227da4b80daa084/src/native/corehost/runtime_config.cpp) provided by .NET runtime in reading `[appname].runtimeconfig.json` file, and thus get all plumbing required for various hosting and environment scenarios. The Windows Forms runtime adds the following wrapper on top of .NET runtime implementation to improve the performance by caching configuration options, and also by defining custom defaults values for the Windows Forms specific feature flags. This wrapper is very similar to the [.NET runtime's implementation](https://github.com/dotnet/runtime/blob/04dac7b0fede29d44f896c5fd793754f83974175/src/libraries/System.Private.CoreLib/src/System/AppContextConfigHelper.cs).
143+
144+
The below example illustrates how to define `ScaleTopLevelFormMinMaxSizeForDpi` feature flag, opt-in by default, for an application targeting .NET 8 or later running on Windows 10:
153145

154146
```cs
155147
internal static partial class LocalAppContextSwitches
156148
{
149+
private const string ScaleTopLevelFormMinMaxSizeForDpiSwitchName = "System.Windows.Forms.ScaleTopLevelFormMinMaxSizeForDpi";
150+
157151
private static readonly FrameworkName? s_targetFrameworkName = GetTargetFrameworkName();
158152
private static readonly bool s_isNetCoreApp = (s_targetFrameworkName?.Identifier) == ".NETCoreApp";
159153

160-
private const string ScaleTopLevelFormMinMaxSizeForDpiSwitchName = "System.Windows.Forms.ScaleTopLevelFormMinMaxSizeForDpi";
161154
private static int s_scaleTopLevelFormMinMaxSize;
162155

163156
public static bool ScaleTopLevelFormMinMaxSizeForDpi
@@ -226,9 +219,7 @@ internal static partial class LocalAppContextSwitches
226219
```
227220

228221

229-
WinForms runtime then uses the static `LocalAppContextSwitches` class to access the runtime configurations. The below sample demonstrates how to access the feature switch `System.Windows.Forms.ScaleTopLevelFormMinMaxSizeForDpi`:
230-
231-
Ex: Use of feature switch in ScaleContainerForDpi() method in ContainerControl.cs to scale Min/Max size of the Container.
222+
The Windows Forms runtime then uses the static `LocalAppContextSwitches` class to access the runtime configurations. The below sample demonstrates the use of the feature switch `System.Windows.Forms.ScaleTopLevelFormMinMaxSizeForDpi` to scale min/max size of a container control:
232223

233224
```cs
234225
internal void ScaleContainerForDpi(int deviceDpiNew, int deviceDpiOld, Rectangle suggestedRectangle)
@@ -252,7 +243,7 @@ internal void ScaleContainerForDpi(int deviceDpiNew, int deviceDpiOld, Rectangle
252243
// WM_DPICHANGED event. Failing to apply SuggestedRectangle will result in a circular WM_DPICHANGED
253244
// events on the control.
254245
255-
// Note: SuggestedRectangle supplied by WM_DPICHANGED event is Dpi (not Font) scaled. if top-level window is
246+
// Note: SuggestedRectangle supplied by WM_DPICHANGED event is DPI (not Font) scaled. if top-level window is
256247
// Font scaled, we might see deviations in the expected bounds and may result in adding Scrollbars (horizontal/vertical)
257248
User32.SetWindowPos(
258249
new HandleRef(this, HandleInternal),
@@ -293,7 +284,7 @@ internal void ScaleContainerForDpi(int deviceDpiNew, int deviceDpiOld, Rectangle
293284
}
294285
finally
295286
{
296-
// We want to perform layout for dpi-changed high Dpi improvements - setting the second parameter to 'true'
287+
// We want to perform layout for DPI-changed high DPI improvements - setting the second parameter to 'true'
297288
ResumeAllLayout(this, true);
298289
_isScaledByDpiChangedEvent = false;
299290
}

0 commit comments

Comments
 (0)