Skip to content

Commit 90e81cb

Browse files
authored
[New+] Hide existing new - remake (#44979)
## Summary of the Pull Request - Add the ability for users and admins (GPO) to control whether to display built in New on the context menu. - Changes to the setting are immediately reflected in the experience. - Built-in New is restored on uninstall. ## PR Checklist Note: Supersedes #39843 - [x] **Closes**: [New+] Replace default New entry #37545 and Replace "New" with New+ option #37946 - [x] **Communication:** Discussed with @niels9001 - 1/22/2025 - [x] **Tests:** Completed manual test pass see highlight below - [x] **Localization:** All end-user-facing strings can be localized - [x] **Dev docs:** Updated "doc\devdocs\modules\newplus.md" - [n/a] **New binaries:** Added on the required places - [n/a] [JSON for signing](https://github.com/microsoft/PowerToys/blob/main/.pipelines/ESRPSigning_core.json) for new binaries - [x] [WXS for installer] Updated installer (uninstall custom action) - [n/a] [YML for CI pipeline](https://github.com/microsoft/PowerToys/blob/main/.pipelines/ci/templates/build-powertoys-steps.yml) for new test projects - [n/a] [YML for signed pipeline](https://github.com/microsoft/PowerToys/blob/main/.pipelines/release.yml) - [No] **Documentation updated:** Pending, coming soon. (original PR MicrosoftDocs/windows-dev-docs#5473) ## Detailed Description of the Pull Request / Additional comments Added the ability for users' admins' to display Windows built-in New or not I'm NOT aware of an official supported way to do this, so I'm achieving this by adding an invalid context menu handler in place of New in the Computer\HKEY_CURRENT_USER\Software\Classes\Directory\background\ShellEx\ContextMenuHandlers\New Changes are immediate, after applying the change, built-in New is shown/hidden accordingly Updates to New+ Settings UI New setting introduced to track user' preference (saved to newplus/settings.json) GPO setting introduced for control New visibility via GPO (GPO wins over user preference) Updates to New+ power_module.cpp When runner is running new plus will also apply built-in New admin GPO and user preference (GPO wins over user preference) to ensure correct behavior on setting restore and GPO application. Updates to installer Uninstall always reenable built-in "New" context menu Updated DevDoc Added a note on how to manually restore built-in New ## Validation Steps Performed Windows 11 x64 Settings UI New+ enabled New+ disabled GPO setting enabled GPO settings disabled Manually updating newplus/settings.json Windows 11 ARM64 I tested the reg hack manually, but didn't go through a full pass. Windows 10 x64 NOT tested. Windows 11, Settings, New+ Disabled and no GPO <img width="1040" height="1002" alt="image" src="https://github.com/user-attachments/assets/1b827b10-f009-4b0b-954f-d9311d40d201" /> Windows 11, Settings, New+ Enabled and no GPO <img width="1015" height="781" alt="image" src="https://github.com/user-attachments/assets/a5fa09d3-7fd3-4830-99a4-5f2ac9ce1a38" /> Hide built-in New: Off (the default) <img width="321" height="417" alt="image" src="https://github.com/user-attachments/assets/355fea60-bbb8-4f11-b648-291aaf0c4a6d" /> Hide built-in New: On <img width="1015" height="87" alt="image" src="https://github.com/user-attachments/assets/e83e45c4-6b67-443b-b045-26e7dda2cf46" /> Modern <img width="308" height="360" alt="image" src="https://github.com/user-attachments/assets/b164b240-6e67-410c-8481-7db3ee3225b7" /> Classic <img width="308" height="289" alt="image" src="https://github.com/user-attachments/assets/e2b6c262-a311-454c-9c76-40cb11ff2970" /> Disabling New+ also unhide New <img width="1031" height="569" alt="image" src="https://github.com/user-attachments/assets/29b8dae7-8190-4e64-b106-c6861e472a3d" /> <img width="308" height="353" alt="image" src="https://github.com/user-attachments/assets/e1977d6b-dc85-4db4-b9ab-c7bb2b27dde2" /> Windows 11, Settings, New+ Enabled and with GPO Hide built-in New: GPO enabled <img width="1020" height="691" alt="image" src="https://github.com/user-attachments/assets/75053ab8-92c6-4d38-b1b8-9b0d8293c207" /> Hide built-in New: GPO disabled <img width="1050" height="161" alt="image" src="https://github.com/user-attachments/assets/1a50b841-ff01-4662-a923-aee63717c834" />
1 parent 3e1b07f commit 90e81cb

19 files changed

Lines changed: 363 additions & 6 deletions

File tree

doc/devdocs/modules/newplus.md

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -141,3 +141,10 @@ Note: The DllHost process loads the DLL only when the context menu is triggered
141141
- A signature issue with the MSIX package
142142

143143
- For development and testing, using the Windows 10 handler can be easier since it doesn't require signing.
144+
145+
## Restoring Built-in Windows New context menu
146+
If the Windows 11 built-in New context menu doesn't reappear on uninstalling PowerToys, some issue with settings etc. here's how to restore the built-in New context menu.
147+
148+
1. Open Registry Editor
149+
1. Go to the key "Computer\HKEY_CURRENT_USER\Software\Classes\Directory\background\ShellEx\ContextMenuHandlers"
150+
1. Delete the "New" subkey (i.e. fullpath "Computer\HKEY_CURRENT_USER\Software\Classes\Directory\background\ShellEx\ContextMenuHandlers\New")

installer/PowerToysSetupCustomActionsVNext/CustomAction.cpp

Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1119,6 +1119,35 @@ UINT __stdcall RemoveScheduledTasksCA(MSIHANDLE hInstall)
11191119
return WcaFinalize(er);
11201120
}
11211121

