Skip to content
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

Invoke ShellExecute on dism.exe for enabling Windows Features #3659

Merged
merged 7 commits into from Oct 11, 2023

Conversation

ryfu-msft
Copy link
Contributor

@ryfu-msft ryfu-msft commented Sep 22, 2023

Changes:

  • All calls to dismApi have been replaced with invoking ShellExecute on the Dism.exe. This is because the DismAPI has issues when being used in packaged context. The behavior of enabling Windows Features has been kept the same and all relevant tests have been updated.
Microsoft Reviewers: Open in CodeFlow

@ryfu-msft ryfu-msft requested a review from a team as a code owner September 22, 2023 21:14
@JohnMcPMS
Copy link
Member

I disabled the tests InstallWithWindowsFeatureDependency_FeatureNotFound and InstallWithWindowsFeatureDependency_Force, as they were failing for the reason you are making this change. Apparently there is some difference between the activation paths.

Please re-enable them in your branch.


std::filesystem::path GetDismExecutablePath()
{
return { ExpandEnvironmentVariables(L"%windir%\\system32\\dism.exe") };
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

nit: there is a GetExpandedPath function in winget/Filesystem.cpp which is specifically created for getting an expanded path

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Changed to calling GetExpandedPath from Filesystem.h

}

#ifndef AICLI_DISABLE_TEST_HOOKS
std::optional<DWORD> s_EnableWindowsFeatureResult_Override{};
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

nit: should we use the pointer pattern for this one and below like other test hooks so the codes have consistency?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

There is another test hook that also passes an optional value like so:
void TestHook_SetPinningIndex_Override(std::optional<std::filesystem::path>&& indexPath);

Since I am also passing an optional DWORD value, I just did something similar to that.


rootDependencies.ApplyToType(DependencyType::WindowsFeature, [&context, &result, &force, &rebootRequired](Dependency dependency)
{
if (FAILED(result) && !force || context.IsTerminated())
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

result does not seem to be an HResult, we would not use FAILED to check non hresult type

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I replaced the FAILED(result) check with a boolean value that is only set to true if we encounter an error. Since there are only a few error codes that we are looking for that change our output behavior to the user, I felt that this was an easier approach rather than checking for failed exit codes.

bool force = context.Args.Contains(Execution::Args::Type::Force);
bool rebootRequired = false;

rootDependencies.ApplyToType(DependencyType::WindowsFeature, [&context, &result, &force, &rebootRequired](Dependency dependency)
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think we should keep this ApplyToType part in DependenciesFLow.cpp so all dependencies related logic are in that flow. ShellExecuteInstallerHandler.cpp will only expose EnableWindowsFeature flow for enabling only 1 feature, so in the future if we are to implement winget features --enable --disable, we can reuse the same code.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I moved the ApplyToType part back to the DependenciesFlow as suggested. I created a separate workflow just for enabling a single feature that way it can be reused in the future.

@ryfu-msft ryfu-msft merged commit 3d60cec into microsoft:master Oct 11, 2023
8 checks passed
@ryfu-msft ryfu-msft deleted the windowsFeature branch October 11, 2023 20:51
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

None yet

3 participants