Skip to content

Conversation

@joeloff
Copy link
Member

@joeloff joeloff commented Jul 27, 2025

Description

Conditionally turn off setting the SYSTEM PATH from the host installer. .NET supports a number of machine keys and values that determine how installers behave on Windows. This PR adds a new value under HKLM\SOFTWARE\Microsoft\.NET named DisableSettingHostPath (type REG_DWORD). When set to 1, the host installer will skip setting the SYSTEM PATH.

The change is needed to support new scenarios in the SDK to manage user installs.

Changes

Current Implementation

The host MSI performs major upgrades by installing the new product first (RemoveExistingProducts executes after InstallExecute). The component writing the DOTNETHOME to the sharedhost registry key also modifies the SYSTEM PATH.

New Implementation

The PATH variable will be set by separate component. Since the previous upgrade model does not support compositional changes, RemoveExistingProducts now runs after InstallInitialize. This ensures that the old product is removed before the new version is installed. It also supports rollback if a failure occurs (provided that rollbacks have not been turned off). While less efficient, the host MSI only contains a single file so there's no incurred overhead.

  • Minor fix in the component ID for writing the registry key to make it consistent with current authoring.
  • Registry search added to retrieve the new machine key. The property must be public
  • Environment entry is moved to a separate component. The component uses the same conditional logic for native vs. non-native platforms while also checking the property based on the machine key. The component has an explicit GUID because it contains neither a file nor a registry key and therefore WiX cannot generate a stable GUID.
  • WixBroadcastEnvironmentChange custom action is conditioned and set to execute after InstallFinalize.

Testing

Manually tested some scenarios using the bundles.

  • Tested clean install+uninstall with/without the registry key on sandbox. Below excerpt is from a log showing the property is set during AppSearch, the component action is set to Null (it won't be installed) and WixBroadcastEnvironmentChange custom action is skipped.
Action start 12:44:58: AppSearch.
MSI (s) (24:28) [12:44:58:287]: PROPERTY CHANGE: Adding DISABLE_SETTING_HOST_PATH property. Its value is '#1'.
...
MSI (s) (24:28) [12:44:58:437]: Component: cmpSetPath; Installed: Absent;   Request: Local;   Action: Null
...
MSI (s) (24:28) [12:44:58:924]: Skipping action: WixBroadcastEnvironmentChange (condition is false)
  • Tested upgrade from 9.0.

Verified that the existing component IDs did not change

8.0.117:

image

10 dev build:

image

Copilot AI review requested due to automatic review settings July 27, 2025 07:01
@github-actions github-actions bot added the needs-area-label An area label is needed to ensure this gets routed to the appropriate area owners label Jul 27, 2025
Copy link
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

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

Pull Request Overview

This PR adds conditional control over SYSTEM PATH modification during .NET host installer execution. The installer can now skip setting the SYSTEM PATH when a new registry key DisableSettingHostPath is set, supporting new SDK scenarios for managing user installs.

  • Introduces registry-based control to disable SYSTEM PATH modification during installation
  • Refactors PATH setting logic into a separate component with proper conditional checks
  • Changes major upgrade scheduling to support compositional changes and rollback capabilities

Reviewed Changes

Copilot reviewed 2 out of 2 changed files in this pull request and generated 1 comment.

File Description
host.wxs Separates PATH setting into dedicated component with registry-based conditional logic and adds new registry search property
dotnet-host.proj Updates major upgrade scheduling and adds new property to candle variables for build process
Comments suppressed due to low confidence (1)

src/installer/pkg/sfx/installers/host.wxs:41

  • [nitpick] The Component ID 'cmpPath' is inconsistent with the new component 'cmpSetPath' naming pattern. Consider renaming to 'cmpRegistryPath' or similar to clarify its purpose of setting registry values rather than PATH.
      <Component Id="cmpPath" Directory="DOTNETHOME" Guid="*">

@joeloff
Copy link
Member Author

joeloff commented Jul 27, 2025

@agocke as an FYI. This is related to what we discussed last week.

Copy link
Member

@nagilson nagilson left a comment

Choose a reason for hiding this comment

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

We should have someone who knows Wix review this PR, but the changes seem sound to me.

I can see some concern that going from afterInstallExecute to afterInstallInitialize may make the install fail if the uninstall failed (?) when it wouldn't have in the past, but given there's no good method for this change otherwise, I think it is justified. I would be surprised if install worked while uninstall did not, anywho.

@joeloff
Copy link
Member Author

joeloff commented Jul 28, 2025

We should have someone who knows Wix review this PR, but the changes seem sound to me.

I can see some concern that going from afterInstallExecute to afterInstallInitialize may make the install fail if the uninstall failed (?) when it wouldn't have in the past, but given there's no good method for this change otherwise, I think it is justified. I would be surprised if install worked while uninstall did not, anywho.

The install would fail if the previous copy of the host failed to uninstall - that is already the case today. The only difference is that now, if rollback is allowed, it would reinstall the older product it failed to uninstall. I tested this using WixFailWhenDeferred (it's a special CA that allows you test failure conditions). In v1, I author the custom action and only set WIXFAILWHENDEFERRED to 1 if UPGRADINGPRODUCTCODE is defined (this property only exists if a product is removed as part of a major upgrade).

    <CustomActionRef Id="WixFailWhenDeferred"/>

    <SetProperty Id="WIXFAILWHENDEFERRED" Value="1" After="InstallInitialize" Sequence="execute">
      UPGRADINGPRODUCTCODE
    </SetProperty>

So, you'll end up with the following. This is from

MSI (s) (08:44) [11:21:31:020]: Doing action: RemoveExistingProducts
....
MSI (s) (08:28) [11:21:31:312]: Hello, I'm your 32bit Impersonated custom action server.
CustomAction WixFailWhenDeferred returned actual error code 1603 (note this may not be 100% accurate if translation happened inside sandbox)
MSI (s) (08:50) [11:21:31:328]: PROPERTY CHANGE: Deleting UpdateStarted property. Its current value is '1'.
Action ended 11:21:31: InstallFinalize. Return value 3.
Action ended 11:21:31: INSTALL. Return value 3.
...
CustomAction  returned actual error code 1603 (note this may not be 100% accurate if translation happened inside sandbox)
MSI (s) (08:44) [11:21:31:375]: Note: 1: 2265 2:  3: -2147287035 
MSI (s) (08:44) [11:21:31:375]: User policy value 'DisableRollback' is 0
MSI (s) (08:44) [11:21:31:375]: Machine policy value 'DisableRollback' is 0
Action ended 11:21:31: RemoveExistingProducts. Return value 3.

@joeloff joeloff merged commit 6454b4c into dotnet:main Jul 30, 2025
77 checks passed
@github-actions github-actions bot locked and limited conversation to collaborators Aug 30, 2025
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.

Labels

needs-area-label An area label is needed to ensure this gets routed to the appropriate area owners

Projects

None yet

Development

Successfully merging this pull request may close these issues.

4 participants