/ src / runner / general_settings.cpp
general_settings.cpp
  1  #include "pch.h"
  2  #include "general_settings.h"
  3  #include "auto_start_helper.h"
  4  #include "tray_icon.h"
  5  #include "quick_access_host.h"
  6  #include "Generated files/resource.h"
  7  #include "hotkey_conflict_detector.h"
  8  
  9  #include <common/SettingsAPI/settings_helpers.h>
 10  #include "powertoy_module.h"
 11  #include <common/themes/windows_colors.h>
 12  
 13  #include "trace.h"
 14  #include "ai_detection.h"
 15  #include <common/utils/elevation.h>
 16  #include <common/version/version.h>
 17  #include <common/utils/resources.h>
 18  
 19  namespace
 20  {
 21      json::JsonValue create_empty_shortcut_array_value()
 22      {
 23          return json::JsonValue::Parse(L"[]");
 24      }
 25  
 26      void ensure_ignored_conflict_properties_shape(json::JsonObject& obj)
 27      {
 28          if (!json::has(obj, L"ignored_shortcuts", json::JsonValueType::Array))
 29          {
 30              obj.SetNamedValue(L"ignored_shortcuts", create_empty_shortcut_array_value());
 31          }
 32      }
 33  
 34      json::JsonObject create_default_ignored_conflict_properties()
 35      {
 36          json::JsonObject obj;
 37          ensure_ignored_conflict_properties_shape(obj);
 38          return obj;
 39      }
 40  
 41      DashboardSortOrder parse_dashboard_sort_order(const json::JsonObject& obj, DashboardSortOrder fallback)
 42      {
 43          if (json::has(obj, L"dashboard_sort_order", json::JsonValueType::Number))
 44          {
 45              const auto raw_value = static_cast<int>(obj.GetNamedNumber(L"dashboard_sort_order", static_cast<double>(static_cast<int>(fallback))));
 46              return raw_value == static_cast<int>(DashboardSortOrder::ByStatus) ? DashboardSortOrder::ByStatus : DashboardSortOrder::Alphabetical;
 47          }
 48  
 49          if (json::has(obj, L"dashboard_sort_order", json::JsonValueType::String))
 50          {
 51              const auto raw = obj.GetNamedString(L"dashboard_sort_order");
 52              if (raw == L"ByStatus")
 53              {
 54                  return DashboardSortOrder::ByStatus;
 55              }
 56  
 57              if (raw == L"Alphabetical")
 58              {
 59                  return DashboardSortOrder::Alphabetical;
 60              }
 61          }
 62  
 63          return fallback;
 64      }
 65  }
 66  
 67  // TODO: would be nice to get rid of these globals, since they're basically cached json settings
 68  static std::wstring settings_theme = L"system";
 69  static bool show_tray_icon = true;
 70  static bool show_theme_adaptive_tray_icon = false;
 71  static bool run_as_elevated = false;
 72  static bool show_new_updates_toast_notification = true;
 73  static bool download_updates_automatically = true;
 74  static bool show_whats_new_after_updates = true;
 75  static bool enable_experimentation = true;
 76  static bool enable_warnings_elevated_apps = true;
 77  static bool enable_quick_access = true;
 78  static PowerToysSettings::HotkeyObject quick_access_shortcut;
 79  static DashboardSortOrder dashboard_sort_order = DashboardSortOrder::Alphabetical;
 80  static json::JsonObject ignored_conflict_properties = create_default_ignored_conflict_properties();
 81  
 82  json::JsonObject GeneralSettings::to_json()
 83  {
 84      json::JsonObject result;
 85  
 86      auto ignoredProps = ignoredConflictProperties;
 87      ensure_ignored_conflict_properties_shape(ignoredProps);
 88  
 89      result.SetNamedValue(L"startup", json::value(isStartupEnabled));
 90      if (!startupDisabledReason.empty())
 91      {
 92          result.SetNamedValue(L"startup_disabled_reason", json::value(startupDisabledReason));
 93      }
 94  
 95      json::JsonObject enabled;
 96      for (const auto& [name, isEnabled] : isModulesEnabledMap)
 97      {
 98          enabled.SetNamedValue(name, json::value(isEnabled));
 99      }
100      result.SetNamedValue(L"enabled", std::move(enabled));
101  
102      result.SetNamedValue(L"show_tray_icon", json::value(showSystemTrayIcon));
103      result.SetNamedValue(L"show_theme_adaptive_tray_icon", json::value(showThemeAdaptiveTrayIcon));
104      result.SetNamedValue(L"is_elevated", json::value(isElevated));
105      result.SetNamedValue(L"run_elevated", json::value(isRunElevated));
106      result.SetNamedValue(L"show_new_updates_toast_notification", json::value(showNewUpdatesToastNotification));
107      result.SetNamedValue(L"download_updates_automatically", json::value(downloadUpdatesAutomatically));
108      result.SetNamedValue(L"show_whats_new_after_updates", json::value(showWhatsNewAfterUpdates));
109      result.SetNamedValue(L"enable_experimentation", json::value(enableExperimentation));
110      result.SetNamedValue(L"dashboard_sort_order", json::value(static_cast<int>(dashboardSortOrder)));
111      result.SetNamedValue(L"is_admin", json::value(isAdmin));
112      result.SetNamedValue(L"enable_warnings_elevated_apps", json::value(enableWarningsElevatedApps));
113      result.SetNamedValue(L"enable_quick_access", json::value(enableQuickAccess));
114      result.SetNamedValue(L"quick_access_shortcut", quickAccessShortcut.get_json());
115      result.SetNamedValue(L"theme", json::value(theme));
116      result.SetNamedValue(L"system_theme", json::value(systemTheme));
117      result.SetNamedValue(L"powertoys_version", json::value(powerToysVersion));
118      result.SetNamedValue(L"ignored_conflict_properties", json::value(ignoredProps));
119  
120      return result;
121  }
122  
123  json::JsonObject load_general_settings()
124  {
125      auto loaded = PTSettingsHelper::load_general_settings();
126      settings_theme = loaded.GetNamedString(L"theme", L"system");
127      if (settings_theme != L"dark" && settings_theme != L"light")
128      {
129          settings_theme = L"system";
130      }
131      show_tray_icon = loaded.GetNamedBoolean(L"show_tray_icon", true);
132      show_theme_adaptive_tray_icon = loaded.GetNamedBoolean(L"show_theme_adaptive_tray_icon", false);
133      run_as_elevated = loaded.GetNamedBoolean(L"run_elevated", false);
134      show_new_updates_toast_notification = loaded.GetNamedBoolean(L"show_new_updates_toast_notification", true);
135      download_updates_automatically = loaded.GetNamedBoolean(L"download_updates_automatically", true) && check_user_is_admin();
136      show_whats_new_after_updates = loaded.GetNamedBoolean(L"show_whats_new_after_updates", true);
137      enable_experimentation = loaded.GetNamedBoolean(L"enable_experimentation", true);
138      enable_warnings_elevated_apps = loaded.GetNamedBoolean(L"enable_warnings_elevated_apps", true);
139      enable_quick_access = loaded.GetNamedBoolean(L"enable_quick_access", true);
140      if (json::has(loaded, L"quick_access_shortcut", json::JsonValueType::Object))
141      {
142          quick_access_shortcut = PowerToysSettings::HotkeyObject::from_json(loaded.GetNamedObject(L"quick_access_shortcut"));
143      }
144      dashboard_sort_order = parse_dashboard_sort_order(loaded, dashboard_sort_order);
145  
146      if (json::has(loaded, L"ignored_conflict_properties", json::JsonValueType::Object))
147      {
148          ignored_conflict_properties = loaded.GetNamedObject(L"ignored_conflict_properties");
149      }
150      else
151      {
152          ignored_conflict_properties = create_default_ignored_conflict_properties();
153      }
154  
155      ensure_ignored_conflict_properties_shape(ignored_conflict_properties);
156  
157      return loaded;
158  }
159  
160  GeneralSettings get_general_settings()
161  {
162      const bool is_user_admin = check_user_is_admin();
163      GeneralSettings settings
164      {
165          .showSystemTrayIcon = show_tray_icon,
166          .showThemeAdaptiveTrayIcon = show_theme_adaptive_tray_icon,
167          .isElevated = is_process_elevated(),
168          .isRunElevated = run_as_elevated,
169          .isAdmin = is_user_admin,
170          .enableWarningsElevatedApps = enable_warnings_elevated_apps,
171          .enableQuickAccess = enable_quick_access,
172          .quickAccessShortcut = quick_access_shortcut,
173          .showNewUpdatesToastNotification = show_new_updates_toast_notification,
174          .downloadUpdatesAutomatically = download_updates_automatically && is_user_admin,
175          .showWhatsNewAfterUpdates = show_whats_new_after_updates,
176          .enableExperimentation = enable_experimentation,
177      .dashboardSortOrder = dashboard_sort_order,
178          .theme = settings_theme,
179          .systemTheme = WindowsColors::is_dark_mode() ? L"dark" : L"light",
180          .powerToysVersion = get_product_version(),
181          .ignoredConflictProperties = ignored_conflict_properties
182      };
183  
184      ensure_ignored_conflict_properties_shape(settings.ignoredConflictProperties);
185  
186      settings.isStartupEnabled = is_auto_start_task_active_for_this_user();
187  
188      for (auto& [name, powertoy] : modules())
189      {
190          settings.isModulesEnabledMap[name] = powertoy->is_enabled();
191      }
192  
193      return settings;
194  }
195  
196  void apply_module_status_update(const json::JsonObject& module_config, bool save)
197  {
198      Logger::info(L"apply_module_status_update: {}", std::wstring{ module_config.ToString() });
199  
200      // Expected format: {"ModuleName": true/false} - only one module per update
201      auto iter = module_config.First();
202      if (!iter.HasCurrent())
203      {
204          Logger::warn(L"apply_module_status_update: Empty module config");
205          return;
206      }
207  
208      const auto& element = iter.Current();
209      const auto value = element.Value();
210      if (value.ValueType() != json::JsonValueType::Boolean)
211      {
212          Logger::warn(L"apply_module_status_update: Invalid value type for module status");
213          return;
214      }
215  
216      const std::wstring name{ element.Key().c_str() };
217      if (modules().find(name) == modules().end())
218      {
219          Logger::warn(L"apply_module_status_update: Module {} not found", name);
220          return;
221      }
222  
223      PowertoyModule& powertoy = modules().at(name);
224      const bool module_inst_enabled = powertoy->is_enabled();
225      bool target_enabled = value.GetBoolean();
226  
227      auto gpo_rule = powertoy->gpo_policy_enabled_configuration();
228      if (gpo_rule == powertoys_gpo::gpo_rule_configured_enabled || gpo_rule == powertoys_gpo::gpo_rule_configured_disabled)
229      {
230          // Apply the GPO Rule.
231          target_enabled = gpo_rule == powertoys_gpo::gpo_rule_configured_enabled;
232      }
233  
234      if (module_inst_enabled == target_enabled)
235      {
236          Logger::info(L"apply_module_status_update: Module {} already in target state {}", name, target_enabled);
237          return;
238      }
239  
240      if (target_enabled)
241      {
242          Logger::info(L"apply_module_status_update: Enabling powertoy {}", name);
243          powertoy->enable();
244          auto& hkmng = HotkeyConflictDetector::HotkeyConflictManager::GetInstance();
245          hkmng.EnableHotkeyByModule(name);
246  
247          // Trigger AI capability detection when ImageResizer is enabled
248          if (name == L"Image Resizer")
249          {
250              Logger::info(L"ImageResizer enabled, triggering AI capability detection");
251              DetectAiCapabilitiesAsync(true);  // Skip settings check since we know it's being enabled
252          }
253      }
254      else
255      {
256          Logger::info(L"apply_module_status_update: Disabling powertoy {}", name);
257          powertoy->disable();
258          auto& hkmng = HotkeyConflictDetector::HotkeyConflictManager::GetInstance();
259          hkmng.DisableHotkeyByModule(name);
260      }
261      // Sync the hotkey state with the module state, so it can be removed for disabled modules.
262      powertoy.UpdateHotkeyEx();
263  
264      if (save)
265      {
266          // Load existing settings and only update the specific module's enabled state
267          json::JsonObject current_settings = PTSettingsHelper::load_general_settings();
268          
269          json::JsonObject enabled;
270          if (current_settings.HasKey(L"enabled"))
271          {
272              enabled = current_settings.GetNamedObject(L"enabled");
273          }
274          
275          // Check if the saved state is different from the requested state
276          bool current_saved = enabled.HasKey(name) ? enabled.GetNamedBoolean(name, true) : true;
277          
278          if (current_saved != target_enabled)
279          {
280              // Update only this module's enabled state
281              enabled.SetNamedValue(name, json::value(target_enabled));
282              current_settings.SetNamedValue(L"enabled", enabled);
283              
284              PTSettingsHelper::save_general_settings(current_settings);
285              
286              GeneralSettings settings_for_trace = get_general_settings();
287              Trace::SettingsChanged(settings_for_trace);
288          }
289      }
290  }
291  
292  void apply_general_settings(const json::JsonObject& general_configs, bool save)
293  {
294      std::wstring old_settings_json_string;
295      if (save)
296      {
297          old_settings_json_string = get_general_settings().to_json().Stringify().c_str();
298      }
299  
300      Logger::info(L"apply_general_settings: {}", std::wstring{ general_configs.ToString() });
301      run_as_elevated = general_configs.GetNamedBoolean(L"run_elevated", false);
302  
303      enable_warnings_elevated_apps = general_configs.GetNamedBoolean(L"enable_warnings_elevated_apps", true);
304  
305      bool new_enable_quick_access = general_configs.GetNamedBoolean(L"enable_quick_access", true);
306      Logger::info(L"apply_general_settings: enable_quick_access={}, new_enable_quick_access={}", enable_quick_access, new_enable_quick_access);
307  
308      PowerToysSettings::HotkeyObject new_quick_access_shortcut;
309      if (json::has(general_configs, L"quick_access_shortcut", json::JsonValueType::Object))
310      {
311          new_quick_access_shortcut = PowerToysSettings::HotkeyObject::from_json(general_configs.GetNamedObject(L"quick_access_shortcut"));
312      }
313  
314      auto hotkey_equals = [](const PowerToysSettings::HotkeyObject& a, const PowerToysSettings::HotkeyObject& b) {
315          return a.get_code() == b.get_code() &&
316                 a.get_modifiers() == b.get_modifiers();
317      };
318  
319      if (enable_quick_access != new_enable_quick_access || !hotkey_equals(quick_access_shortcut, new_quick_access_shortcut))
320      {
321          enable_quick_access = new_enable_quick_access;
322          quick_access_shortcut = new_quick_access_shortcut;
323  
324          if (enable_quick_access)
325          {
326              QuickAccessHost::start();
327          }
328          else
329          {
330              QuickAccessHost::stop();
331          }
332          update_quick_access_hotkey(enable_quick_access, quick_access_shortcut);
333      }
334  
335      show_new_updates_toast_notification = general_configs.GetNamedBoolean(L"show_new_updates_toast_notification", true);
336  
337      download_updates_automatically = general_configs.GetNamedBoolean(L"download_updates_automatically", true);
338      show_whats_new_after_updates = general_configs.GetNamedBoolean(L"show_whats_new_after_updates", true);
339  
340      enable_experimentation = general_configs.GetNamedBoolean(L"enable_experimentation", true);
341      dashboard_sort_order = parse_dashboard_sort_order(general_configs, dashboard_sort_order);
342  
343      // apply_general_settings is called by the runner's WinMain, so we can just force the run at startup gpo rule here.
344      auto gpo_run_as_startup = powertoys_gpo::getConfiguredRunAtStartupValue();
345  
346      if (json::has(general_configs, L"startup", json::JsonValueType::Boolean))
347      {
348          bool startup = general_configs.GetNamedBoolean(L"startup");
349  
350          if (gpo_run_as_startup == powertoys_gpo::gpo_rule_configured_enabled)
351          {
352              startup = true;
353          }
354          else if (gpo_run_as_startup == powertoys_gpo::gpo_rule_configured_disabled)
355          {
356              startup = false;
357          }
358  
359          if (startup)
360          {
361              if (is_process_elevated())
362              {
363                  delete_auto_start_task_for_this_user();
364                  create_auto_start_task_for_this_user(run_as_elevated);
365              }
366              else
367              {
368                  if (!is_auto_start_task_active_for_this_user())
369                  {
370                      delete_auto_start_task_for_this_user();
371                      create_auto_start_task_for_this_user(false);
372  
373                      run_as_elevated = false;
374                  }
375                  else if (!general_configs.GetNamedBoolean(L"run_elevated", false))
376                  {
377                      delete_auto_start_task_for_this_user();
378                      create_auto_start_task_for_this_user(false);
379                  }
380              }
381          }
382          else
383          {
384              delete_auto_start_task_for_this_user();
385          }
386      }
387      else
388      {
389          delete_auto_start_task_for_this_user();
390          if (gpo_run_as_startup == powertoys_gpo::gpo_rule_configured_enabled || gpo_run_as_startup == powertoys_gpo::gpo_rule_configured_not_configured)
391          {
392              create_auto_start_task_for_this_user(run_as_elevated);
393          }
394      }
395  
396      if (json::has(general_configs, L"enabled"))
397      {
398          for (const auto& enabled_element : general_configs.GetNamedObject(L"enabled"))
399          {
400              const auto value = enabled_element.Value();
401              if (value.ValueType() != json::JsonValueType::Boolean)
402              {
403                  continue;
404              }
405              const std::wstring name{ enabled_element.Key().c_str() };
406              const bool found = modules().find(name) != modules().end();
407              if (!found)
408              {
409                  continue;
410              }
411              PowertoyModule& powertoy = modules().at(name);
412              const bool module_inst_enabled = powertoy->is_enabled();
413              bool target_enabled = value.GetBoolean();
414  
415              auto gpo_rule = powertoy->gpo_policy_enabled_configuration();
416              if (gpo_rule == powertoys_gpo::gpo_rule_configured_enabled || gpo_rule == powertoys_gpo::gpo_rule_configured_disabled)
417              {
418                  // Apply the GPO Rule.
419                  target_enabled = gpo_rule == powertoys_gpo::gpo_rule_configured_enabled;
420              }
421  
422              if (module_inst_enabled == target_enabled)
423              {
424                  continue;
425              }
426              if (target_enabled)
427              {
428                  Logger::info(L"apply_general_settings: Enabling powertoy {}", name);
429                  powertoy->enable();
430                  auto& hkmng = HotkeyConflictDetector::HotkeyConflictManager::GetInstance();
431                  hkmng.EnableHotkeyByModule(name);
432  
433                  // Trigger AI capability detection when ImageResizer is enabled
434                  if (name == L"Image Resizer")
435                  {
436                      Logger::info(L"ImageResizer enabled, triggering AI capability detection");
437                      DetectAiCapabilitiesAsync(true);  // Skip settings check since we know it's being enabled
438                  }
439              }
440              else
441              {
442                  Logger::info(L"apply_general_settings: Disabling powertoy {}", name);
443                  powertoy->disable();
444                  auto& hkmng = HotkeyConflictDetector::HotkeyConflictManager::GetInstance();
445                  hkmng.DisableHotkeyByModule(name);
446              }
447              // Sync the hotkey state with the module state, so it can be removed for disabled modules.
448              powertoy.UpdateHotkeyEx();
449          }
450      }
451  
452      if (json::has(general_configs, L"theme", json::JsonValueType::String))
453      {
454          settings_theme = general_configs.GetNamedString(L"theme");
455      }
456  
457      if (json::has(general_configs, L"show_tray_icon", json::JsonValueType::Boolean))
458      {
459          show_tray_icon = general_configs.GetNamedBoolean(L"show_tray_icon");
460          set_tray_icon_visible(show_tray_icon);
461      }
462  
463      if (json::has(general_configs, L"show_theme_adaptive_tray_icon", json::JsonValueType::Boolean))
464      {
465          bool new_theme_adaptive = general_configs.GetNamedBoolean(L"show_theme_adaptive_tray_icon");
466          Logger::info(L"apply_general_settings: show_theme_adaptive_tray_icon current={}, new={}",
467                       show_theme_adaptive_tray_icon, new_theme_adaptive);
468          if (show_theme_adaptive_tray_icon != new_theme_adaptive)
469          {
470              show_theme_adaptive_tray_icon = new_theme_adaptive;
471              set_tray_icon_theme_adaptive(show_theme_adaptive_tray_icon);
472          }
473          else
474          {
475              Logger::info(L"apply_general_settings: show_theme_adaptive_tray_icon unchanged, skipping update");
476          }
477      }
478      else
479      {
480          Logger::warn(L"apply_general_settings: show_theme_adaptive_tray_icon not found in config");
481      }
482  
483      if (json::has(general_configs, L"ignored_conflict_properties", json::JsonValueType::Object))
484      {
485          ignored_conflict_properties = general_configs.GetNamedObject(L"ignored_conflict_properties");
486          ensure_ignored_conflict_properties_shape(ignored_conflict_properties);
487      }
488  
489      if (save)
490      {
491          GeneralSettings save_settings = get_general_settings();
492          std::wstring new_settings_json_string = save_settings.to_json().Stringify().c_str();
493          if (old_settings_json_string != new_settings_json_string)
494          {
495              PTSettingsHelper::save_general_settings(save_settings.to_json());
496              Trace::SettingsChanged(save_settings);
497          }
498      }
499  }
500  
501  void start_enabled_powertoys()
502  {
503      std::unordered_set<std::wstring> powertoys_to_disable;
504      std::unordered_map<std::wstring, powertoys_gpo::gpo_rule_configured_t> powertoys_gpo_configuration;
505      // Take into account default values supplied by modules themselves and gpo configurations
506      for (auto& [name, powertoy] : modules())
507      {
508          auto gpo_rule = powertoy->gpo_policy_enabled_configuration();
509          powertoys_gpo_configuration[name] = gpo_rule;
510          if (gpo_rule == powertoys_gpo::gpo_rule_configured_unavailable)
511          {
512              Logger::warn(L"start_enabled_powertoys: couldn't read the gpo rule for Powertoy {}", name);
513          }
514          if (gpo_rule == powertoys_gpo::gpo_rule_configured_wrong_value)
515          {
516              Logger::warn(L"start_enabled_powertoys: gpo rule for Powertoy {} is set to an unknown value", name);
517          }
518  
519          if (!powertoy->is_enabled_by_default())
520              powertoys_to_disable.emplace(name);
521      }
522  
523      json::JsonObject general_settings;
524      try
525      {
526          general_settings = load_general_settings();
527          if (general_settings.HasKey(L"enabled"))
528          {
529              json::JsonObject enabled = general_settings.GetNamedObject(L"enabled");
530              for (const auto& disabled_element : enabled)
531              {
532                  std::wstring disable_module_name{ static_cast<std::wstring_view>(disabled_element.Key()) };
533  
534                  if (powertoys_gpo_configuration.find(disable_module_name) != powertoys_gpo_configuration.end() && (powertoys_gpo_configuration[disable_module_name] == powertoys_gpo::gpo_rule_configured_enabled || powertoys_gpo_configuration[disable_module_name] == powertoys_gpo::gpo_rule_configured_disabled))
535                  {
536                      // If gpo forces the enabled setting, no need to check the setting for this PowerToy. It will be applied later on this function.
537                      continue;
538                  }
539  
540                  // Disable explicitly disabled modules
541                  if (!disabled_element.Value().GetBoolean())
542                  {
543                      Logger::info(L"start_enabled_powertoys: Powertoy {} explicitly disabled", disable_module_name);
544                      powertoys_to_disable.emplace(std::move(disable_module_name));
545                  }
546                  // If module was scheduled for disable, but it's enabled in the settings - override default value
547                  else if (auto it = powertoys_to_disable.find(disable_module_name); it != end(powertoys_to_disable))
548                  {
549                      Logger::info(L"start_enabled_powertoys: Overriding default enabled value for {} powertoy", disable_module_name);
550                      powertoys_to_disable.erase(it);
551                  }
552              }
553          }
554      }
555      catch (...)
556      {
557      }
558  
559      for (auto& [name, powertoy] : modules())
560      {
561          bool should_powertoy_be_enabled = true;
562  
563          auto gpo_rule = powertoys_gpo_configuration.find(name) != powertoys_gpo_configuration.end() ? powertoys_gpo_configuration[name] : powertoys_gpo::gpo_rule_configured_not_configured;
564  
565          if (gpo_rule == powertoys_gpo::gpo_rule_configured_enabled || gpo_rule == powertoys_gpo::gpo_rule_configured_disabled)
566          {
567              // Apply the GPO Rule.
568              should_powertoy_be_enabled = gpo_rule == powertoys_gpo::gpo_rule_configured_enabled;
569              Logger::info(L"start_enabled_powertoys: GPO sets the enabled state for {} powertoy as {}", name, should_powertoy_be_enabled);
570          }
571          else if (powertoys_to_disable.contains(name))
572          {
573              // Apply the settings or default information provided by the PowerToy on first run.
574              should_powertoy_be_enabled = false;
575          }
576  
577          if (should_powertoy_be_enabled)
578          {
579              Logger::info(L"start_enabled_powertoys: Enabling powertoy {}", name);
580              powertoy->enable();
581              auto& hkmng = HotkeyConflictDetector::HotkeyConflictManager::GetInstance();
582              hkmng.EnableHotkeyByModule(name);
583              powertoy.UpdateHotkeyEx();
584          }
585      }
586  }
587  
588