commit 077cf644438980e6eccfe1742abca65595aeb7b6
parent 9fb9458dcfc3899a3fb2138584f73d11b11708ba
Author: Ryan <69221034+ryfu-msft@users.noreply.github.com>
Date: Wed, 13 Sep 2023 16:02:01 -0700
make windows feature experimental (#3620)
Diffstat:
10 files changed, 54 insertions(+), 0 deletions(-)
diff --git a/doc/Settings.md b/doc/Settings.md
@@ -272,4 +272,15 @@ You can enable the feature as shown below.
"experimentalFeatures": {
"configuration": true
},
+```
+
+### windowsFeature
+
+This feature enables the ability to enable Windows Feature dependencies during installation.
+You can enable the feature as shown below.
+
+```json
+ "experimentalFeatures": {
+ "windowsFeature": true
+ },
```
\ No newline at end of file
diff --git a/schemas/JSON/settings/settings.schema.0.2.json b/schemas/JSON/settings/settings.schema.0.2.json
@@ -241,6 +241,11 @@
"description": "Enable support for configuration",
"type": "boolean",
"default": false
+ },
+ "windowsFeature": {
+ "description": "Enable support for enabling Windows Feature(s)",
+ "type": "boolean",
+ "default": false
}
}
}
diff --git a/src/AppInstallerCLICore/Workflows/DependenciesFlow.cpp b/src/AppInstallerCLICore/Workflows/DependenciesFlow.cpp
@@ -129,6 +129,11 @@ namespace AppInstaller::CLI::Workflow
void EnableWindowsFeaturesDependencies(Execution::Context& context)
{
+ if (!Settings::ExperimentalFeature::IsEnabled(Settings::ExperimentalFeature::Feature::WindowsFeature))
+ {
+ return;
+ }
+
const auto& rootDependencies = context.Get<Execution::Data::Installer>()->Dependencies;
if (rootDependencies.Empty())
diff --git a/src/AppInstallerCLIE2ETests/FeaturesCommand.cs b/src/AppInstallerCLIE2ETests/FeaturesCommand.cs
@@ -53,6 +53,7 @@ namespace AppInstallerCLIE2ETests
WinGetSettingsHelper.ConfigureFeature("experimentalArg", true);
WinGetSettingsHelper.ConfigureFeature("experimentalCmd", true);
WinGetSettingsHelper.ConfigureFeature("directMSI", true);
+ WinGetSettingsHelper.ConfigureFeature("windowsFeature", true);
var result = TestCommon.RunAICLICommand("features", string.Empty);
Assert.True(result.StdOut.Contains("Enabled"));
}
diff --git a/src/AppInstallerCLIE2ETests/InstallCommand.cs b/src/AppInstallerCLIE2ETests/InstallCommand.cs
@@ -17,6 +17,15 @@ namespace AppInstallerCLIE2ETests
public class InstallCommand : BaseCommand
{
/// <summary>
+ /// One time setup.
+ /// </summary>
+ [OneTimeSetUp]
+ public void OneTimeSetup()
+ {
+ WinGetSettingsHelper.ConfigureFeature("windowsFeature", true);
+ }
+
+ /// <summary>
/// Set up.
/// </summary>
[SetUp]
diff --git a/src/AppInstallerCLITests/WindowsFeature.cpp b/src/AppInstallerCLITests/WindowsFeature.cpp
@@ -24,6 +24,9 @@ TEST_CASE("InstallFlow_WindowsFeatureDoesNotExist", "[windowsFeature]")
TestCommon::TempFile installResultPath("TestExeInstalled.txt");
+ TestCommon::TestUserSettings testSettings;
+ testSettings.Set<Setting::EFWindowsFeature>(true);
+
std::ostringstream installOutput;
TestContext context{ installOutput, std::cin };
auto previousThreadGlobals = context.SetForCurrentThread();
@@ -57,6 +60,9 @@ TEST_CASE("InstallFlow_FailedToEnableWindowsFeature", "[windowsFeature]")
TestCommon::TempFile installResultPath("TestExeInstalled.txt");
+ TestCommon::TestUserSettings testSettings;
+ testSettings.Set<Setting::EFWindowsFeature>(true);
+
std::ostringstream installOutput;
TestContext context{ installOutput, std::cin };
auto previousThreadGlobals = context.SetForCurrentThread();
@@ -92,6 +98,9 @@ TEST_CASE("InstallFlow_FailedToEnableWindowsFeature_Force", "[windowsFeature]")
TestCommon::TempFile installResultPath("TestExeInstalled.txt");
+ TestCommon::TestUserSettings testSettings;
+ testSettings.Set<Setting::EFWindowsFeature>(true);
+
// Override with arbitrary DISM api error (DISMAPI_E_DISMAPI_NOT_INITIALIZED) and make windows feature discoverable.
HRESULT dismErrorResult = 0xc0040001;
LocIndString testFeatureDisplayName = LocIndString{ "Test Windows Feature"_liv };
@@ -139,6 +148,9 @@ TEST_CASE("InstallFlow_RebootRequired", "[windowsFeature]")
TestCommon::TempFile installResultPath("TestExeInstalled.txt");
+ TestCommon::TestUserSettings testSettings;
+ testSettings.Set<Setting::EFWindowsFeature>(true);
+
// Override with reboot required HRESULT.
auto mockDismHelperOverride = TestHook::MockDismHelper_Override();
auto setEnableFeatureOverride = TestHook::SetEnableWindowsFeatureResult_Override(ERROR_SUCCESS_REBOOT_REQUIRED);
@@ -173,6 +185,9 @@ TEST_CASE("InstallFlow_RebootRequired_Force", "[windowsFeature]")
TestCommon::TempFile installResultPath("TestExeInstalled.txt");
+ TestCommon::TestUserSettings testSettings;
+ testSettings.Set<Setting::EFWindowsFeature>(true);
+
// Override with reboot required HRESULT.
auto mockDismHelperOverride = TestHook::MockDismHelper_Override();
auto setEnableFeatureOverride = TestHook::SetEnableWindowsFeatureResult_Override(ERROR_SUCCESS_REBOOT_REQUIRED);
diff --git a/src/AppInstallerCommonCore/ExperimentalFeature.cpp b/src/AppInstallerCommonCore/ExperimentalFeature.cpp
@@ -40,6 +40,8 @@ namespace AppInstaller::Settings
return userSettings.Get<Setting::EFExperimentalArg>();
case ExperimentalFeature::Feature::DirectMSI:
return userSettings.Get<Setting::EFDirectMSI>();
+ case ExperimentalFeature::Feature::WindowsFeature:
+ return userSettings.Get<Setting::EFWindowsFeature>();
default:
THROW_HR(E_UNEXPECTED);
}
@@ -69,6 +71,8 @@ namespace AppInstaller::Settings
return ExperimentalFeature{ "Argument Sample", "experimentalArg", "https://aka.ms/winget-settings", Feature::ExperimentalArg };
case Feature::DirectMSI:
return ExperimentalFeature{ "Direct MSI Installation", "directMSI", "https://aka.ms/winget-settings", Feature::DirectMSI };
+ case Feature::WindowsFeature:
+ return ExperimentalFeature{ "Windows Feature Dependencies", "windowsFeature", "https://aka.ms/winget-settings", Feature::WindowsFeature };
default:
THROW_HR(E_UNEXPECTED);
}
diff --git a/src/AppInstallerCommonCore/Public/winget/ExperimentalFeature.h b/src/AppInstallerCommonCore/Public/winget/ExperimentalFeature.h
@@ -23,6 +23,7 @@ namespace AppInstaller::Settings
None = 0x0,
// Before making DirectMSI non-experimental, it should be part of manifest validation.
DirectMSI = 0x1,
+ WindowsFeature = 0x2,
Max, // This MUST always be after all experimental features
// Features listed after Max will not be shown with the features command
diff --git a/src/AppInstallerCommonCore/Public/winget/UserSettings.h b/src/AppInstallerCommonCore/Public/winget/UserSettings.h
@@ -70,6 +70,7 @@ namespace AppInstaller::Settings
EFExperimentalCmd,
EFExperimentalArg,
EFDirectMSI,
+ EFWindowsFeature,
// Telemetry
TelemetryDisable,
// Install behavior
@@ -145,6 +146,7 @@ namespace AppInstaller::Settings
SETTINGMAPPING_SPECIALIZATION(Setting::EFExperimentalCmd, bool, bool, false, ".experimentalFeatures.experimentalCmd"sv);
SETTINGMAPPING_SPECIALIZATION(Setting::EFExperimentalArg, bool, bool, false, ".experimentalFeatures.experimentalArg"sv);
SETTINGMAPPING_SPECIALIZATION(Setting::EFDirectMSI, bool, bool, false, ".experimentalFeatures.directMSI"sv);
+ SETTINGMAPPING_SPECIALIZATION(Setting::EFWindowsFeature, bool, bool, false, ".experimentalFeatures.windowsFeature"sv);
// Telemetry
SETTINGMAPPING_SPECIALIZATION(Setting::TelemetryDisable, bool, bool, false, ".telemetry.disable"sv);
// Install behavior
diff --git a/src/AppInstallerCommonCore/UserSettings.cpp b/src/AppInstallerCommonCore/UserSettings.cpp
@@ -259,6 +259,7 @@ namespace AppInstaller::Settings
WINGET_VALIDATE_PASS_THROUGH(EFExperimentalCmd)
WINGET_VALIDATE_PASS_THROUGH(EFExperimentalArg)
WINGET_VALIDATE_PASS_THROUGH(EFDirectMSI)
+ WINGET_VALIDATE_PASS_THROUGH(EFWindowsFeature)
WINGET_VALIDATE_PASS_THROUGH(AnonymizePathForDisplay)
WINGET_VALIDATE_PASS_THROUGH(TelemetryDisable)
WINGET_VALIDATE_PASS_THROUGH(InteractivityDisable)