1122+
UINT __stdcall RestoreBuiltInNewContextMenuCA(MSIHANDLE hInstall)
1123+
{
1124+
HRESULT hr = S_OK;
1125+
hr = WcaInitialize(hInstall, "RestoreBuiltInNewContextMenuCA");
1126+
1127+
constexpr wchar_t built_in_new_registry_path[] = LR"(Software\Classes\Directory\Background\ShellEx\ContextMenuHandlers\New)";
1128+
1129+
HKEY key{};
1130+
1131+
if (RegOpenKeyExW(HKEY_CURRENT_USER,
1132+
built_in_new_registry_path,
1133+
0,
1134+
KEY_ALL_ACCESS,
1135+
&key) != ERROR_SUCCESS)
1136+
{
1137+
return WcaFinalize(ERROR_SUCCESS);
1138+
}
1139+
1140+
if (RegDeleteValueW(key, nullptr) != ERROR_SUCCESS)
1141+
{
1142+
RegCloseKey(key);
1143+
return WcaFinalize(ERROR_SUCCESS);
1144+
}
1145+
1146+
RegCloseKey(key);
1147+
1148+
return WcaFinalize(ERROR_SUCCESS);
1149+
}
1150+
11221151
UINT __stdcall TelemetryLogInstallSuccessCA(MSIHANDLE hInstall)
11231152
{
11241153
HRESULT hr = S_OK;

installer/PowerToysSetupCustomActionsVNext/CustomAction.def

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@ EXPORTS
77
ApplyModulesRegistryChangeSetsCA
88
DetectPrevInstallPathCA
99
RemoveScheduledTasksCA
10+
RestoreBuiltInNewContextMenuCA
1011
TelemetryLogInstallSuccessCA
1112
TelemetryLogInstallCancelCA
1213
TelemetryLogInstallFailCA

installer/PowerToysSetupVNext/Product.wxs

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -161,6 +161,9 @@
161161
<!-- Clean Video Conference Mute registry keys that might be around from previous installations. We've deprecated this utility since then. -->
162162
<Custom Action="CleanVideoConferenceRegistry" Before="InstallFinalize" Condition="NOT Installed" />
163163

164+
<!-- Restore built-in "New" context menu in case user disabled it via New+ -->
165+
<Custom Action="RestoreBuiltInNewContextMenu" Before="RemoveFiles" Condition="Installed AND (REMOVE=&quot;ALL&quot;)" />
166+
164167
</InstallExecuteSequence>
165168

166169
<CustomAction Id="SetLaunchPowerToysParam" Property="LaunchPowerToys" Value="[INSTALLFOLDER]" />
@@ -262,6 +265,8 @@
262265

263266
<CustomAction Id="SetBundleInstallLocation" Return="ignore" Impersonate="no" Execute="deferred" DllEntry="SetBundleInstallLocationCA" BinaryRef="PTCustomActions" />
264267

268+
<CustomAction Id="RestoreBuiltInNewContextMenu" Return="ignore" Impersonate="yes" Execute="deferred" DllEntry="RestoreBuiltInNewContextMenuCA" BinaryRef="PTCustomActions" />
269+
265270
<!-- Close 'PowerToys.exe' before uninstall-->
266271
<Property Id="MSIRESTARTMANAGERCONTROL" Value="DisableShutdown" />
267272
<Property Id="MSIFASTINSTALL" Value="DisableShutdown" />

src/common/GPOWrapper/GPOWrapper.cpp

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -292,4 +292,8 @@ namespace winrt::PowerToys::GPOWrapper::implementation
292292
{
293293
return static_cast<GpoRuleConfigured>(powertoys_gpo::getConfiguredRunAtStartupValue());
294294
}
295+
GpoRuleConfigured GPOWrapper::GetConfiguredNewPlusHideBuiltInNewContextMenuValue()
296+
{
297+
return static_cast<GpoRuleConfigured>(powertoys_gpo::getConfiguredNewPlusHideBuiltInNewContextMenuValue());
298+
}
295299
}

