diff --git a/doc/gpo/README.md b/doc/gpo/README.md index dc4f6a4b6f..134679f147 100644 --- a/doc/gpo/README.md +++ b/doc/gpo/README.md @@ -39,3 +39,35 @@ This policy configures whether PowerToys experimentation is allowed. With experi If this setting is not configured or enabled, the user can control experimentation in the PowerToys settings menu. If this setting is disabled, experimentation is not allowed. + +If this setting is not configured, experimentation is allowed. + +### Installer and Updates + +#### Disable automatic downloads + +This policy configures whether automatic downloads of available updates are disabled or not. (On metered connections updates are never downloaded.) + +If enabled, automatic downloads are disabled. + +If disabled or not configured, the user is in control of automatic downloads setting. + +#### Suspend Action Center notification for new updates + +This policy configures whether the action center notification for new updates is suspended for 2 minor releases. (Example: if the installed version is v0.60.0, then the next notification is shown for the v0.63.* release.) + +If enabled, the notification is suspended. + +If disabled or not configured, the notification is shown. + +Note: The notification about new major versions is always displayed. + + diff --git a/src/common/GPOWrapper/GPOWrapper.cpp b/src/common/GPOWrapper/GPOWrapper.cpp index 09327b9c31..95e228ec3e 100644 --- a/src/common/GPOWrapper/GPOWrapper.cpp +++ b/src/common/GPOWrapper/GPOWrapper.cpp @@ -120,6 +120,10 @@ namespace winrt::PowerToys::GPOWrapper::implementation { return static_cast(powertoys_gpo::getConfiguredVideoConferenceMuteEnabledValue()); } + GpoRuleConfigured GPOWrapper::GetDisableAutomaticUpdateDownloadValue() + { + return static_cast(powertoys_gpo::getDisableAutomaticUpdateDownloadValue()); + } GpoRuleConfigured GPOWrapper::GetAllowExperimentationValue() { return static_cast(powertoys_gpo::getAllowExperimentationValue()); diff --git a/src/common/GPOWrapper/GPOWrapper.h b/src/common/GPOWrapper/GPOWrapper.h index 0ca33d1224..3a0ca75ace 100644 --- a/src/common/GPOWrapper/GPOWrapper.h +++ b/src/common/GPOWrapper/GPOWrapper.h @@ -36,6 +36,7 @@ namespace winrt::PowerToys::GPOWrapper::implementation static GpoRuleConfigured GetConfiguredTextExtractorEnabledValue(); static GpoRuleConfigured GetConfiguredPastePlainEnabledValue(); static GpoRuleConfigured GetConfiguredVideoConferenceMuteEnabledValue(); + static GpoRuleConfigured GetDisableAutomaticUpdateDownloadValue(); static GpoRuleConfigured GetAllowExperimentationValue(); }; } diff --git a/src/common/GPOWrapper/GPOWrapper.idl b/src/common/GPOWrapper/GPOWrapper.idl index 2b9f631cc7..5ab4744702 100644 --- a/src/common/GPOWrapper/GPOWrapper.idl +++ b/src/common/GPOWrapper/GPOWrapper.idl @@ -40,6 +40,7 @@ namespace PowerToys static GpoRuleConfigured GetConfiguredTextExtractorEnabledValue(); static GpoRuleConfigured GetConfiguredPastePlainEnabledValue(); static GpoRuleConfigured GetConfiguredVideoConferenceMuteEnabledValue(); + static GpoRuleConfigured GetDisableAutomaticUpdateDownloadValue(); static GpoRuleConfigured GetAllowExperimentationValue(); } } diff --git a/src/common/utils/gpo.h b/src/common/utils/gpo.h index 3414129b81..4e54aeda3d 100644 --- a/src/common/utils/gpo.h +++ b/src/common/utils/gpo.h @@ -48,6 +48,13 @@ namespace powertoys_gpo { const std::wstring POLICY_CONFIGURE_ENABLED_TEXT_EXTRACTOR = L"ConfigureEnabledUtilityTextExtractor"; const std::wstring POLICY_CONFIGURE_ENABLED_PASTE_PLAIN = L"ConfigureEnabledUtilityPastePlain"; const std::wstring POLICY_CONFIGURE_ENABLED_VIDEO_CONFERENCE_MUTE = L"ConfigureEnabledUtilityVideoConferenceMute"; + + // The registry value names for PowerToys installer and update policies. + const std::wstring POLICY_DISABLE_AUTOMATIC_UPDATE_DOWNLOAD = L"AutomaticUpdateDownloadDisabled"; + const std::wstring POLICY_SUSPEND_NEW_UPDATE_TOAST = L"SuspendNewUpdateAvailableToast"; + const std::wstring POLICY_DISABLE_PERIODIC_UPDATE_CHECK = L"PeriodicUpdateCheckDisabled"; + + // The registry value names for other PowerToys policies. const std::wstring POLICY_ALLOW_EXPERIMENTATION = L"AllowExperimentation"; inline gpo_rule_configured_t getConfiguredValue(const std::wstring& registry_value_name) @@ -248,6 +255,21 @@ namespace powertoys_gpo { return getConfiguredValue(POLICY_CONFIGURE_ENABLED_VIDEO_CONFERENCE_MUTE); } + inline gpo_rule_configured_t getDisableAutomaticUpdateDownloadValue() + { + return getConfiguredValue(POLICY_DISABLE_AUTOMATIC_UPDATE_DOWNLOAD); + } + + inline gpo_rule_configured_t getSuspendNewUpdateToastValue() + { + return getConfiguredValue(POLICY_SUSPEND_NEW_UPDATE_TOAST); + } + + inline gpo_rule_configured_t getDisablePeriodicUpdateCheckValue() + { + return getConfiguredValue(POLICY_DISABLE_PERIODIC_UPDATE_CHECK); + } + inline gpo_rule_configured_t getAllowExperimentationValue() { return getConfiguredValue(POLICY_ALLOW_EXPERIMENTATION); diff --git a/src/gpo/assets/PowerToys.admx b/src/gpo/assets/PowerToys.admx index 9ccf25b0a2..ef5b2c015d 100644 --- a/src/gpo/assets/PowerToys.admx +++ b/src/gpo/assets/PowerToys.admx @@ -13,7 +13,9 @@ - + + + @@ -307,6 +309,38 @@ + + + + + + + + + + + + + + + + + + + + + diff --git a/src/gpo/assets/en-US/PowerToys.adml b/src/gpo/assets/en-US/PowerToys.adml index 25ea233de6..d86fbf9a95 100644 --- a/src/gpo/assets/en-US/PowerToys.adml +++ b/src/gpo/assets/en-US/PowerToys.adml @@ -7,6 +7,7 @@ Microsoft PowerToys + Installer and Updates PowerToys version 0.64.0 or later PowerToys version 0.68.0 or later @@ -28,6 +29,26 @@ If you enable this setting, the utility will be always enabled and the user won' If you disable this setting, the utility will be always disabled and the user won't be able to enable it. If you don't configure this setting, users are able to disable or enable the utility. + + This policy configures whether automatic downloads of available updates are disabled or not. (On metered connections updates are never downloaded.) + +If enabled, automatic downloads are disabled. + +If disabled or not configured, the user is in control of automatic downloads setting. + + This policy configures whether the action center notification for new updates is suspended for 2 minor releases. (Example: if the installed version is v0.60.0, then the next notification is shown for the v0.63.* release.) + +If enabled, the notification is suspended. + +If disabled or not configured, the notification is shown. + +Note: The notification about new major versions is always displayed. + + This policy allows you to disable automatic update checks running in the background. (The manual check in PT Settings is not affected by this policy.) + +If enabled, the automatic update checks are disabled. + +If disabled or not configured, the automatic update checks are enabled. This policy configures whether PowerToys experimentation is allowed. With experimentation allowed the user sees the new features being experimented if it gets selected as part of the test group. (Experimentation will only happen on Windows Insider builds.) @@ -64,6 +85,9 @@ If this setting is disabled, experimentation is not allowed. Shortcut Guide: Configure enabled state Text Extractor: Configure enabled state Video Conference Mute: Configure enabled state + Disable automatic downloads + Suspend Action Center notification for new updates + Disable automatic update checks Allow Experimentation diff --git a/src/runner/UpdateUtils.cpp b/src/runner/UpdateUtils.cpp index 8d46ced78c..5de6fa740f 100644 --- a/src/runner/UpdateUtils.cpp +++ b/src/runner/UpdateUtils.cpp @@ -6,6 +6,7 @@ #include "general_settings.h" #include "UpdateUtils.h" +#include #include #include #include @@ -21,6 +22,10 @@ namespace { constexpr int64_t UPDATE_CHECK_INTERVAL_MINUTES = 60 * 24; constexpr int64_t UPDATE_CHECK_AFTER_FAILED_INTERVAL_MINUTES = 60 * 2; + + // How many minor versions to suspend the toast notification (example: installed=0.60.0, suspend=2, next notification=0.63.*) + // Attention: When changing this value please update the ADML file to. + const int UPDATE_NOTIFICATION_TOAST_SUSPEND_MINOR_VERSION_COUNT = 2; } using namespace notifications; using namespace updating; @@ -113,7 +118,7 @@ bool IsMeteredConnection() void ProcessNewVersionInfo(const github_version_info& version_info, UpdateState& state, const bool download_update, - const bool show_notifications) + bool show_notifications) { state.githubUpdateLastCheckedDate.emplace(timeutil::now()); if (std::holds_alternative(version_info)) @@ -135,6 +140,22 @@ void ProcessNewVersionInfo(const github_version_info& version_info, return; } + // Check notification GPO. + // We check only if notifications are allowed. This is the case if we are triggered by the periodic check. + if (show_notifications && powertoys_gpo::getSuspendNewUpdateToastValue() == powertoys_gpo::gpo_rule_configured_enabled) + { + Logger::info(L"GPO to suspend new update toast notification is enabled."); + if (new_version_info.version.major <= VERSION_MAJOR && new_version_info.version.minor - VERSION_MINOR <= UPDATE_NOTIFICATION_TOAST_SUSPEND_MINOR_VERSION_COUNT) + { + Logger::info(L"The difference between the installed version and the newer version is within the allowed period. The toast notification is not shown."); + show_notifications = false; + } + else + { + Logger::info(L"The installed version is older than allowed for suspending the toast notification. The toast notification is shown."); + } + } + if (download_update) { Logger::trace(L"Downloading installer for a new version"); @@ -168,6 +189,14 @@ void ProcessNewVersionInfo(const github_version_info& version_info, void PeriodicUpdateWorker() { + // Check if periodic update check is disabled by GPO. + // This policy code is implemented but not active. It is for later usage in PT version after 1.0 release. + //if (powertoys_gpo::getDisablePeriodicUpdateCheckValue() == powertoys_gpo::gpo_rule_configured_enabled) + //{ + // Logger::info(L"Initialization of periodic update checks stopped. Periodic update checks are disabled by GPO."); + // return; + //} + for (;;) { auto state = UpdateState::read(); @@ -184,7 +213,14 @@ void PeriodicUpdateWorker() std::this_thread::sleep_for(std::chrono::minutes{ sleep_minutes_till_next_update }); - const bool download_update = !IsMeteredConnection() && get_general_settings().downloadUpdatesAutomatically; + // Auto download setting. + bool download_update = !IsMeteredConnection() && get_general_settings().downloadUpdatesAutomatically; + if (powertoys_gpo::getDisableAutomaticUpdateDownloadValue() == powertoys_gpo::gpo_rule_configured_enabled) + { + Logger::info(L"Automatic download of updates is disabled by GPO."); + download_update = false; + } + bool version_info_obtained = false; try { @@ -230,7 +266,15 @@ void CheckForUpdatesCallback() new_version_info = version_up_to_date{}; Logger::error(L"Couldn't obtain version info from github: {}", new_version_info.error()); } - const bool download_update = !IsMeteredConnection() && get_general_settings().downloadUpdatesAutomatically; + + // Auto download setting + bool download_update = !IsMeteredConnection() && get_general_settings().downloadUpdatesAutomatically; + if (powertoys_gpo::getDisableAutomaticUpdateDownloadValue() == powertoys_gpo::gpo_rule_configured_enabled) + { + Logger::info(L"Automatic download of updates is disabled by GPO."); + download_update = false; + } + ProcessNewVersionInfo(*new_version_info, state, download_update, false); UpdateState::store([&](UpdateState& v) { v = std::move(state); diff --git a/src/settings-ui/Settings.UI/Strings/en-us/Resources.resw b/src/settings-ui/Settings.UI/Strings/en-us/Resources.resw index 660077f0d8..1a51030002 100644 --- a/src/settings-ui/Settings.UI/Strings/en-us/Resources.resw +++ b/src/settings-ui/Settings.UI/Strings/en-us/Resources.resw @@ -3040,4 +3040,7 @@ Activate by holding the key for the character you want to add an accent to, then Enable Mouse Jump "Mouse Jump" is the name of the utility. + + The system administrator has disabled the automatic download of updates. + \ No newline at end of file diff --git a/src/settings-ui/Settings.UI/ViewModels/GeneralViewModel.cs b/src/settings-ui/Settings.UI/ViewModels/GeneralViewModel.cs index 9876249c10..db3ac314e2 100644 --- a/src/settings-ui/Settings.UI/ViewModels/GeneralViewModel.cs +++ b/src/settings-ui/Settings.UI/ViewModels/GeneralViewModel.cs @@ -142,6 +142,7 @@ namespace Microsoft.PowerToys.Settings.UI.ViewModels _updateCheckedDate = UpdatingSettingsConfig.LastCheckedDateLocalized; _experimentationIsGpoDisallowed = GPOWrapper.GetAllowExperimentationValue() == GpoRuleConfigured.Disabled; + _autoDownloadUpdatesIsGpoDisabled = GPOWrapper.GetDisableAutomaticUpdateDownloadValue() == GpoRuleConfigured.Enabled; if (dispatcherAction != null) { @@ -156,6 +157,7 @@ namespace Microsoft.PowerToys.Settings.UI.ViewModels private int _themeIndex; private bool _autoDownloadUpdates; + private bool _autoDownloadUpdatesIsGpoDisabled; private bool _enableExperimentation; private bool _experimentationIsGpoDisallowed; @@ -272,11 +274,20 @@ namespace Microsoft.PowerToys.Settings.UI.ViewModels } } + // Are we running a dev build? (Please note that we verify this in the code that gets the newest version from GitHub too.) + public static bool AutoUpdatesDisabledOnDevBuild + { + get + { + return Helper.GetProductVersion() == "v0.0.1"; + } + } + public bool AutoDownloadUpdates { get { - return _autoDownloadUpdates; + return _autoDownloadUpdates && !_autoDownloadUpdatesIsGpoDisabled; } set @@ -290,6 +301,18 @@ namespace Microsoft.PowerToys.Settings.UI.ViewModels } } + public bool IsAutoDownloadUpdatesCardEnabled + { + get => !AutoUpdatesDisabledOnDevBuild && !_autoDownloadUpdatesIsGpoDisabled; + } + + // The settings card is hidden for users who are not a member of the Administrators group and in this case the GPO info should be hidden too. + // We hide it, because we don't want a normal user to enable the setting. He can't install the updates. + public bool ShowAutoDownloadUpdatesGpoInformation + { + get => _isAdmin && _autoDownloadUpdatesIsGpoDisabled; + } + public bool EnableExperimentation { get @@ -313,14 +336,6 @@ namespace Microsoft.PowerToys.Settings.UI.ViewModels get => _experimentationIsGpoDisallowed; } - public static bool AutoUpdatesEnabled - { - get - { - return Helper.GetProductVersion() != "v0.0.1"; - } - } - public string SettingsBackupAndRestoreDir { get @@ -659,7 +674,7 @@ namespace Microsoft.PowerToys.Settings.UI.ViewModels { get { - return AutoUpdatesEnabled && !IsNewVersionDownloading; + return !AutoUpdatesDisabledOnDevBuild && !IsNewVersionDownloading; } } diff --git a/src/settings-ui/Settings.UI/Views/GeneralPage.xaml b/src/settings-ui/Settings.UI/Views/GeneralPage.xaml index e2b4bd33df..33ee9cefe1 100644 --- a/src/settings-ui/Settings.UI/Views/GeneralPage.xaml +++ b/src/settings-ui/Settings.UI/Views/GeneralPage.xaml @@ -190,12 +190,18 @@ +