[PTRun][Enterprise]GPO for plugin enabled state (#27468)
* try code for gpo with pluginID param * fix typo * fixes * update admx * Add second policy to admx * spelling fixes * admx clean up * add gpo code * small fixes * fixes * fix cast * update settings code * bug fixes * fix plugins disabled warning * Info bar in settings * settings ui fixes * code clean up * fix spelling * fix spelling * code optimization * changes * fix code * switch to char* * update comments * validate plugin ID * spell fixes * spell fixes * fix IPlugin interface * Update Directory.Packages.props hopefully fixes unit tests * revert change of nuget pkg * fixes * fix spell check * add todo comment * improve gpo.h * improve gpo.h * update gpo.h * clean up code in gpo.h * fix build * try to fix build * xaml fix * Fix getting string value from the registry * communicate policy state suing settings.json * various changes and gpo docs * spell fixes * PT Run: Policy handling * spell fix * fix logging * fix admx revision * revision fix 2 * review feedback 1 * review feedback 2 * dev docs update * fix typo
This commit is contained in:
Родитель
19827d0093
Коммит
602a3ff090
|
@ -20,6 +20,10 @@
|
|||
"IcoPathLight": string // Path to light theme icon. The path is relative to the root plugin folder
|
||||
}
|
||||
```
|
||||
- [ ] Make sure your `Main` class contains a public, static string property for the `PluginID`. The plugin id has to be the same as the one in the `plugin.json`file.
|
||||
```csharp
|
||||
public static string PluginID => "xxxxxxx"; // The part xxxxxxx stands for the plugin ID.
|
||||
```
|
||||
- [ ] Do not use plugin name or PowerToys as prefixes for entities inside of the plugin project
|
||||
- [ ] The plugin has to have Unit tests. Use MSTest framework
|
||||
- [ ] Plugin's output code and assets have to be included in the installer [`Product.wxs`](/installer/PowerToysSetup/Product.wxs)
|
||||
|
|
|
@ -94,3 +94,34 @@ If enabled, the automatic update checks are disabled.
|
|||
|
||||
If disabled or not configured, the automatic update checks are enabled.
|
||||
-->
|
||||
|
||||
### PowerToys Run
|
||||
|
||||
#### Configure enabled state for all plugins
|
||||
|
||||
This policy configures the enabled state for all PowerToys Run plugins. All plugins will have the same state.
|
||||
|
||||
If you enable this setting, the plugins will be always enabled and the user won't be able to disable it.
|
||||
|
||||
If you disable this setting, the plugins 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 plugins.
|
||||
|
||||
You can override this policy for individual plugins using the policy "Configure enabled state for individual plugins".
|
||||
|
||||
Note: Changes require a restart of PowerToys Run.
|
||||
|
||||
#### Configure enabled state for individual plugins
|
||||
|
||||
With this policy you can configures an individual enabled state for each PowerToys Run plugin that you add to the list.
|
||||
|
||||
If you enable this setting, you can define the list of plugins and their enabled states:
|
||||
- The value name (first column) is the plugin ID. You will find it in the plugin.json which is located in the plugin folder.
|
||||
- The value (second column) is a numeric value: 0 for disabled, 1 for enabled and 2 for user takes control.
|
||||
- Example to disable the Program plugin: `791FC278BA414111B8D1886DFE447410 | 0`
|
||||
|
||||
If you disable or don't configure this policy, either the user or the policy "Configure enabled state for all plugins" takes control over the enabled state of the plugins.
|
||||
|
||||
You can set the enabled state for all plugins not listed here using the policy "Configure enabled state for all plugins".
|
||||
|
||||
Note: Changes require a restart of PowerToys Run.
|
|
@ -144,4 +144,8 @@ namespace winrt::PowerToys::GPOWrapper::implementation
|
|||
{
|
||||
return static_cast<GpoRuleConfigured>(powertoys_gpo::getAllowExperimentationValue());
|
||||
}
|
||||
GpoRuleConfigured GPOWrapper::GetRunPluginEnabledValue(winrt::hstring const& pluginID)
|
||||
{
|
||||
return static_cast<GpoRuleConfigured>(powertoys_gpo::getRunPluginEnabledValue(winrt::to_string(pluginID)));
|
||||
}
|
||||
}
|
||||
|
|
|
@ -42,6 +42,7 @@ namespace winrt::PowerToys::GPOWrapper::implementation
|
|||
static GpoRuleConfigured GetConfiguredPeekEnabledValue();
|
||||
static GpoRuleConfigured GetDisableAutomaticUpdateDownloadValue();
|
||||
static GpoRuleConfigured GetAllowExperimentationValue();
|
||||
static GpoRuleConfigured GetRunPluginEnabledValue(winrt::hstring const& pluginID);
|
||||
};
|
||||
}
|
||||
|
||||
|
|
|
@ -46,6 +46,7 @@ namespace PowerToys
|
|||
static GpoRuleConfigured GetConfiguredPeekEnabledValue();
|
||||
static GpoRuleConfigured GetDisableAutomaticUpdateDownloadValue();
|
||||
static GpoRuleConfigured GetAllowExperimentationValue();
|
||||
static GpoRuleConfigured GetRunPluginEnabledValue(String pluginID);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -51,5 +51,10 @@ namespace PowerToys.GPOWrapperProjection
|
|||
{
|
||||
return (GpoRuleConfigured)PowerToys.GPOWrapper.GPOWrapper.GetConfiguredPeekEnabledValue();
|
||||
}
|
||||
|
||||
public static GpoRuleConfigured GetRunPluginEnabledValue(string pluginID)
|
||||
{
|
||||
return (GpoRuleConfigured)PowerToys.GPOWrapper.GPOWrapper.GetRunPluginEnabledValue(pluginID);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,6 +1,7 @@
|
|||
#pragma once
|
||||
|
||||
#include <Windows.h>
|
||||
#include <optional>
|
||||
|
||||
namespace powertoys_gpo {
|
||||
enum gpo_rule_configured_t {
|
||||
|
@ -13,6 +14,7 @@ namespace powertoys_gpo {
|
|||
|
||||
// Registry path where gpo policy values are stored.
|
||||
const std::wstring POLICIES_PATH = L"SOFTWARE\\Policies\\PowerToys";
|
||||
const std::wstring POWER_LAUNCHER_INDIVIDUAL_PLUGIN_ENABLED_LIST_PATH = POLICIES_PATH + L"\\PowerLauncherIndividualPluginEnabledList";
|
||||
|
||||
// Registry scope where gpo policy values are stored.
|
||||
const HKEY POLICIES_SCOPE_MACHINE = HKEY_LOCAL_MACHINE;
|
||||
|
@ -62,6 +64,39 @@ namespace powertoys_gpo {
|
|||
|
||||
// The registry value names for other PowerToys policies.
|
||||
const std::wstring POLICY_ALLOW_EXPERIMENTATION = L"AllowExperimentation";
|
||||
const std::wstring POLICY_CONFIGURE_ENABLED_POWER_LAUNCHER_ALL_PLUGINS = L"PowerLauncherAllPluginsEnabledState";
|
||||
|
||||
|
||||
inline std::optional<std::wstring> readRegistryStringValue(HKEY hRootKey, const std::wstring& subKey, const std::wstring& value_name)
|
||||
{
|
||||
DWORD reg_value_type = REG_SZ;
|
||||
DWORD reg_flags = RRF_RT_REG_SZ;
|
||||
|
||||
DWORD string_buffer_capacity;
|
||||
// Request required buffer capacity / string length
|
||||
if (RegGetValueW(hRootKey, subKey.c_str(), value_name.c_str(), reg_flags, ®_value_type, NULL, &string_buffer_capacity) != ERROR_SUCCESS)
|
||||
{
|
||||
return std::nullopt;
|
||||
}
|
||||
else if (string_buffer_capacity == 0)
|
||||
{
|
||||
return std::nullopt;
|
||||
}
|
||||
|
||||
// RegGetValueW overshoots sometimes. Use a buffer first to not have characters past the string end.
|
||||
wchar_t* temp_buffer = new wchar_t[string_buffer_capacity / sizeof(wchar_t) + 1];
|
||||
// Read string
|
||||
if (RegGetValueW(hRootKey, subKey.c_str(), value_name.c_str(), reg_flags, ®_value_type, temp_buffer, &string_buffer_capacity) != ERROR_SUCCESS)
|
||||
{
|
||||
delete temp_buffer;
|
||||
return std::nullopt;
|
||||
}
|
||||
|
||||
// Convert buffer to std::wstring, delete buffer and return REG_SZ value
|
||||
std::wstring string_value = temp_buffer;
|
||||
delete temp_buffer;
|
||||
return string_value;
|
||||
}
|
||||
|
||||
inline gpo_rule_configured_t getConfiguredValue(const std::wstring& registry_value_name)
|
||||
{
|
||||
|
@ -117,6 +152,51 @@ namespace powertoys_gpo {
|
|||
}
|
||||
}
|
||||
|
||||
inline std::optional<std::wstring> getPolicyListValue(const std::wstring& registry_list_path, const std::wstring& registry_list_value_name)
|
||||
{
|
||||
// This function returns the value of an entry of an policy list. The user scope is only checked, if the list is not enabled for the machine to not mix the lists.
|
||||
|
||||
HKEY key{};
|
||||
|
||||
// Try to read from the machine list.
|
||||
bool machine_list_found = false;
|
||||
if (RegOpenKeyExW(POLICIES_SCOPE_MACHINE, registry_list_path.c_str(), 0, KEY_READ, &key) == ERROR_SUCCESS)
|
||||
{
|
||||
machine_list_found = true;
|
||||
RegCloseKey(key);
|
||||
|
||||
// If the path exists in the machine registry, we try to read the value.
|
||||
auto regValueData = readRegistryStringValue(POLICIES_SCOPE_MACHINE, registry_list_path, registry_list_value_name);
|
||||
|
||||
if (regValueData.has_value())
|
||||
{
|
||||
// Return the value from the machine list.
|
||||
return *regValueData;
|
||||
}
|
||||
}
|
||||
|
||||
// If no list exists for machine, we try to read from the user list.
|
||||
if (!machine_list_found)
|
||||
{
|
||||
if (RegOpenKeyExW(POLICIES_SCOPE_USER, registry_list_path.c_str(), 0, KEY_READ, &key) == ERROR_SUCCESS)
|
||||
{
|
||||
RegCloseKey(key);
|
||||
|
||||
// If the path exists in the user registry, we try to read the value.
|
||||
auto regValueData = readRegistryStringValue(POLICIES_SCOPE_USER, registry_list_path, registry_list_value_name);
|
||||
|
||||
if (regValueData.has_value())
|
||||
{
|
||||
// Return the value from the user list.
|
||||
return *regValueData;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// No list exists for machine and user, or no value was found in the list, or an error ocurred while reading the value.
|
||||
return std::nullopt;
|
||||
}
|
||||
|
||||
inline gpo_rule_configured_t getUtilityEnabledValue(const std::wstring& utility_name)
|
||||
{
|
||||
auto individual_value = getConfiguredValue(utility_name);
|
||||
|
@ -321,4 +401,44 @@ namespace powertoys_gpo {
|
|||
return getConfiguredValue(POLICY_ALLOW_EXPERIMENTATION);
|
||||
}
|
||||
|
||||
inline gpo_rule_configured_t getRunPluginEnabledValue(std::string pluginID)
|
||||
{
|
||||
if (pluginID == "" || pluginID == " ")
|
||||
{
|
||||
// this plugin id can't exist in the registry
|
||||
return gpo_rule_configured_not_configured;
|
||||
}
|
||||
|
||||
std::wstring plugin_id(pluginID.begin(), pluginID.end());
|
||||
auto individual_plugin_setting = getPolicyListValue(POWER_LAUNCHER_INDIVIDUAL_PLUGIN_ENABLED_LIST_PATH, plugin_id);
|
||||
|
||||
if (individual_plugin_setting.has_value())
|
||||
{
|
||||
if (*individual_plugin_setting == L"0")
|
||||
{
|
||||
// force disabled
|
||||
return gpo_rule_configured_disabled;
|
||||
}
|
||||
else if (*individual_plugin_setting == L"1")
|
||||
{
|
||||
// force enabled
|
||||
return gpo_rule_configured_enabled;
|
||||
}
|
||||
else if (*individual_plugin_setting == L"2")
|
||||
{
|
||||
// user takes control
|
||||
return gpo_rule_configured_not_configured;
|
||||
}
|
||||
else
|
||||
{
|
||||
return gpo_rule_configured_wrong_value;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
// If no individual plugin policy exists, we check the policy with the setting for all plugins.
|
||||
return getConfiguredValue(POLICY_CONFIGURE_ENABLED_POWER_LAUNCHER_ALL_PLUGINS);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -20,6 +20,9 @@
|
|||
<category name="PowerToys" displayName="$(string.PowerToys)" />
|
||||
<category name="InstallerUpdates" displayName="$(string.InstallerUpdates)">
|
||||
<parentCategory ref="PowerToys" />
|
||||
</category>
|
||||
<category name="PowerToysRun" displayName="$(string.PowerToysRun)">
|
||||
<parentCategory ref="PowerToys" />
|
||||
</category>
|
||||
</categories>
|
||||
<policies>
|
||||
|
@ -416,6 +419,23 @@
|
|||
<disabledValue>
|
||||
<decimal value="0" />
|
||||
</disabledValue>
|
||||
</policy>
|
||||
<policy name="PowerToysRunAllPluginsEnabledState" class="Both" displayName="$(string.PowerToysRunAllPluginsEnabledState)" explainText="$(string.PowerToysRunAllPluginsEnabledStateDescription)" key="Software\Policies\PowerToys" valueName="PowerLauncherAllPluginsEnabledState">
|
||||
<parentCategory ref="PowerToysRun" />
|
||||
<supportedOn ref="SUPPORTED_POWERTOYS_0_75_0" />
|
||||
<enabledValue>
|
||||
<decimal value="1" />
|
||||
</enabledValue>
|
||||
<disabledValue>
|
||||
<decimal value="0" />
|
||||
</disabledValue>
|
||||
</policy>
|
||||
<policy name="PowerToysRunIndividualPluginEnabledState" class="Both" displayName="$(string.PowerToysRunIndividualPluginEnabledState)" explainText="$(string.PowerToysRunIndividualPluginEnabledStateDescription)" presentation="$(presentation.PowerToysRunIndividualPluginEnabledState)" key="Software\Policies\PowerToys\PowerLauncherIndividualPluginEnabledList">
|
||||
<parentCategory ref="PowerToysRun" />
|
||||
<supportedOn ref="SUPPORTED_POWERTOYS_0_75_0"/>
|
||||
<elements>
|
||||
<list id="PowerToysRunIndividualPluginEnabledList" explicitValue="true" />
|
||||
</elements>
|
||||
</policy>
|
||||
</policies>
|
||||
</policyDefinitions>
|
||||
|
|
|
@ -8,6 +8,7 @@
|
|||
<stringTable>
|
||||
<string id="PowerToys">Microsoft PowerToys</string>
|
||||
<string id="InstallerUpdates">Installer and Updates</string>
|
||||
<string id="PowerToysRun">PowerToys Run</string>
|
||||
|
||||
<string id="SUPPORTED_POWERTOYS_0_64_0">PowerToys version 0.64.0 or later</string>
|
||||
<string id="SUPPORTED_POWERTOYS_0_68_0">PowerToys version 0.68.0 or later</string>
|
||||
|
@ -80,6 +81,31 @@ If disabled or not configured, the automatic update checks are enabled.
|
|||
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.
|
||||
</string>
|
||||
<string id="PowerToysRunAllPluginsEnabledStateDescription">This policy configures the enabled state for all PowerToys Run plugins. All plugins will have the same state.
|
||||
|
||||
If you enable this setting, the plugins will be always enabled and the user won't be able to disable it.
|
||||
|
||||
If you disable this setting, the plugins 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 plugins.
|
||||
|
||||
You can override this policy for individual plugins using the policy "Configure enabled state for individual plugins".
|
||||
|
||||
Note: Changes require a restart of PowerToys Run.
|
||||
</string>
|
||||
<string id="PowerToysRunIndividualPluginEnabledStateDescription">With this policy you can configures an individual enabled state for each PowerToys Run plugin that you add to the list.
|
||||
|
||||
If you enable this setting, you can define the list of plugins and their enabled states:
|
||||
- The value name (first column) is the plugin ID. You will find it in the plugin.json which is located in the plugin folder.
|
||||
- The value (second column) is a numeric value: 0 for disabled, 1 for enabled and 2 for user takes control.
|
||||
- Example to disable the Program plugin: 791FC278BA414111B8D1886DFE447410 | 0
|
||||
|
||||
If you disable or don't configure this policy, either the user or the policy "Configure enabled state for all plugins" takes control over the enabled state of the plugins.
|
||||
|
||||
You can set the enabled state for all plugins not listed here using the policy "Configure enabled state for all plugins".
|
||||
|
||||
Note: Changes require a restart of PowerToys Run.
|
||||
</string>
|
||||
<string id="ConfigureGlobalUtilityEnabledState">Configure global utility enabled state</string>
|
||||
<string id="ConfigureEnabledUtilityAlwaysOnTop">Always On Top: Configure enabled state</string>
|
||||
|
@ -120,7 +146,16 @@ If this setting is disabled, experimentation is not allowed.
|
|||
<string id="SuspendNewUpdateToast">Suspend Action Center notification for new updates</string>
|
||||
<string id="DisablePeriodicUpdateCheck">Disable automatic update checks</string>
|
||||
<string id="AllowExperimentation">Allow Experimentation</string>
|
||||
<string id="PowerToysRunAllPluginsEnabledState">Configure enabled state for all plugins</string>
|
||||
<string id="PowerToysRunIndividualPluginEnabledState">Configure enabled state for individual plugins</string>
|
||||
</stringTable>
|
||||
|
||||
<presentationTable>
|
||||
<presentation id="PowerToysRunIndividualPluginEnabledState">
|
||||
<listBox refId="PowerToysRunIndividualPluginEnabledList">List of managed plugins:</listBox>
|
||||
</presentation>
|
||||
</presentationTable>
|
||||
|
||||
</resources>
|
||||
</policyDefinitionResources>
|
||||
|
||||
|
|
|
@ -21,6 +21,8 @@ namespace Community.PowerToys.Run.Plugin.UnitConverter
|
|||
|
||||
public string Description => Properties.Resources.plugin_description;
|
||||
|
||||
public static string PluginID => "aa0ee9daff654fb7be452c2d77c471b9";
|
||||
|
||||
private PluginInitContext _context;
|
||||
private static string _icon_path;
|
||||
private bool _disposed;
|
||||
|
|
|
@ -23,6 +23,8 @@ namespace Community.PowerToys.Run.Plugin.VSCodeWorkspaces
|
|||
|
||||
public string Description => GetTranslatedPluginDescription();
|
||||
|
||||
public static string PluginID => "525995402BEF4A8CA860D92F6D108092";
|
||||
|
||||
public Main()
|
||||
{
|
||||
VSCodeInstances.LoadVSCodeInstances();
|
||||
|
|
|
@ -20,6 +20,8 @@ namespace Community.PowerToys.Run.Plugin.ValueGenerator
|
|||
|
||||
public string Description => Resources.plugin_description;
|
||||
|
||||
public static string PluginID => "a26b1bb4dbd911edafa10242ac120002";
|
||||
|
||||
private PluginInitContext _context;
|
||||
private static bool _isLightTheme = true;
|
||||
private bool _disposed;
|
||||
|
|
|
@ -36,6 +36,8 @@ namespace Community.PowerToys.Run.Plugin.WebSearch
|
|||
|
||||
public string Description => Properties.Resources.plugin_description;
|
||||
|
||||
public static string PluginID => "9F1B49201C3F4BF781CAAD5CD88EA4DC";
|
||||
|
||||
public IEnumerable<PluginAdditionalOption> AdditionalOptions => new List<PluginAdditionalOption>()
|
||||
{
|
||||
new PluginAdditionalOption()
|
||||
|
|
|
@ -44,6 +44,8 @@ namespace Microsoft.Plugin.Folder
|
|||
|
||||
public string Description => Properties.Resources.wox_plugin_folder_plugin_description;
|
||||
|
||||
public static string PluginID => "B4D3B69656E14D44865C8D818EAE47C4";
|
||||
|
||||
public void Save()
|
||||
{
|
||||
_storage.Save();
|
||||
|
|
|
@ -51,6 +51,8 @@ namespace Microsoft.Plugin.Indexer
|
|||
|
||||
public string Description => Properties.Resources.Microsoft_plugin_indexer_plugin_description;
|
||||
|
||||
public static string PluginID => "2140FC9819AD43A3A616E2735815C27C";
|
||||
|
||||
public IEnumerable<PluginAdditionalOption> AdditionalOptions => new List<PluginAdditionalOption>()
|
||||
{
|
||||
new PluginAdditionalOption()
|
||||
|
|
|
@ -37,6 +37,8 @@ namespace Microsoft.Plugin.Program
|
|||
|
||||
public string Description => Properties.Resources.wox_plugin_program_plugin_description;
|
||||
|
||||
public static string PluginID => "791FC278BA414111B8D1886DFE447410";
|
||||
|
||||
private static PluginInitContext _context;
|
||||
private readonly PluginJsonStorage<ProgramPluginSettings> _settingsStorage;
|
||||
private bool _disposed;
|
||||
|
|
|
@ -39,6 +39,8 @@ namespace Microsoft.Plugin.Shell
|
|||
|
||||
public string Description => Properties.Resources.wox_plugin_cmd_plugin_description;
|
||||
|
||||
public static string PluginID => "D409510CD0D2481F853690A07E6DC426";
|
||||
|
||||
public IEnumerable<PluginAdditionalOption> AdditionalOptions => new List<PluginAdditionalOption>()
|
||||
{
|
||||
new PluginAdditionalOption()
|
||||
|
|
|
@ -37,6 +37,8 @@ namespace Microsoft.Plugin.Uri
|
|||
|
||||
public string Description => Properties.Resources.Microsoft_plugin_uri_plugin_description;
|
||||
|
||||
public static string PluginID => "03276A39D4E9417C8FFD200B0EE5E871";
|
||||
|
||||
public List<ContextMenuResult> LoadContextMenus(Result selectedResult)
|
||||
{
|
||||
return new List<ContextMenuResult>(0);
|
||||
|
|
|
@ -29,6 +29,8 @@ namespace Microsoft.Plugin.WindowWalker
|
|||
|
||||
public string Description => Properties.Resources.wox_plugin_windowwalker_plugin_description;
|
||||
|
||||
public static string PluginID => "F737A9223560B3C6833B5FFB8CDF78E5";
|
||||
|
||||
internal static readonly VirtualDesktopHelper VirtualDesktopHelperInstance = new VirtualDesktopHelper();
|
||||
|
||||
public List<Result> Query(Query query)
|
||||
|
|
|
@ -30,6 +30,8 @@ namespace Microsoft.PowerToys.Run.Plugin.Calculator
|
|||
|
||||
public string Description => Resources.wox_plugin_calculator_plugin_description;
|
||||
|
||||
public static string PluginID => "CEA0FDFC6D3B4085823D60DC76F28855";
|
||||
|
||||
private bool _disposed;
|
||||
|
||||
public IEnumerable<PluginAdditionalOption> AdditionalOptions => new List<PluginAdditionalOption>()
|
||||
|
|
|
@ -22,6 +22,8 @@ namespace Microsoft.PowerToys.Run.Plugin.History
|
|||
|
||||
public string Description => Resources.wox_plugin_history_plugin_description;
|
||||
|
||||
public static string PluginID => "C88512156BB74580AADF7252E130BA8D";
|
||||
|
||||
private bool _disposed;
|
||||
|
||||
public List<Result> Query(Query query)
|
||||
|
|
|
@ -59,6 +59,11 @@ namespace Microsoft.PowerToys.Run.Plugin.OneNote
|
|||
/// </summary>
|
||||
public string Description => Resources.PluginDescription;
|
||||
|
||||
/// <summary>
|
||||
/// Gets the plugin ID for validation
|
||||
/// </summary>
|
||||
public static string PluginID => "0778F0C264114FEC8A3DF59447CF0A74";
|
||||
|
||||
/// <summary>
|
||||
/// Initialize the plugin with the given <see cref="PluginInitContext"/>
|
||||
/// </summary>
|
||||
|
|
|
@ -21,6 +21,8 @@ namespace Microsoft.PowerToys.Run.Plugin.PowerToys
|
|||
|
||||
public string Description => Resources.Plugin_Description;
|
||||
|
||||
public static string PluginID => "29DD65DB28C84A37BDEF1D2B43DA368B";
|
||||
|
||||
public string GetTranslatedPluginTitle() => Resources.Plugin_Name;
|
||||
|
||||
public string GetTranslatedPluginDescription() => Resources.Plugin_Description;
|
||||
|
|
|
@ -46,6 +46,8 @@ namespace Microsoft.PowerToys.Run.Plugin.Registry
|
|||
|
||||
public string Description => Resources.PluginDescription;
|
||||
|
||||
public static string PluginID => "303417D927BF4C97BCFFC78A123BE0C8";
|
||||
|
||||
/// <summary>
|
||||
/// Initializes a new instance of the <see cref="Main"/> class.
|
||||
/// </summary>
|
||||
|
|
|
@ -23,6 +23,8 @@ namespace Microsoft.PowerToys.Run.Plugin.Service
|
|||
|
||||
public string Description => Resources.wox_plugin_service_plugin_description;
|
||||
|
||||
public static string PluginID => "11A6C36E4E91439CA69F702CBD364EF7";
|
||||
|
||||
public void Init(PluginInitContext context)
|
||||
{
|
||||
_context = context;
|
||||
|
|
|
@ -31,6 +31,8 @@ namespace Microsoft.PowerToys.Run.Plugin.System
|
|||
|
||||
public string Description => Resources.Microsoft_plugin_sys_plugin_description;
|
||||
|
||||
public static string PluginID => "CEA08895D2544B019B2E9C5009600DF4";
|
||||
|
||||
public string IconTheme { get; set; }
|
||||
|
||||
public bool IsBootedInUefiMode { get; set; }
|
||||
|
|
|
@ -25,6 +25,8 @@ namespace Microsoft.PowerToys.Run.Plugin.TimeDate
|
|||
|
||||
public string Description => GetTranslatedPluginDescription();
|
||||
|
||||
public static string PluginID => "5D69806A5A474115821C3E4C56B9C793";
|
||||
|
||||
public IEnumerable<PluginAdditionalOption> AdditionalOptions
|
||||
{
|
||||
get
|
||||
|
|
|
@ -72,6 +72,11 @@ namespace Microsoft.PowerToys.Run.Plugin.WindowsSettings
|
|||
/// </summary>
|
||||
public string Description => Resources.PluginDescription;
|
||||
|
||||
/// <summary>
|
||||
/// Gets the plugin ID for validation
|
||||
/// </summary>
|
||||
public static string PluginID => "5043CECEE6A748679CBE02D27D83747A";
|
||||
|
||||
/// <summary>
|
||||
/// Initialize the plugin with the given <see cref="PluginInitContext"/>.
|
||||
/// </summary>
|
||||
|
|
|
@ -34,6 +34,8 @@ namespace Microsoft.PowerToys.Run.Plugin.WindowsTerminal
|
|||
|
||||
public string Description => Resources.plugin_description;
|
||||
|
||||
public static string PluginID => "F59BA85006B14389A72A0EA756695F1D";
|
||||
|
||||
public IEnumerable<PluginAdditionalOption> AdditionalOptions => new List<PluginAdditionalOption>()
|
||||
{
|
||||
new PluginAdditionalOption()
|
||||
|
|
|
@ -11,6 +11,8 @@ using System.IO.Abstractions;
|
|||
using System.Linq;
|
||||
using System.Reflection;
|
||||
using System.Threading.Tasks;
|
||||
using global::PowerToys.GPOWrapper;
|
||||
using ManagedCommon;
|
||||
using PowerLauncher.Properties;
|
||||
using Wox.Infrastructure.Storage;
|
||||
using Wox.Plugin;
|
||||
|
@ -140,6 +142,25 @@ namespace PowerLauncher.Plugin
|
|||
var failedPlugins = new ConcurrentQueue<PluginPair>();
|
||||
Parallel.ForEach(AllPlugins, pair =>
|
||||
{
|
||||
// Check policy state for the plugin and update metadata
|
||||
var enabledPolicyState = GPOWrapper.GetRunPluginEnabledValue(pair.Metadata.ID);
|
||||
if (enabledPolicyState == GpoRuleConfigured.Enabled)
|
||||
{
|
||||
pair.Metadata.Disabled = false;
|
||||
pair.Metadata.IsEnabledPolicyConfigured = true;
|
||||
Log.Info($"The plugin <{pair.Metadata.Name}> is enabled by policy.", typeof(PluginManager));
|
||||
}
|
||||
else if (enabledPolicyState == GpoRuleConfigured.Disabled)
|
||||
{
|
||||
pair.Metadata.Disabled = true;
|
||||
pair.Metadata.IsEnabledPolicyConfigured = true;
|
||||
Log.Info($"The plugin <{pair.Metadata.Name}> is disabled by policy.", typeof(PluginManager));
|
||||
}
|
||||
else if (enabledPolicyState == GpoRuleConfigured.WrongValue)
|
||||
{
|
||||
Log.Warn($"Wrong policy value for enabled policy for plugin <{pair.Metadata.Name}>.", typeof(PluginManager));
|
||||
}
|
||||
|
||||
if (pair.Metadata.Disabled)
|
||||
{
|
||||
return;
|
||||
|
|
|
@ -9,6 +9,7 @@ using System.Linq;
|
|||
using System.Threading;
|
||||
using System.Windows.Input;
|
||||
using Common.UI;
|
||||
using global::PowerToys.GPOWrapper;
|
||||
using Microsoft.PowerToys.Settings.UI.Library;
|
||||
using PowerLauncher.Helper;
|
||||
using PowerLauncher.Plugin;
|
||||
|
@ -242,6 +243,7 @@ namespace PowerLauncher
|
|||
IconPathDark = GetIcon(x.Metadata, x.Metadata.IcoPathDark),
|
||||
IconPathLight = GetIcon(x.Metadata, x.Metadata.IcoPathLight),
|
||||
AdditionalOptions = x.Plugin is ISettingProvider ? (x.Plugin as ISettingProvider).AdditionalOptions : new List<PluginAdditionalOption>(),
|
||||
EnabledPolicyUiState = (int)GpoRuleConfigured.NotConfigured,
|
||||
});
|
||||
}
|
||||
|
||||
|
@ -256,11 +258,13 @@ namespace PowerLauncher
|
|||
if (defaultPlugins.ContainsKey(plugin.Id))
|
||||
{
|
||||
var additionalOptions = CombineAdditionalOptions(defaultPlugins[plugin.Id].AdditionalOptions, plugin.AdditionalOptions);
|
||||
var enabledPolicyState = GPOWrapper.GetRunPluginEnabledValue(plugin.Id);
|
||||
plugin.Name = defaultPlugins[plugin.Id].Name;
|
||||
plugin.Description = defaultPlugins[plugin.Id].Description;
|
||||
plugin.Author = defaultPlugins[plugin.Id].Author;
|
||||
plugin.IconPathDark = defaultPlugins[plugin.Id].IconPathDark;
|
||||
plugin.IconPathLight = defaultPlugins[plugin.Id].IconPathLight;
|
||||
plugin.EnabledPolicyUiState = (int)enabledPolicyState;
|
||||
defaultPlugins[plugin.Id] = plugin;
|
||||
defaultPlugins[plugin.Id].AdditionalOptions = additionalOptions;
|
||||
}
|
||||
|
|
|
@ -2,6 +2,7 @@
|
|||
// The Microsoft Corporation licenses this file to you under the MIT license.
|
||||
// See the LICENSE file in the project root for more information.
|
||||
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
|
||||
namespace Wox.Plugin
|
||||
|
@ -17,5 +18,11 @@ namespace Wox.Plugin
|
|||
|
||||
// Localized description
|
||||
string Description { get; }
|
||||
|
||||
/* The two property lines are commented because they break the unit tests. (The Moq package used in the unit tests doesn't support the .Net 7 feature 'static abstract' properties yet.) - https://github.com/Moq/Moq/issues/1398
|
||||
*
|
||||
* // Plugin ID for validating the plugin.json entry (It must be static for accessing it before loading the plugin.)
|
||||
* public static abstract string PluginID { get; }
|
||||
*/
|
||||
}
|
||||
}
|
||||
|
|
|
@ -32,6 +32,10 @@ namespace Wox.Plugin
|
|||
|
||||
public bool Disabled { get; set; }
|
||||
|
||||
// This property is used in PT Run only to decide whether to updated the Disabled property or not.
|
||||
[JsonIgnore]
|
||||
public bool IsEnabledPolicyConfigured { get; set; }
|
||||
|
||||
[JsonInclude]
|
||||
public string ExecuteFilePath { get; private set; }
|
||||
|
||||
|
|
|
@ -63,20 +63,24 @@ namespace Wox.Plugin
|
|||
return;
|
||||
}
|
||||
|
||||
if (Metadata.Disabled && !setting.Disabled)
|
||||
// If the enabled state is policy managed then we skip the update of the disabled state as it must be a manual settings.json manipulation.
|
||||
if (!Metadata.IsEnabledPolicyConfigured)
|
||||
{
|
||||
Metadata.Disabled = false;
|
||||
InitializePlugin(api);
|
||||
|
||||
if (!IsPluginInitialized)
|
||||
if (Metadata.Disabled && !setting.Disabled)
|
||||
{
|
||||
string description = $"{Resources.FailedToLoadPluginDescription} {Metadata.Name}\n\n{Resources.FailedToLoadPluginDescriptionPartTwo}";
|
||||
api.ShowMsg(Resources.FailedToLoadPluginTitle, description, string.Empty, false);
|
||||
Metadata.Disabled = false;
|
||||
InitializePlugin(api);
|
||||
|
||||
if (!IsPluginInitialized)
|
||||
{
|
||||
string description = $"{Resources.FailedToLoadPluginDescription} {Metadata.Name}\n\n{Resources.FailedToLoadPluginDescriptionPartTwo}";
|
||||
api.ShowMsg(Resources.FailedToLoadPluginTitle, description, string.Empty, false);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
Metadata.Disabled = setting.Disabled;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
Metadata.Disabled = setting.Disabled;
|
||||
}
|
||||
|
||||
Metadata.ActionKeyword = setting.ActionKeyword;
|
||||
|
@ -167,6 +171,19 @@ namespace Wox.Plugin
|
|||
return false;
|
||||
}
|
||||
|
||||
// Validate plugin ID to prevent bypassing the GPO by changing the ID in the plugin.json file.
|
||||
string pluginID = (string)type.GetProperty("PluginID", BindingFlags.Public | BindingFlags.Static)?.GetValue(null);
|
||||
if (pluginID == null)
|
||||
{
|
||||
Log.Error($"Can't validate plugin ID of plugin <{Metadata.Name}> in {Metadata.ExecuteFilePath}: The static property <Main.PluginID> was not found.", MethodBase.GetCurrentMethod().DeclaringType);
|
||||
return false;
|
||||
}
|
||||
else if (pluginID != Metadata.ID)
|
||||
{
|
||||
Log.Error($"Wrong plugin ID found in plugin.json of plugin <{Metadata.Name}>. ('{Metadata.ID}' != '{pluginID}')", MethodBase.GetCurrentMethod().DeclaringType);
|
||||
return false;
|
||||
}
|
||||
|
||||
try
|
||||
{
|
||||
Plugin = (IPlugin)Activator.CreateInstance(type);
|
||||
|
|
|
@ -18,6 +18,10 @@ namespace Microsoft.PowerToys.Settings.UI.Library
|
|||
|
||||
public bool Disabled { get; set; }
|
||||
|
||||
// Use to communicate the state to settings UI (Using int type because we can't reference GPOWrapper.)
|
||||
// This property should never be used inside of PT Run to get the policy state as it can be manipulated by changing the settings.json file.
|
||||
public int EnabledPolicyUiState { get; set; }
|
||||
|
||||
public bool IsGlobal { get; set; }
|
||||
|
||||
public string ActionKeyword { get; set; }
|
||||
|
|
|
@ -238,7 +238,12 @@
|
|||
</controls:SettingsCard>
|
||||
|
||||
|
||||
|
||||
<InfoBar
|
||||
x:Uid="Run_SomePluginsAreGpoManaged"
|
||||
IsClosable="False"
|
||||
IsOpen="{x:Bind ViewModel.ShowPluginsAreGpoManagedInfo, Mode=OneWay}"
|
||||
IsTabStop="{x:Bind ViewModel.ShowPluginsAreGpoManagedInfo, Mode=OneWay}"
|
||||
Severity="Informational" />
|
||||
<InfoBar
|
||||
x:Uid="Run_AllPluginsDisabled"
|
||||
IsClosable="False"
|
||||
|
@ -293,7 +298,8 @@
|
|||
Visibility="{x:Bind ShowBadgeOnPluginSettingError}" />
|
||||
</Grid>
|
||||
|
||||
<ToggleSwitch x:Uid="PowerLauncher_EnablePluginToggle" IsOn="{x:Bind Path=Disabled, Converter={StaticResource BoolNegationConverter}, Mode=TwoWay}" />
|
||||
<ToggleSwitch x:Uid="PowerLauncher_EnablePluginToggle" IsOn="{x:Bind Path=Disabled, Converter={StaticResource BoolNegationConverter}, Mode=TwoWay}" IsEnabled="{x:Bind Path=EnabledGpoRuleIsConfigured, Converter={StaticResource BoolNegationConverter}, Mode=OneWay}" />
|
||||
|
||||
</StackPanel>
|
||||
<controls:SettingsExpander.Items>
|
||||
<controls:SettingsCard x:Uid="PowerLauncher_ActionKeyword" IsEnabled="{x:Bind Enabled, Mode=OneWay}">
|
||||
|
|
|
@ -3680,6 +3680,9 @@ Activate by holding the key for the character you want to add an accent to, then
|
|||
<data name="Run_PluginUseFindMorePlugins.Content" xml:space="preserve">
|
||||
<value>Find more plugins</value>
|
||||
</data>
|
||||
<data name="Run_SomePluginsAreGpoManaged.Title" xml:space="preserve">
|
||||
<value>The system administrator is managing the enabled state of some plugins.</value>
|
||||
</data>
|
||||
<data name="AlwaysOnTop_FrameOpacity.Header" xml:space="preserve">
|
||||
<value>Opacity (%)</value>
|
||||
</data>
|
||||
|
|
|
@ -8,6 +8,7 @@ using System.ComponentModel;
|
|||
using System.IO;
|
||||
using System.Linq;
|
||||
using System.Runtime.CompilerServices;
|
||||
using global::PowerToys.GPOWrapper;
|
||||
using Microsoft.PowerToys.Settings.UI.Library;
|
||||
|
||||
namespace Microsoft.PowerToys.Settings.UI.ViewModels
|
||||
|
@ -33,6 +34,9 @@ namespace Microsoft.PowerToys.Settings.UI.ViewModels
|
|||
NotifyPropertyChanged(nameof(AdditionalOptions));
|
||||
};
|
||||
}
|
||||
|
||||
_enabledGpoRuleConfiguration = (GpoRuleConfigured)settings.EnabledPolicyUiState;
|
||||
_enabledGpoRuleIsConfigured = _enabledGpoRuleConfiguration == GpoRuleConfigured.Disabled || _enabledGpoRuleConfiguration == GpoRuleConfigured.Enabled;
|
||||
}
|
||||
|
||||
public string Id { get => settings.Id; }
|
||||
|
@ -43,11 +47,25 @@ namespace Microsoft.PowerToys.Settings.UI.ViewModels
|
|||
|
||||
public string Author { get => settings.Author; }
|
||||
|
||||
private GpoRuleConfigured _enabledGpoRuleConfiguration;
|
||||
private bool _enabledGpoRuleIsConfigured;
|
||||
|
||||
public bool Disabled
|
||||
{
|
||||
get
|
||||
{
|
||||
return settings.Disabled;
|
||||
if (_enabledGpoRuleConfiguration == GpoRuleConfigured.Disabled)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
else if (_enabledGpoRuleConfiguration == GpoRuleConfigured.Enabled)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
else
|
||||
{
|
||||
return settings.Disabled;
|
||||
}
|
||||
}
|
||||
|
||||
set
|
||||
|
@ -55,6 +73,7 @@ namespace Microsoft.PowerToys.Settings.UI.ViewModels
|
|||
if (settings.Disabled != value)
|
||||
{
|
||||
settings.Disabled = value;
|
||||
|
||||
NotifyPropertyChanged();
|
||||
NotifyPropertyChanged(nameof(ShowNotAccessibleWarning));
|
||||
NotifyPropertyChanged(nameof(Enabled));
|
||||
|
@ -67,6 +86,8 @@ namespace Microsoft.PowerToys.Settings.UI.ViewModels
|
|||
|
||||
public bool Enabled => !Disabled;
|
||||
|
||||
public bool EnabledGpoRuleIsConfigured => _enabledGpoRuleIsConfigured;
|
||||
|
||||
public double DisabledOpacity => Disabled ? 0.5 : 1;
|
||||
|
||||
public bool IsGlobalAndEnabled
|
||||
|
|
|
@ -135,6 +135,7 @@ namespace Microsoft.PowerToys.Settings.UI.ViewModels
|
|||
}
|
||||
|
||||
OnPropertyChanged(nameof(ShowAllPluginsDisabledWarning));
|
||||
OnPropertyChanged(nameof(ShowPluginsAreGpoManagedInfo));
|
||||
UpdateSettings();
|
||||
}
|
||||
|
||||
|
@ -174,6 +175,7 @@ namespace Microsoft.PowerToys.Settings.UI.ViewModels
|
|||
OnPropertyChanged(nameof(EnablePowerLauncher));
|
||||
OnPropertyChanged(nameof(ShowAllPluginsDisabledWarning));
|
||||
OnPropertyChanged(nameof(ShowPluginsLoadingMessage));
|
||||
OnPropertyChanged(nameof(ShowPluginsAreGpoManagedInfo));
|
||||
OutGoingGeneralSettings outgoing = new OutGoingGeneralSettings(GeneralSettingsConfig);
|
||||
SendConfigMSG(outgoing.ToString());
|
||||
}
|
||||
|
@ -186,6 +188,7 @@ namespace Microsoft.PowerToys.Settings.UI.ViewModels
|
|||
OnPropertyChanged(nameof(EnablePowerLauncher));
|
||||
OnPropertyChanged(nameof(ShowAllPluginsDisabledWarning));
|
||||
OnPropertyChanged(nameof(ShowPluginsLoadingMessage));
|
||||
OnPropertyChanged(nameof(ShowPluginsAreGpoManagedInfo));
|
||||
}
|
||||
|
||||
public bool IsEnabledGpoConfigured
|
||||
|
@ -616,9 +619,14 @@ namespace Microsoft.PowerToys.Settings.UI.ViewModels
|
|||
}
|
||||
}
|
||||
|
||||
public bool ShowPluginsAreGpoManagedInfo
|
||||
{
|
||||
get => EnablePowerLauncher && settings.Plugins.Any() && Plugins.Any(x => x.EnabledGpoRuleIsConfigured);
|
||||
}
|
||||
|
||||
public bool ShowAllPluginsDisabledWarning
|
||||
{
|
||||
get => EnablePowerLauncher && settings.Plugins.Any() && settings.Plugins.All(x => x.Disabled);
|
||||
get => EnablePowerLauncher && settings.Plugins.Any() && Plugins.All(x => x.Disabled);
|
||||
}
|
||||
|
||||
public bool ShowPluginsLoadingMessage
|
||||
|
|
Загрузка…
Ссылка в новой задаче