src/common/GPOWrapper/GPOWrapper.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -78,6 +78,7 @@ namespace winrt::PowerToys::GPOWrapper::implementation
7878
static GpoRuleConfigured GetAllowDataDiagnosticsValue();
7979
static GpoRuleConfigured GetConfiguredRunAtStartupValue();
8080
static GpoRuleConfigured GetConfiguredNewPlusReplaceVariablesValue();
81+
static GpoRuleConfigured GetConfiguredNewPlusHideBuiltInNewContextMenuValue();
8182
};
8283
}
8384

src/common/GPOWrapper/GPOWrapper.idl

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -82,6 +82,7 @@ namespace PowerToys
8282
static GpoRuleConfigured GetAllowDataDiagnosticsValue();
8383
static GpoRuleConfigured GetConfiguredRunAtStartupValue();
8484
static GpoRuleConfigured GetConfiguredNewPlusReplaceVariablesValue();
85+
static GpoRuleConfigured GetConfiguredNewPlusHideBuiltInNewContextMenuValue();
8586
}
8687
}
8788
}

src/common/utils/gpo.h

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -103,6 +103,7 @@ namespace powertoys_gpo
103103
const std::wstring POLICY_MWB_POLICY_DEFINED_IP_MAPPING_RULES = L"MwbPolicyDefinedIpMappingRules";
104104
const std::wstring POLICY_NEW_PLUS_HIDE_TEMPLATE_FILENAME_EXTENSION = L"NewPlusHideTemplateFilenameExtension";
105105
const std::wstring POLICY_NEW_PLUS_REPLACE_VARIABLES = L"NewPlusReplaceVariablesInTemplateFilenames";
106+
const std::wstring POLICY_NEW_PLUS_HIDE_BUILT_IN_NEW_CONTEXT_MENU = L"NewPlusHideBuiltInNewContextMenu";
106107

107108
// Methods used for reading the registry
108109
#pragma region ReadRegistryMethods
@@ -700,5 +701,10 @@ namespace powertoys_gpo
700701
return getConfiguredValue(POLICY_NEW_PLUS_REPLACE_VARIABLES);
701702
}
702703

704+
inline gpo_rule_configured_t getConfiguredNewPlusHideBuiltInNewContextMenuValue()
705+
{
706+
return getConfiguredValue(POLICY_NEW_PLUS_HIDE_BUILT_IN_NEW_CONTEXT_MENU);
707+
}
708+
703709
#pragma endregion IndividualModuleSettingPolicies
704710
}

src/gpo/assets/PowerToys.admx

Lines changed: 13 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,11 @@
11
<?xml version="1.0" encoding="utf-8"?>
22
<!-- Copyright (c) Microsoft Corporation.
33
Licensed under the MIT License. -->
4-
<policyDefinitions xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" revision="1.19" schemaVersion="1.0" xmlns="http://schemas.microsoft.com/GroupPolicy/2006/07/PolicyDefinitions">
4+
<policyDefinitions xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" revision="1.20" schemaVersion="1.0" xmlns="http://schemas.microsoft.com/GroupPolicy/2006/07/PolicyDefinitions">
55
<policyNamespaces>
66
<target prefix="powertoys" namespace="Microsoft.Policies.PowerToys" />
77
</policyNamespaces>
8-
<resources minRequiredRevision="1.19"/><!-- Last changed with PowerToys v0.97.0 -->
8+
<resources minRequiredRevision="1.20"/><!-- Last changed with PowerToys v0.98.0 -->
99
<supportedOn>
1010
<definitions>
1111
<definition name="SUPPORTED_POWERTOYS_0_64_0" displayName="$(string.SUPPORTED_POWERTOYS_0_64_0)"/>
@@ -28,6 +28,7 @@
2828
<definition name="SUPPORTED_POWERTOYS_0_90_0" displayName="$(string.SUPPORTED_POWERTOYS_0_90_0)"/>
2929
<definition name="SUPPORTED_POWERTOYS_0_96_0" displayName="$(string.SUPPORTED_POWERTOYS_0_96_0)"/>
3030
<definition name="SUPPORTED_POWERTOYS_0_97_0" displayName="$(string.SUPPORTED_POWERTOYS_0_97_0)"/>
31+
<definition name="SUPPORTED_POWERTOYS_0_98_0" displayName="$(string.SUPPORTED_POWERTOYS_0_98_0)"/>
3132
<definition name="SUPPORTED_POWERTOYS_0_64_0_TO_0_87_1" displayName="$(string.SUPPORTED_POWERTOYS_0_64_0_TO_0_87_1)"/>
3233
</definitions>
3334
</supportedOn>
@@ -826,5 +827,15 @@
826827
<decimal value="0" />
827828
</disabledValue>
828829
</policy>
830+
<policy name="NewPlusHideBuiltInNewContextMenu" class="Both" displayName="$(string.NewPlusHideBuiltInNewContextMenu)" explainText="$(string.NewPlusHideBuiltInNewContextMenuDescription)" key="Software\Policies\PowerToys" valueName="NewPlusHideBuiltInNewContextMenu">
831+
<parentCategory ref="NewPlus" />
832+
<supportedOn ref="SUPPORTED_POWERTOYS_0_98_0" />
833+
<enabledValue>
834+
<decimal value="1" />
835+
</enabledValue>
836+
<disabledValue>
837+
<decimal value="0" />
838+
</disabledValue>
839+
</policy>
829840
</policies>
830841
</policyDefinitions>

src/gpo/assets/en-US/PowerToys.adml

Lines changed: 11 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -35,6 +35,7 @@
3535
<string id="SUPPORTED_POWERTOYS_0_90_0">PowerToys version 0.90.0 or later</string>
3636
<string id="SUPPORTED_POWERTOYS_0_96_0">PowerToys version 0.96.0 or later</string>
3737
<string id="SUPPORTED_POWERTOYS_0_97_0">PowerToys version 0.97.0 or later</string>
38+
<string id="SUPPORTED_POWERTOYS_0_98_0">PowerToys version 0.98.0 or later</string>
3839
<string id="SUPPORTED_POWERTOYS_0_64_0_TO_0_87_1">From PowerToys version 0.64.0 until PowerToys version 0.87.1</string>
3940

4041
<string id="ConfigureAllUtilityGlobalEnabledStateDescription">This policy configures the enabled state for all PowerToys utilities.
@@ -238,7 +239,7 @@ If you disable this policy, the setting is disabled and variables in filenames w
238239

239240
If you don't configure this policy, the user will be able to control the setting and can enable or disable it.
240241
</string>
241-
242+
242243
<string id="ConfigureAllUtilityGlobalEnabledState">Configure global utility enabled state</string>
243244
<string id="ConfigureEnabledUtilityAdvancedPaste">Advanced Paste: Configure enabled state</string>
244245
<string id="ConfigureEnabledUtilityAlwaysOnTop">Always On Top: Configure enabled state</string>
@@ -356,6 +357,15 @@ If you disable this policy, users will not be able to select or use Foundry Loca
356357
<string id="AllowDiagnosticData">Allow sending diagnostic data</string>
357358
<string id="ConfigureRunAtStartup">Configure the run at startup setting</string>
358359
<string id="NewPlusReplaceVariablesInTemplateFilenames">Replace variables in template filenames</string>
360+
<string id="NewPlusHideBuiltInNewContextMenu">Hide the built-in "New" context menu</string>
361+
<string id="NewPlusHideBuiltInNewContextMenuDescription">This policy configures if Windows' built-in New context menu should be hidden on the context menu.
362+
363+
If you enable this policy, then the built-in New context menu will be hidden, and user can only create new files and folders using New+ and the explorer toolbar New button.
364+
365+
If you disable this policy, then the build-in New context menu will be displayed as normal in Windows.
366+
367+
If you don't configure this policy, the user will be able to control the setting and can enable or disable it.
368+
</string>
359369
</stringTable>
360370

361371
<presentationTable>
@@ -369,4 +379,3 @@ If you disable this policy, users will not be able to select or use Foundry Loca
369379

370380
</resources>
371381
</policyDefinitionResources>
372-

0 commit comments

Comments
 (0)