mirror of
https://github.com/microsoft/PowerToys.git
synced 2026-04-05 18:57:19 +02:00
[PT Run] Registry plugin (#7951)
This commit is contained in:
@@ -0,0 +1,27 @@
|
||||
// Copyright (c) Microsoft Corporation
|
||||
// The Microsoft Corporation licenses this file to you under the MIT license.
|
||||
// See the LICENSE file in the project root for more information.
|
||||
|
||||
using Microsoft.PowerToys.Run.Plugin.Registry.Constants;
|
||||
using Microsoft.VisualStudio.TestTools.UnitTesting;
|
||||
|
||||
namespace Microsoft.PowerToys.Run.Plugin.Registry.UnitTest.Constants
|
||||
{
|
||||
[TestClass]
|
||||
public sealed class KeyNameTest
|
||||
{
|
||||
[TestMethod]
|
||||
[DataRow("HKEY", KeyName.FirstPart)]
|
||||
[DataRow("HKEY_", KeyName.FirstPartUnderscore)]
|
||||
[DataRow("HKCR", KeyName.ClassRootShort)]
|
||||
[DataRow("HKCC", KeyName.CurrentConfigShort)]
|
||||
[DataRow("HKCU", KeyName.CurrentUserShort)]
|
||||
[DataRow("HKLM", KeyName.LocalMachineShort)]
|
||||
[DataRow("HKPD", KeyName.PerformanceDataShort)]
|
||||
[DataRow("HKU", KeyName.UsersShort)]
|
||||
public void TestConstants(string shortName, string baseName)
|
||||
{
|
||||
Assert.AreEqual(shortName, baseName);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,41 @@
|
||||
// Copyright (c) Microsoft Corporation
|
||||
// The Microsoft Corporation licenses this file to you under the MIT license.
|
||||
// See the LICENSE file in the project root for more information.
|
||||
|
||||
using Microsoft.PowerToys.Run.Plugin.Registry.Helper;
|
||||
using Microsoft.VisualStudio.TestTools.UnitTesting;
|
||||
|
||||
namespace Microsoft.PowerToys.Run.Plugin.Registry.UnitTest.Helper
|
||||
{
|
||||
[TestClass]
|
||||
public sealed class QueryHelperTest
|
||||
{
|
||||
[TestMethod]
|
||||
[DataRow(@"HKLM", false, @"HKLM", "")]
|
||||
[DataRow(@"HKLM\", false, @"HKLM\", "")]
|
||||
[DataRow(@"HKLM\\", true, @"HKLM", "")]
|
||||
[DataRow(@"HKLM\\Test", true, @"HKLM", "Test")]
|
||||
[DataRow(@"HKLM\Test\\TestTest", true, @"HKLM\Test", "TestTest")]
|
||||
[DataRow(@"HKLM\Test\\\TestTest", true, @"HKLM\Test", @"\TestTest")]
|
||||
public void GetQueryPartsTest(string query, bool expectedHasValueName, string expectedQueryKey, string expectedQueryValueName)
|
||||
{
|
||||
var hasValueName = QueryHelper.GetQueryParts(query, out var queryKey, out var queryValueName);
|
||||
|
||||
Assert.AreEqual(expectedHasValueName, hasValueName);
|
||||
Assert.AreEqual(expectedQueryKey, queryKey);
|
||||
Assert.AreEqual(expectedQueryValueName, queryValueName);
|
||||
}
|
||||
|
||||
[TestMethod]
|
||||
[DataRow(@"HKCR\*\OpenWithList", @"HKEY_CLASSES_ROOT\*\OpenWithList")]
|
||||
[DataRow(@"HKCU\Control Panel\Accessibility", @"HKEY_CURRENT_USER\Control Panel\Accessibility")]
|
||||
[DataRow(@"HKLM\HARDWARE\UEFI", @"HKEY_LOCAL_MACHINE\HARDWARE\UEFI")]
|
||||
[DataRow(@"HKU\.DEFAULT\Environment", @"HKEY_USERS\.DEFAULT\Environment")]
|
||||
[DataRow(@"HKCC\System\CurrentControlSet\Control", @"HKEY_CURRENT_CONFIG\System\CurrentControlSet\Control")]
|
||||
[DataRow(@"HKPD\???", @"HKEY_PERFORMANCE_DATA\???")]
|
||||
public void GetShortBaseKeyTest(string registryKeyShort, string registryKeyFull)
|
||||
{
|
||||
Assert.AreEqual(registryKeyShort, QueryHelper.GetKeyWithShortBaseKey(registryKeyFull));
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,73 @@
|
||||
// Copyright (c) Microsoft Corporation
|
||||
// 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.Collections;
|
||||
using System.Linq;
|
||||
using Microsoft.PowerToys.Run.Plugin.Registry.Helper;
|
||||
using Microsoft.VisualStudio.TestTools.UnitTesting;
|
||||
|
||||
namespace Microsoft.PowerToys.Run.Plugin.Registry.UnitTest.Helper
|
||||
{
|
||||
[TestClass]
|
||||
public sealed class RegistryHelperTest
|
||||
{
|
||||
[TestMethod]
|
||||
[DataRow(@"HKCC\System\CurrentControlSet\Control", "HKEY_CURRENT_CONFIG")]
|
||||
[DataRow(@"HKCR\*\OpenWithList", "HKEY_CLASSES_ROOT")]
|
||||
[DataRow(@"HKCU\Control Panel\Accessibility", "HKEY_CURRENT_USER")]
|
||||
[DataRow(@"HKLM\HARDWARE\UEFI", "HKEY_LOCAL_MACHINE")]
|
||||
[DataRow(@"HKPD\???", "HKEY_PERFORMANCE_DATA")]
|
||||
[DataRow(@"HKU\.DEFAULT\Environment", "HKEY_USERS")]
|
||||
public void GetRegistryBaseKeyTestOnlyOneBaseKey(string query, string expectedBaseKey)
|
||||
{
|
||||
var (baseKeyList, _) = RegistryHelper.GetRegistryBaseKey(query);
|
||||
Assert.IsTrue(baseKeyList.Count() == 1);
|
||||
Assert.AreEqual(expectedBaseKey, baseKeyList.FirstOrDefault().Name);
|
||||
}
|
||||
|
||||
[TestMethod]
|
||||
public void GetRegistryBaseKeyTestMoreThanOneBaseKey()
|
||||
{
|
||||
var (baseKeyList, _) = RegistryHelper.GetRegistryBaseKey("HKC\\Control Panel\\Accessibility"); /* #no-spell-check-line */
|
||||
|
||||
Assert.IsTrue(baseKeyList.Count() > 1);
|
||||
|
||||
var list = baseKeyList.Select(found => found.Name);
|
||||
Assert.IsTrue(list.Contains("HKEY_CLASSES_ROOT"));
|
||||
Assert.IsTrue(list.Contains("HKEY_CURRENT_CONFIG"));
|
||||
Assert.IsTrue(list.Contains("HKEY_CURRENT_USER"));
|
||||
}
|
||||
|
||||
[TestMethod]
|
||||
[DataRow(@"HKCR\*\OpenWithList", @"*\OpenWithList")]
|
||||
[DataRow(@"HKCU\Control Panel\Accessibility", @"Control Panel\Accessibility")]
|
||||
[DataRow(@"HKLM\HARDWARE\UEFI", @"HARDWARE\UEFI")]
|
||||
[DataRow(@"HKU\.DEFAULT\Environment", @".DEFAULT\Environment")]
|
||||
[DataRow(@"HKCC\System\CurrentControlSet\Control", @"System\CurrentControlSet\Control")]
|
||||
[DataRow(@"HKPD\???", @"???")]
|
||||
public void GetRegistryBaseKeyTestSubKey(string query, string expectedSubKey)
|
||||
{
|
||||
var (_, subKey) = RegistryHelper.GetRegistryBaseKey(query);
|
||||
Assert.AreEqual(expectedSubKey, subKey);
|
||||
}
|
||||
|
||||
[TestMethod]
|
||||
public void GetAllBaseKeysTest()
|
||||
{
|
||||
var list = RegistryHelper.GetAllBaseKeys();
|
||||
|
||||
CollectionAssert.AllItemsAreNotNull((ICollection)list);
|
||||
CollectionAssert.AllItemsAreUnique((ICollection)list);
|
||||
|
||||
var keys = list.Select(found => found.Key).ToList() as ICollection;
|
||||
|
||||
CollectionAssert.Contains(keys, Win32.Registry.ClassesRoot);
|
||||
CollectionAssert.Contains(keys, Win32.Registry.CurrentConfig);
|
||||
CollectionAssert.Contains(keys, Win32.Registry.CurrentUser);
|
||||
CollectionAssert.Contains(keys, Win32.Registry.LocalMachine);
|
||||
CollectionAssert.Contains(keys, Win32.Registry.PerformanceData);
|
||||
CollectionAssert.Contains(keys, Win32.Registry.Users);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,30 @@
|
||||
// Copyright (c) Microsoft Corporation
|
||||
// The Microsoft Corporation licenses this file to you under the MIT license.
|
||||
// See the LICENSE file in the project root for more information.
|
||||
|
||||
using Microsoft.PowerToys.Run.Plugin.Registry.Helper;
|
||||
using Microsoft.VisualStudio.TestTools.UnitTesting;
|
||||
|
||||
namespace Microsoft.PowerToys.Run.Plugin.Registry.UnitTest.Helper
|
||||
{
|
||||
[TestClass]
|
||||
public sealed class ResultHelperTest
|
||||
{
|
||||
[TestMethod]
|
||||
[DataRow(@"HKEY_CLASSES_ROOT\*\OpenWithList", @"HKEY_CLASSES_ROOT\*\OpenWithList")]
|
||||
[DataRow(@"HKEY_CURRENT_USER\Control Panel\Accessibility", @"HKEY_CURRENT_USER\Control Panel\Accessibility")]
|
||||
[DataRow(@"HKEY_LOCAL_MACHINE\HARDWARE\UEFI", @"HKEY_LOCAL_MACHINE\HARDWARE\UEFI")]
|
||||
[DataRow(@"HKEY_USERS\.DEFAULT\Environment", @"HKEY_USERS\.DEFAULT\Environment")]
|
||||
[DataRow(@"HKCC\System\CurrentControlSet\Control", @"HKEY_CURRENT_CONFIG\System\CurrentControlSet\Control")]
|
||||
[DataRow(@"HKEY_PERFORMANCE_DATA\???", @"HKEY_PERFORMANCE_DATA\???")]
|
||||
[DataRow(@"HKCR\*\shell\Open with VS Code\command", @"HKEY_CLASSES_ROOT\*\shell\Open with VS Code\command")]
|
||||
[DataRow(@"...ndows\CurrentVersion\Explorer\StartupApproved", @"HKEY_CURRENT_USER\Microsoft\Windows\CurrentVersion\Explorer\StartupApproved")]
|
||||
[DataRow(@"...p\Upgrade\NetworkDriverBackup\Control\Network", @"HKEY_LOCAL_MACHINE\SYSTEM\Setup\Upgrade\NetworkDriverBackup\Control\Network")]
|
||||
[DataRow(@"...anel\International\User Profile System Backup", @"HKEY_USERS\.DEFAULT\Control Panel\International\User Profile System Backup")]
|
||||
[DataRow(@"...stem\CurrentControlSet\Control\Print\Printers", @"HKEY_CURRENT_CONFIG\System\CurrentControlSet\Control\Print\Printers")]
|
||||
public void GetTruncatedTextTest(string registryKeyShort, string registryKeyFull)
|
||||
{
|
||||
Assert.AreEqual(registryKeyShort, ResultHelper.GetTruncatedText(registryKeyFull, 45));
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,65 @@
|
||||
<Project Sdk="Microsoft.NET.Sdk">
|
||||
|
||||
<PropertyGroup>
|
||||
<TargetFramework>netcoreapp3.1</TargetFramework>
|
||||
<Platforms>x64</Platforms>
|
||||
<NeutralLanguage>en-US</NeutralLanguage>
|
||||
<LangVersion>8.0</LangVersion>
|
||||
<Nullable>enable</Nullable>
|
||||
<IsPackable>false</IsPackable>
|
||||
</PropertyGroup>
|
||||
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
|
||||
<DebugSymbols>true</DebugSymbols>
|
||||
<DefineConstants>DEBUG;TRACE</DefineConstants>
|
||||
<DebugType>full</DebugType>
|
||||
<PlatformTarget>x64</PlatformTarget>
|
||||
<ErrorReport>prompt</ErrorReport>
|
||||
<CodeAnalysisRuleSet>MinimumRecommendedRules.ruleset</CodeAnalysisRuleSet>
|
||||
<WarningLevel>4</WarningLevel>
|
||||
<Optimize>false</Optimize>
|
||||
<TreatWarningsAsErrors>true</TreatWarningsAsErrors>
|
||||
</PropertyGroup>
|
||||
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
|
||||
<DefineConstants>TRACE</DefineConstants>
|
||||
<Optimize>true</Optimize>
|
||||
<DebugType>pdbonly</DebugType>
|
||||
<PlatformTarget>x64</PlatformTarget>
|
||||
<ErrorReport>prompt</ErrorReport>
|
||||
<CodeAnalysisRuleSet>MinimumRecommendedRules.ruleset</CodeAnalysisRuleSet>
|
||||
<WarningLevel>4</WarningLevel>
|
||||
<TreatWarningsAsErrors>true</TreatWarningsAsErrors>
|
||||
</PropertyGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<PackageReference Include="Microsoft.NET.Test.Sdk" Version="16.7.1" />
|
||||
<PackageReference Include="MSTest.TestAdapter" Version="2.1.1" />
|
||||
<PackageReference Include="MSTest.TestFramework" Version="2.1.1" />
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<Compile Include="..\..\..\..\codeAnalysis\GlobalSuppressions.cs">
|
||||
<Link>GlobalSuppressions.cs</Link>
|
||||
</Compile>
|
||||
<AdditionalFiles Include="..\..\..\..\codeAnalysis\StyleCop.json">
|
||||
<Link>StyleCop.json</Link>
|
||||
</AdditionalFiles>
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<PackageReference Include="Microsoft.CodeAnalysis.FxCopAnalyzers" Version="3.3.0">
|
||||
<PrivateAssets>all</PrivateAssets>
|
||||
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
|
||||
</PackageReference>
|
||||
<PackageReference Include="StyleCop.Analyzers" Version="1.1.118">
|
||||
<PrivateAssets>all</PrivateAssets>
|
||||
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
|
||||
</PackageReference>
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<ProjectReference Include="..\Microsoft.PowerToys.Run.Plugin.Registry\Microsoft.PowerToys.Run.Plugin.Registry.csproj" />
|
||||
</ItemGroup>
|
||||
|
||||
</Project>
|
||||
@@ -0,0 +1,113 @@
|
||||
// Copyright (c) Microsoft Corporation
|
||||
// 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 Microsoft.PowerToys.Run.Plugin.Registry.Helper;
|
||||
using Microsoft.Win32;
|
||||
|
||||
namespace Microsoft.PowerToys.Run.Plugin.Registry.Classes
|
||||
{
|
||||
/// <summary>
|
||||
/// A entry of the registry.
|
||||
/// </summary>
|
||||
internal class RegistryEntry
|
||||
{
|
||||
/// <summary>
|
||||
/// Gets the full path to a registry key.
|
||||
/// </summary>
|
||||
internal string KeyPath { get; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets the registry key for this entry.
|
||||
/// </summary>
|
||||
internal RegistryKey? Key { get; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets a possible exception that was occurred when try to open this registry key (e.g. <see cref="UnauthorizedAccessException"/>).
|
||||
/// </summary>
|
||||
internal Exception? Exception { get; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets the name of the current selected registry value.
|
||||
/// </summary>
|
||||
internal string? ValueName { get; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets the value of the current selected registry value.
|
||||
/// </summary>
|
||||
internal object? ValueData { get; }
|
||||
|
||||
/// <summary>
|
||||
/// Initializes a new instance of the <see cref="RegistryEntry"/> class.
|
||||
/// </summary>
|
||||
/// <param name="keyPath">The full path to the registry key for this entry.</param>
|
||||
/// <param name="exception">A exception that was occurred when try to access this registry key.</param>
|
||||
internal RegistryEntry(string keyPath, Exception exception)
|
||||
{
|
||||
KeyPath = keyPath;
|
||||
Exception = exception;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Initializes a new instance of the <see cref="RegistryEntry"/> class.
|
||||
/// </summary>
|
||||
/// <param name="key">The <see cref="RegistryKey"/> for this entry.</param>
|
||||
internal RegistryEntry(RegistryKey key)
|
||||
{
|
||||
KeyPath = key.Name;
|
||||
Key = key;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Initializes a new instance of the <see cref="RegistryEntry"/> class.
|
||||
/// </summary>
|
||||
/// <param name="key">The <see cref="RegistryKey"/> for this entry.</param>
|
||||
/// <param name="valueName">The value name of the current selected registry value.</param>
|
||||
/// <param name="value">The value of the current selected registry value.</param>
|
||||
internal RegistryEntry(RegistryKey key, string valueName, object value)
|
||||
{
|
||||
KeyPath = key.Name;
|
||||
Key = key;
|
||||
ValueName = valueName;
|
||||
ValueData = value;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Return the registry key.
|
||||
/// </summary>
|
||||
/// <returns>A registry key.</returns>
|
||||
internal string GetRegistryKey()
|
||||
{
|
||||
return $"{Key?.Name ?? KeyPath}";
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Return the value name with the complete registry key.
|
||||
/// </summary>
|
||||
/// <returns>A value name with the complete registry key.</returns>
|
||||
internal string GetValueNameWithKey()
|
||||
{
|
||||
return $"{Key?.Name ?? KeyPath}\\\\{ValueName?.ToString() ?? string.Empty}";
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Return the value data of a value name inside a registry key.
|
||||
/// </summary>
|
||||
/// <returns>A value data.</returns>
|
||||
internal string GetValueData()
|
||||
{
|
||||
if (Key is null)
|
||||
{
|
||||
return KeyPath;
|
||||
}
|
||||
|
||||
if (string.IsNullOrEmpty(ValueName))
|
||||
{
|
||||
return Key.Name;
|
||||
}
|
||||
|
||||
return ValueHelper.GetValue(Key, ValueName);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,52 @@
|
||||
// Copyright (c) Microsoft Corporation
|
||||
// The Microsoft Corporation licenses this file to you under the MIT license.
|
||||
// See the LICENSE file in the project root for more information.
|
||||
|
||||
namespace Microsoft.PowerToys.Run.Plugin.Registry.Constants
|
||||
{
|
||||
/// <summary>
|
||||
/// This class contains names for important registry keys
|
||||
/// </summary>
|
||||
internal static class KeyName
|
||||
{
|
||||
/// <summary>
|
||||
/// The first name part of each base key without the underscore
|
||||
/// </summary>
|
||||
internal const string FirstPart = "HKEY";
|
||||
|
||||
/// <summary>
|
||||
/// The first name part of each base key follow by a underscore
|
||||
/// </summary>
|
||||
internal const string FirstPartUnderscore = "HKEY_";
|
||||
|
||||
/// <summary>
|
||||
/// The short name for the base key HKEY_CLASSES_ROOT (see <see cref="Win32.Registry.ClassesRoot"/>)
|
||||
/// </summary>
|
||||
internal const string ClassRootShort = "HKCR";
|
||||
|
||||
/// <summary>
|
||||
/// The short name for the base key HKEY_CURRENT_CONFIG (see <see cref="Win32.Registry.CurrentConfig"/>)
|
||||
/// </summary>
|
||||
internal const string CurrentConfigShort = "HKCC";
|
||||
|
||||
/// <summary>
|
||||
/// The short name for the base key HKEY_CURRENT_USER (see <see cref="Win32.Registry.CurrentUser"/>)
|
||||
/// </summary>
|
||||
internal const string CurrentUserShort = "HKCU";
|
||||
|
||||
/// <summary>
|
||||
/// The short name for the base key HKEY_LOCAL_MACHINE (see <see cref="Win32.Registry.LocalMachine"/>)
|
||||
/// </summary>
|
||||
internal const string LocalMachineShort = "HKLM";
|
||||
|
||||
/// <summary>
|
||||
/// The short name for the base key HKEY_PERFORMANCE_DATA (see <see cref="Win32.Registry.PerformanceData"/>)
|
||||
/// </summary>
|
||||
internal const string PerformanceDataShort = "HKPD";
|
||||
|
||||
/// <summary>
|
||||
/// The short name for the base key HKEY_USERS (see <see cref="Win32.Registry.Users"/>)
|
||||
/// </summary>
|
||||
internal const string UsersShort = "HKU";
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,32 @@
|
||||
// Copyright (c) Microsoft Corporation
|
||||
// The Microsoft Corporation licenses this file to you under the MIT license.
|
||||
// See the LICENSE file in the project root for more information.
|
||||
|
||||
namespace Microsoft.PowerToys.Run.Plugin.Registry.Constants
|
||||
{
|
||||
/// <summary>
|
||||
/// This class contain all maximum text length.
|
||||
/// </summary>
|
||||
public static class MaxTextLength
|
||||
{
|
||||
/// <summary>
|
||||
/// The maximum length for the title text length with two context menu symbols on the right.
|
||||
/// </summary>
|
||||
internal const int MaximumTitleLengthWithTwoSymbols = 44;
|
||||
|
||||
/// <summary>
|
||||
/// The maximum length for the title text length with three context menu symbols on the right.
|
||||
/// </summary>
|
||||
internal const int MaximumTitleLengthWithThreeSymbols = 40;
|
||||
|
||||
/// <summary>
|
||||
/// The maximum length for the sub-title text length with two context menu symbols on the right.
|
||||
/// </summary>
|
||||
internal const int MaximumSubTitleLengthWithTwoSymbols = 85;
|
||||
|
||||
/// <summary>
|
||||
/// The maximum length for the sub-title text length with three context menu symbols on the right.
|
||||
/// </summary>
|
||||
internal const int MaximumSubTitleLengthWithThreeSymbols = 78;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,22 @@
|
||||
// Copyright (c) Microsoft Corporation
|
||||
// The Microsoft Corporation licenses this file to you under the MIT license.
|
||||
// See the LICENSE file in the project root for more information.
|
||||
|
||||
namespace Microsoft.PowerToys.Run.Plugin.Registry.Enumerations
|
||||
{
|
||||
/// <summary>
|
||||
/// The truncate side for a to long text
|
||||
/// </summary>
|
||||
internal enum TruncateSide
|
||||
{
|
||||
/// <summary>
|
||||
/// Truncate a text only from the right side
|
||||
/// </summary>
|
||||
OnlyFromLeft,
|
||||
|
||||
/// <summary>
|
||||
/// Truncate a text only from the left side
|
||||
/// </summary>
|
||||
OnlyFromRight,
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,140 @@
|
||||
// Copyright (c) Microsoft Corporation
|
||||
// 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;
|
||||
using System.Windows;
|
||||
using System.Windows.Input;
|
||||
using Microsoft.PowerToys.Run.Plugin.Registry.Classes;
|
||||
using Microsoft.PowerToys.Run.Plugin.Registry.Properties;
|
||||
using Wox.Plugin;
|
||||
using Wox.Plugin.Logger;
|
||||
|
||||
namespace Microsoft.PowerToys.Run.Plugin.Registry.Helper
|
||||
{
|
||||
/// <summary>
|
||||
/// Helper class to easier work with context menu entries
|
||||
/// </summary>
|
||||
internal static class ContextMenuHelper
|
||||
{
|
||||
/// <summary>
|
||||
/// Return a list with all context menu entries for the given <see cref="Result"/>
|
||||
/// <para>Symbols taken from <see href="https://docs.microsoft.com/en-us/windows/uwp/design/style/segoe-ui-symbol-font"/></para>
|
||||
/// </summary>
|
||||
/// <param name="result">The result for the context menu entires</param>
|
||||
/// <param name="assemblyName">The name of the this assembly</param>
|
||||
/// <returns>A list with context menu entries</returns>
|
||||
internal static List<ContextMenuResult> GetContextMenu(Result result, string assemblyName)
|
||||
{
|
||||
if (!(result?.ContextData is RegistryEntry entry))
|
||||
{
|
||||
return new List<ContextMenuResult>(0);
|
||||
}
|
||||
|
||||
var list = new List<ContextMenuResult>();
|
||||
|
||||
if (string.IsNullOrEmpty(entry.ValueName))
|
||||
{
|
||||
list.Add(new ContextMenuResult
|
||||
{
|
||||
AcceleratorKey = Key.C,
|
||||
AcceleratorModifiers = ModifierKeys.Control,
|
||||
Action = _ => TryToCopyToClipBoard(entry.GetRegistryKey()),
|
||||
FontFamily = "Segoe MDL2 Assets",
|
||||
Glyph = "\xE8C8", // E8C8 => Symbol: Copy
|
||||
PluginName = assemblyName,
|
||||
Title = $"{Resources.CopyKeyNamePath} (Ctrl+C)",
|
||||
});
|
||||
}
|
||||
else
|
||||
{
|
||||
list.Add(new ContextMenuResult
|
||||
{
|
||||
AcceleratorKey = Key.C,
|
||||
AcceleratorModifiers = ModifierKeys.Control | ModifierKeys.Shift,
|
||||
Action = _ => TryToCopyToClipBoard(entry.GetValueData()),
|
||||
FontFamily = "Segoe MDL2 Assets",
|
||||
Glyph = "\xF413", // F413 => Symbol: CopyTo
|
||||
PluginName = assemblyName,
|
||||
Title = $"{Resources.CopyValueData} (Ctrl+Shift+C)",
|
||||
});
|
||||
|
||||
list.Add(new ContextMenuResult
|
||||
{
|
||||
AcceleratorKey = Key.C,
|
||||
AcceleratorModifiers = ModifierKeys.Control,
|
||||
Action = _ => TryToCopyToClipBoard(entry.GetValueNameWithKey()),
|
||||
FontFamily = "Segoe MDL2 Assets",
|
||||
Glyph = "\xE8C8", // E8C8 => Symbol: Copy
|
||||
PluginName = assemblyName,
|
||||
Title = $"{Resources.CopyValueName} (Ctrl+C)",
|
||||
});
|
||||
}
|
||||
|
||||
list.Add(new ContextMenuResult
|
||||
{
|
||||
AcceleratorKey = Key.Enter,
|
||||
Action = _ => TryToOpenInRegistryEditor(entry),
|
||||
FontFamily = "Segoe MDL2 Assets",
|
||||
Glyph = "\xE8A7", // E8A7 => Symbol: OpenInNewWindow
|
||||
PluginName = assemblyName,
|
||||
Title = $"{Resources.OpenKeyInRegistryEditor} (Enter)",
|
||||
});
|
||||
|
||||
return list;
|
||||
}
|
||||
|
||||
#pragma warning disable CA1031 // Do not catch general exception types
|
||||
|
||||
/// <summary>
|
||||
/// Open the Windows registry editor and jump to registry key inside the given key (inside the <see cref="RegistryEntry"/>
|
||||
/// </summary>
|
||||
/// <param name="entry">The <see cref="RegistryEntry"/> to jump in</param>
|
||||
/// <returns><see langword="true"/> if the registry editor was successful open, otherwise <see langword="false"/></returns>
|
||||
internal static bool TryToOpenInRegistryEditor(in RegistryEntry entry)
|
||||
{
|
||||
try
|
||||
{
|
||||
RegistryHelper.OpenRegistryKey(entry.Key?.Name ?? entry.KeyPath);
|
||||
return true;
|
||||
}
|
||||
catch (System.ComponentModel.Win32Exception)
|
||||
{
|
||||
MessageBox.Show(
|
||||
Resources.OpenInRegistryEditorAccessExceptionText,
|
||||
Resources.OpenInRegistryEditorAccessExceptionTitle,
|
||||
MessageBoxButton.OK,
|
||||
MessageBoxImage.Error);
|
||||
return false;
|
||||
}
|
||||
catch (Exception exception)
|
||||
{
|
||||
Log.Exception("Error on opening Windows registry editor", exception, typeof(Main));
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Copy the given text to the clipboard
|
||||
/// </summary>
|
||||
/// <param name="text">The text to copy to the clipboard</param>
|
||||
/// <returns><see langword="true"/>The text successful copy to the clipboard, otherwise <see langword="false"/></returns>
|
||||
private static bool TryToCopyToClipBoard(in string text)
|
||||
{
|
||||
try
|
||||
{
|
||||
Clipboard.Clear();
|
||||
Clipboard.SetText(text);
|
||||
return true;
|
||||
}
|
||||
catch (Exception exception)
|
||||
{
|
||||
Log.Exception("Can't copy to clipboard", exception, typeof(Main));
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
#pragma warning restore CA1031 // Do not catch general exception types
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,98 @@
|
||||
// Copyright (c) Microsoft Corporation
|
||||
// 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;
|
||||
using System.Linq;
|
||||
using Microsoft.PowerToys.Run.Plugin.Registry.Constants;
|
||||
|
||||
namespace Microsoft.PowerToys.Run.Plugin.Registry.Helper
|
||||
{
|
||||
/// <summary>
|
||||
/// Helper class to easier work with queries
|
||||
/// </summary>
|
||||
internal static class QueryHelper
|
||||
{
|
||||
/// <summary>
|
||||
/// The character to distinguish if the search query contain multiple parts (typically "\\")
|
||||
/// </summary>
|
||||
internal const string QuerySplitCharacter = "\\\\";
|
||||
|
||||
/// <summary>
|
||||
/// A list that contain short names of all registry base keys
|
||||
/// </summary>
|
||||
private static readonly IReadOnlyDictionary<string, string> _shortBaseKeys = new Dictionary<string, string>(6)
|
||||
{
|
||||
{ Win32.Registry.ClassesRoot.Name, KeyName.ClassRootShort },
|
||||
{ Win32.Registry.CurrentConfig.Name, KeyName.CurrentConfigShort },
|
||||
{ Win32.Registry.CurrentUser.Name, KeyName.CurrentUserShort },
|
||||
{ Win32.Registry.LocalMachine.Name, KeyName.LocalMachineShort },
|
||||
{ Win32.Registry.PerformanceData.Name, KeyName.PerformanceDataShort },
|
||||
{ Win32.Registry.Users.Name, KeyName.UsersShort },
|
||||
};
|
||||
|
||||
/// <summary>
|
||||
/// Return the parts of a given query
|
||||
/// </summary>
|
||||
/// <param name="query">The query that could contain parts</param>
|
||||
/// <param name="queryKey">The key part of the query</param>
|
||||
/// <param name="queryValueName">The value name part of the query</param>
|
||||
/// <returns><see langword="true"/> when the query search for a key and a value name, otherwise <see langword="false"/></returns>
|
||||
internal static bool GetQueryParts(in string query, out string queryKey, out string queryValueName)
|
||||
{
|
||||
if (!query.Contains(QuerySplitCharacter, StringComparison.InvariantCultureIgnoreCase))
|
||||
{
|
||||
queryKey = query;
|
||||
queryValueName = string.Empty;
|
||||
return false;
|
||||
}
|
||||
|
||||
var querySplit = query.Split(QuerySplitCharacter);
|
||||
|
||||
queryKey = querySplit.FirstOrDefault();
|
||||
queryValueName = querySplit.LastOrDefault();
|
||||
return true;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Return a registry key with a long base key
|
||||
/// </summary>
|
||||
/// <param name="registryKey">A registry key with a short base key</param>
|
||||
/// <returns>A registry key with a long base key</returns>
|
||||
internal static string GetKeyWithLongBaseKey(in string registryKey)
|
||||
{
|
||||
foreach (var shortName in _shortBaseKeys)
|
||||
{
|
||||
if (!registryKey.StartsWith(shortName.Value, StringComparison.InvariantCultureIgnoreCase))
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
return registryKey.Replace(shortName.Value, shortName.Key, StringComparison.InvariantCultureIgnoreCase);
|
||||
}
|
||||
|
||||
return registryKey;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Return a registry key with a short base key (useful to reduce the text length of a registry key)
|
||||
/// </summary>
|
||||
/// <param name="registryKey">A registry key with a full base key</param>
|
||||
/// <returns>A registry key with a short base key</returns>
|
||||
internal static string GetKeyWithShortBaseKey(in string registryKey)
|
||||
{
|
||||
foreach (var shortName in _shortBaseKeys)
|
||||
{
|
||||
if (!registryKey.StartsWith(shortName.Key, StringComparison.InvariantCultureIgnoreCase))
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
return registryKey.Replace(shortName.Key, shortName.Value, StringComparison.InvariantCultureIgnoreCase);
|
||||
}
|
||||
|
||||
return registryKey;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,239 @@
|
||||
// Copyright (c) Microsoft Corporation
|
||||
// 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;
|
||||
using System.Collections.ObjectModel;
|
||||
using System.Diagnostics;
|
||||
using System.Linq;
|
||||
using Microsoft.PowerToys.Run.Plugin.Registry.Classes;
|
||||
using Microsoft.PowerToys.Run.Plugin.Registry.Constants;
|
||||
using Microsoft.PowerToys.Run.Plugin.Registry.Properties;
|
||||
using Microsoft.Win32;
|
||||
|
||||
namespace Microsoft.PowerToys.Run.Plugin.Registry.Helper
|
||||
{
|
||||
#pragma warning disable CA1031 // Do not catch general exception types
|
||||
|
||||
/// <summary>
|
||||
/// Helper class to easier work with the registry
|
||||
/// </summary>
|
||||
internal static class RegistryHelper
|
||||
{
|
||||
/// <summary>
|
||||
/// A list that contain all registry base keys in a long/full version and in a short version (e.g HKLM = HKEY_LOCAL_MACHINE)
|
||||
/// </summary>
|
||||
private static readonly IReadOnlyDictionary<string, RegistryKey> _baseKeys = new Dictionary<string, RegistryKey>(12)
|
||||
{
|
||||
{ KeyName.ClassRootShort, Win32.Registry.ClassesRoot },
|
||||
{ Win32.Registry.ClassesRoot.Name, Win32.Registry.ClassesRoot },
|
||||
{ KeyName.CurrentConfigShort, Win32.Registry.CurrentConfig },
|
||||
{ Win32.Registry.CurrentConfig.Name, Win32.Registry.CurrentConfig },
|
||||
{ KeyName.CurrentUserShort, Win32.Registry.CurrentUser },
|
||||
{ Win32.Registry.CurrentUser.Name, Win32.Registry.CurrentUser },
|
||||
{ KeyName.LocalMachineShort, Win32.Registry.LocalMachine },
|
||||
{ Win32.Registry.LocalMachine.Name, Win32.Registry.LocalMachine },
|
||||
{ KeyName.PerformanceDataShort, Win32.Registry.PerformanceData },
|
||||
{ Win32.Registry.PerformanceData.Name, Win32.Registry.PerformanceData },
|
||||
{ KeyName.UsersShort, Win32.Registry.Users },
|
||||
{ Win32.Registry.Users.Name, Win32.Registry.Users },
|
||||
};
|
||||
|
||||
/// <summary>
|
||||
/// Try to find registry base keys based on the given query
|
||||
/// </summary>
|
||||
/// <param name="query">The query to search</param>
|
||||
/// <returns>A combination of a list of base <see cref="RegistryKey"/> and the sub keys</returns>
|
||||
internal static (IEnumerable<RegistryKey>? baseKey, string subKey) GetRegistryBaseKey(in string query)
|
||||
{
|
||||
if (string.IsNullOrWhiteSpace(query))
|
||||
{
|
||||
return (null, string.Empty);
|
||||
}
|
||||
|
||||
var baseKey = query.Split('\\').FirstOrDefault();
|
||||
var subKey = query.Replace(baseKey, string.Empty, StringComparison.InvariantCultureIgnoreCase).TrimStart('\\');
|
||||
|
||||
var baseKeyResult = _baseKeys
|
||||
.Where(found => found.Key.StartsWith(baseKey, StringComparison.InvariantCultureIgnoreCase))
|
||||
.Select(found => found.Value)
|
||||
.Distinct();
|
||||
|
||||
return (baseKeyResult, subKey);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Return a list of all registry base key
|
||||
/// </summary>
|
||||
/// <returns>A list with all registry base keys</returns>
|
||||
internal static ICollection<RegistryEntry> GetAllBaseKeys()
|
||||
{
|
||||
return new Collection<RegistryEntry>
|
||||
{
|
||||
new RegistryEntry(Win32.Registry.ClassesRoot),
|
||||
new RegistryEntry(Win32.Registry.CurrentConfig),
|
||||
new RegistryEntry(Win32.Registry.CurrentUser),
|
||||
new RegistryEntry(Win32.Registry.LocalMachine),
|
||||
new RegistryEntry(Win32.Registry.PerformanceData),
|
||||
new RegistryEntry(Win32.Registry.Users),
|
||||
};
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Search for the given sub-key path in the given registry base key
|
||||
/// </summary>
|
||||
/// <param name="baseKey">The base <see cref="RegistryKey"/></param>
|
||||
/// <param name="subKeyPath">The path of the registry sub-key</param>
|
||||
/// <returns>A list with all found registry keys</returns>
|
||||
internal static ICollection<RegistryEntry> SearchForSubKey(in RegistryKey baseKey, in string subKeyPath)
|
||||
{
|
||||
if (string.IsNullOrEmpty(subKeyPath))
|
||||
{
|
||||
return FindSubKey(baseKey, string.Empty);
|
||||
}
|
||||
|
||||
var subKeysNames = subKeyPath.Split('\\');
|
||||
var index = 0;
|
||||
var subKey = baseKey;
|
||||
|
||||
ICollection<RegistryEntry> result;
|
||||
|
||||
do
|
||||
{
|
||||
result = FindSubKey(subKey, subKeysNames.ElementAtOrDefault(index));
|
||||
|
||||
if (result.Count == 0)
|
||||
{
|
||||
return FindSubKey(subKey, string.Empty);
|
||||
}
|
||||
|
||||
if (result.Count == 1 && index < subKeysNames.Length)
|
||||
{
|
||||
subKey = result.First().Key;
|
||||
}
|
||||
|
||||
if (result.Count > 1 || subKey == null)
|
||||
{
|
||||
break;
|
||||
}
|
||||
|
||||
index++;
|
||||
}
|
||||
while (index < subKeysNames.Length);
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Return a human readable summary of a given <see cref="RegistryKey"/>
|
||||
/// </summary>
|
||||
/// <param name="key">The <see cref="RegistryKey"/> for the summary</param>
|
||||
/// <returns>A human readable summary</returns>
|
||||
internal static string GetSummary(in RegistryKey key)
|
||||
{
|
||||
return $"{Resources.SubKeys} {key.SubKeyCount} - {Resources.Values} {key.ValueCount}";
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Open a given registry key in the registry editor
|
||||
/// </summary>
|
||||
/// <param name="fullKey">The registry key to open</param>
|
||||
internal static void OpenRegistryKey(in string fullKey)
|
||||
{
|
||||
// it's impossible to directly open a key via command-line option, so we must override the last remember key
|
||||
Win32.Registry.SetValue(@"HKEY_Current_User\Software\Microsoft\Windows\CurrentVersion\Applets\Regedit", "LastKey", fullKey);
|
||||
|
||||
var processStartInfo = new ProcessStartInfo
|
||||
{
|
||||
// -m => allow multi-instance (hidden start option)
|
||||
Arguments = "-m",
|
||||
|
||||
FileName = "regedit.exe",
|
||||
|
||||
// Start as administrator
|
||||
Verb = "runas",
|
||||
|
||||
// Start as administrator will not work without this
|
||||
UseShellExecute = true,
|
||||
};
|
||||
|
||||
Process.Start(processStartInfo);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Try to find the given registry sub-key in the given registry parent-key
|
||||
/// </summary>
|
||||
/// <param name="parentKey">The parent-key, also the root to start the search</param>
|
||||
/// <param name="searchSubKey">The sub-key to find</param>
|
||||
/// <returns>A list with all found registry sub-keys</returns>
|
||||
private static ICollection<RegistryEntry> FindSubKey(in RegistryKey parentKey, in string searchSubKey)
|
||||
{
|
||||
var list = new Collection<RegistryEntry>();
|
||||
|
||||
try
|
||||
{
|
||||
foreach (var subKey in parentKey.GetSubKeyNames().OrderBy(found => found))
|
||||
{
|
||||
if (!subKey.StartsWith(searchSubKey, StringComparison.InvariantCultureIgnoreCase))
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
if (string.Equals(subKey, searchSubKey, StringComparison.InvariantCultureIgnoreCase))
|
||||
{
|
||||
list.Add(new RegistryEntry(parentKey.OpenSubKey(subKey, RegistryKeyPermissionCheck.ReadSubTree)));
|
||||
return list;
|
||||
}
|
||||
|
||||
try
|
||||
{
|
||||
list.Add(new RegistryEntry(parentKey.OpenSubKey(subKey, RegistryKeyPermissionCheck.ReadSubTree)));
|
||||
}
|
||||
catch (Exception exception)
|
||||
{
|
||||
list.Add(new RegistryEntry($"{parentKey.Name}\\{subKey}", exception));
|
||||
}
|
||||
}
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
list.Add(new RegistryEntry(parentKey.Name, ex));
|
||||
}
|
||||
|
||||
return list;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Return a list with a registry sub-keys of the given registry parent-key
|
||||
/// </summary>
|
||||
/// <param name="parentKey">The registry parent-key</param>
|
||||
/// <param name="maxCount">(optional) The maximum count of the results</param>
|
||||
/// <returns>A list with all found registry sub-keys</returns>
|
||||
private static ICollection<RegistryEntry> GetAllSubKeys(in RegistryKey parentKey, in int maxCount = 50)
|
||||
{
|
||||
var list = new Collection<RegistryEntry>();
|
||||
|
||||
try
|
||||
{
|
||||
foreach (var subKey in parentKey.GetSubKeyNames())
|
||||
{
|
||||
if (list.Count >= maxCount)
|
||||
{
|
||||
break;
|
||||
}
|
||||
|
||||
list.Add(new RegistryEntry(parentKey));
|
||||
}
|
||||
}
|
||||
catch (Exception exception)
|
||||
{
|
||||
list.Add(new RegistryEntry(parentKey.Name, exception));
|
||||
}
|
||||
|
||||
return list;
|
||||
}
|
||||
}
|
||||
|
||||
#pragma warning restore CA1031 // Do not catch general exception types
|
||||
}
|
||||
@@ -0,0 +1,219 @@
|
||||
// Copyright (c) Microsoft Corporation
|
||||
// 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;
|
||||
using System.Linq;
|
||||
using Microsoft.PowerToys.Run.Plugin.Registry.Classes;
|
||||
using Microsoft.PowerToys.Run.Plugin.Registry.Constants;
|
||||
using Microsoft.PowerToys.Run.Plugin.Registry.Enumerations;
|
||||
using Microsoft.PowerToys.Run.Plugin.Registry.Properties;
|
||||
using Microsoft.Win32;
|
||||
using Wox.Plugin;
|
||||
|
||||
namespace Microsoft.PowerToys.Run.Plugin.Registry.Helper
|
||||
{
|
||||
/// <summary>
|
||||
/// Helper class to easier work with results
|
||||
/// </summary>
|
||||
internal static class ResultHelper
|
||||
{
|
||||
#pragma warning disable CA1031 // Do not catch general exception types
|
||||
|
||||
/// <summary>
|
||||
/// Return a list with <see cref="Result"/>s, based on the given list
|
||||
/// </summary>
|
||||
/// <param name="list">The original result list to convert</param>
|
||||
/// <param name="iconPath">The path to the icon of each entry</param>
|
||||
/// <returns>A list with <see cref="Result"/></returns>
|
||||
internal static List<Result> GetResultList(in IEnumerable<RegistryEntry> list, in string iconPath)
|
||||
{
|
||||
var resultList = new List<Result>();
|
||||
|
||||
foreach (var entry in list)
|
||||
{
|
||||
var result = new Result
|
||||
{
|
||||
IcoPath = iconPath,
|
||||
};
|
||||
|
||||
if (entry.Exception is null && !(entry.Key is null))
|
||||
{
|
||||
// when key contains keys or fields
|
||||
result.QueryTextDisplay = entry.Key.Name;
|
||||
result.SubTitle = RegistryHelper.GetSummary(entry.Key);
|
||||
result.Title = GetTruncatedText(entry.Key.Name, MaxTextLength.MaximumTitleLengthWithTwoSymbols);
|
||||
}
|
||||
else if (entry.Key is null && !(entry.Exception is null))
|
||||
{
|
||||
// on error (e.g access denied)
|
||||
result.QueryTextDisplay = entry.KeyPath;
|
||||
result.SubTitle = GetTruncatedText(entry.Exception.Message, MaxTextLength.MaximumSubTitleLengthWithTwoSymbols, TruncateSide.OnlyFromRight);
|
||||
result.Title = GetTruncatedText(entry.KeyPath, MaxTextLength.MaximumTitleLengthWithTwoSymbols);
|
||||
}
|
||||
else
|
||||
{
|
||||
result.QueryTextDisplay = entry.KeyPath;
|
||||
result.Title = GetTruncatedText(entry.KeyPath, MaxTextLength.MaximumTitleLengthWithTwoSymbols);
|
||||
}
|
||||
|
||||
result.Action = (_) => ContextMenuHelper.TryToOpenInRegistryEditor(entry);
|
||||
result.ContextData = entry;
|
||||
result.ToolTipData = new ToolTipData(Resources.RegistryKey, $"{Resources.KeyName}\t{result.Title}");
|
||||
|
||||
resultList.Add(result);
|
||||
}
|
||||
|
||||
return resultList;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Return a list with <see cref="Result"/>s, based on the given <see cref="RegistryKey"/>
|
||||
/// </summary>
|
||||
/// <param name="key">The <see cref="RegistryKey"/> that should contain entries for the list</param>
|
||||
/// <param name="iconPath">The path to the icon of each entry</param>
|
||||
/// <param name="searchValue">(optional) When not <see cref="string.Empty"/> filter the list for the given value name and value</param>
|
||||
/// <returns>A list with <see cref="Result"/></returns>
|
||||
internal static List<Result> GetValuesFromKey(in RegistryKey? key, in string iconPath, string searchValue = "")
|
||||
{
|
||||
if (key is null)
|
||||
{
|
||||
return new List<Result>(0);
|
||||
}
|
||||
|
||||
ICollection<KeyValuePair<string, object>> valueList = new List<KeyValuePair<string, object>>(key.ValueCount);
|
||||
|
||||
var resultList = new List<Result>();
|
||||
|
||||
try
|
||||
{
|
||||
var valueNames = key.GetValueNames();
|
||||
|
||||
try
|
||||
{
|
||||
foreach (var valueName in valueNames)
|
||||
{
|
||||
valueList.Add(KeyValuePair.Create(valueName, key.GetValue(valueName)));
|
||||
}
|
||||
}
|
||||
catch (Exception valueException)
|
||||
{
|
||||
var registryEntry = new RegistryEntry(key.Name, valueException);
|
||||
|
||||
resultList.Add(new Result
|
||||
{
|
||||
ContextData = registryEntry,
|
||||
IcoPath = iconPath,
|
||||
SubTitle = GetTruncatedText(valueException.Message, MaxTextLength.MaximumSubTitleLengthWithThreeSymbols, TruncateSide.OnlyFromRight),
|
||||
Title = GetTruncatedText(key.Name, MaxTextLength.MaximumTitleLengthWithThreeSymbols),
|
||||
ToolTipData = new ToolTipData(valueException.Message, valueException.ToString()),
|
||||
Action = (_) => ContextMenuHelper.TryToOpenInRegistryEditor(registryEntry),
|
||||
QueryTextDisplay = key.Name,
|
||||
});
|
||||
}
|
||||
|
||||
if (!string.IsNullOrEmpty(searchValue))
|
||||
{
|
||||
var filteredValueName = valueList.Where(found => found.Key.Contains(searchValue, StringComparison.InvariantCultureIgnoreCase));
|
||||
var filteredValueList = valueList.Where(found => found.Value.ToString()?.Contains(searchValue, StringComparison.InvariantCultureIgnoreCase) ?? false);
|
||||
|
||||
valueList = filteredValueName.Concat(filteredValueList).Distinct().ToList();
|
||||
}
|
||||
|
||||
foreach (var valueEntry in valueList.OrderBy(found => found.Key))
|
||||
{
|
||||
var valueName = valueEntry.Key;
|
||||
if (string.IsNullOrEmpty(valueName))
|
||||
{
|
||||
valueName = "(Default)";
|
||||
}
|
||||
|
||||
var registryEntry = new RegistryEntry(key, valueEntry.Key, valueEntry.Value);
|
||||
|
||||
resultList.Add(new Result
|
||||
{
|
||||
ContextData = registryEntry,
|
||||
IcoPath = iconPath,
|
||||
SubTitle = GetTruncatedText(GetSubTileForRegistryValue(key, valueEntry), MaxTextLength.MaximumSubTitleLengthWithThreeSymbols, TruncateSide.OnlyFromRight),
|
||||
Title = GetTruncatedText(valueName, MaxTextLength.MaximumTitleLengthWithThreeSymbols),
|
||||
ToolTipData = new ToolTipData(Resources.RegistryValue, GetToolTipTextForRegistryValue(key, valueEntry)),
|
||||
Action = (_) => ContextMenuHelper.TryToOpenInRegistryEditor(registryEntry),
|
||||
|
||||
// Avoid user handling interrupt when move up/down inside the results of a registry key
|
||||
QueryTextDisplay = $"{key.Name}{QueryHelper.QuerySplitCharacter}",
|
||||
});
|
||||
}
|
||||
}
|
||||
catch (Exception exception)
|
||||
{
|
||||
var registryEntry = new RegistryEntry(key.Name, exception);
|
||||
|
||||
resultList.Add(new Result
|
||||
{
|
||||
ContextData = registryEntry,
|
||||
IcoPath = iconPath,
|
||||
SubTitle = GetTruncatedText(exception.Message, MaxTextLength.MaximumSubTitleLengthWithThreeSymbols, TruncateSide.OnlyFromRight),
|
||||
Title = GetTruncatedText(key.Name, MaxTextLength.MaximumTitleLengthWithThreeSymbols),
|
||||
ToolTipData = new ToolTipData(exception.Message, exception.ToString()),
|
||||
Action = (_) => ContextMenuHelper.TryToOpenInRegistryEditor(registryEntry),
|
||||
QueryTextDisplay = key.Name,
|
||||
});
|
||||
}
|
||||
|
||||
return resultList;
|
||||
}
|
||||
|
||||
#pragma warning restore CA1031 // Do not catch general exception types
|
||||
|
||||
/// <summary>
|
||||
/// Return a truncated name
|
||||
/// </summary>
|
||||
/// <param name="text">The text to truncate</param>
|
||||
/// <param name="maxLength">The maximum length of the text</param>
|
||||
/// <param name="truncateSide">(optional) The side of the truncate</param>
|
||||
/// <returns>A truncated text with a maximum length</returns>
|
||||
internal static string GetTruncatedText(string text, in int maxLength, TruncateSide truncateSide = TruncateSide.OnlyFromLeft)
|
||||
{
|
||||
if (truncateSide == TruncateSide.OnlyFromLeft)
|
||||
{
|
||||
if (text.Length > maxLength)
|
||||
{
|
||||
text = QueryHelper.GetKeyWithShortBaseKey(text);
|
||||
}
|
||||
|
||||
return text.Length > maxLength ? $"...{text[^maxLength..]}" : text;
|
||||
}
|
||||
else
|
||||
{
|
||||
return text.Length > maxLength ? $"{text[0..maxLength]}..." : text;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Return the tool-tip text for a registry value
|
||||
/// </summary>
|
||||
/// <param name="key">The registry key for the tool-tip</param>
|
||||
/// <param name="valueEntry">The value name and value of the registry value</param>
|
||||
/// <returns>A tool-tip text</returns>
|
||||
private static string GetToolTipTextForRegistryValue(RegistryKey key, KeyValuePair<string, object> valueEntry)
|
||||
{
|
||||
return $"{Resources.KeyName}\t{key.Name}{Environment.NewLine}"
|
||||
+ $"{Resources.Name}\t{valueEntry.Key}{Environment.NewLine}"
|
||||
+ $"{Resources.Type}\t{ValueHelper.GetType(key, valueEntry.Key)}{Environment.NewLine}"
|
||||
+ $"{Resources.Value}\t{ValueHelper.GetValue(key, valueEntry.Key)}";
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Return the sub-title text for a registry value
|
||||
/// </summary>
|
||||
/// <param name="key">The registry key for the sub-title</param>
|
||||
/// <param name="valueEntry">The value name and value of the registry value</param>
|
||||
/// <returns>A sub-title text</returns>
|
||||
private static string GetSubTileForRegistryValue(RegistryKey key, KeyValuePair<string, object> valueEntry)
|
||||
{
|
||||
return $"{Resources.Type} {ValueHelper.GetType(key, valueEntry.Key)}"
|
||||
+ $" - {Resources.Value} {ValueHelper.GetValue(key, valueEntry.Key, 50)}";
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,63 @@
|
||||
// Copyright (c) Microsoft Corporation
|
||||
// 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.Linq;
|
||||
using Microsoft.PowerToys.Run.Plugin.Registry.Properties;
|
||||
using Microsoft.Win32;
|
||||
|
||||
namespace Microsoft.PowerToys.Run.Plugin.Registry.Helper
|
||||
{
|
||||
/// <summary>
|
||||
/// Helper class to easier work with values of a <see cref="RegistryKey"/>
|
||||
/// </summary>
|
||||
internal static class ValueHelper
|
||||
{
|
||||
/// <summary>
|
||||
/// Return a human readable value data, of the given value name inside the given <see cref="RegistryKey"/>
|
||||
/// </summary>
|
||||
/// <param name="key">The <see cref="RegistryKey"/> that should contain the value name.</param>
|
||||
/// <param name="valueName">The name of the value.</param>
|
||||
/// <param name="maxLength">The maximum length for the human readable value.</param>
|
||||
/// <returns>A human readable value data.</returns>
|
||||
internal static string GetValue(in RegistryKey key, in string valueName, int maxLength = int.MaxValue)
|
||||
{
|
||||
var unformattedValue = key.GetValue(valueName);
|
||||
|
||||
var valueData = key.GetValueKind(valueName) switch
|
||||
{
|
||||
RegistryValueKind.DWord => $"0x{unformattedValue:X8} ({(uint)(int)unformattedValue})",
|
||||
RegistryValueKind.QWord => $"0x{unformattedValue:X16} ({(ulong)(long)unformattedValue})",
|
||||
RegistryValueKind.Binary => (unformattedValue as byte[]).Aggregate(string.Empty, (current, singleByte) => $"{current} {singleByte:X2}"),
|
||||
_ => $"{unformattedValue}",
|
||||
};
|
||||
|
||||
return valueData.Length > maxLength
|
||||
? $"{valueData.Substring(0, maxLength)}..."
|
||||
: valueData;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Return the registry type name of a given value name inside a given <see cref="RegistryKey"/>
|
||||
/// </summary>
|
||||
/// <param name="key">The <see cref="RegistryKey"/> that should contain the value name</param>
|
||||
/// <param name="valueName">The name of the value</param>
|
||||
/// <returns>A registry type name</returns>
|
||||
internal static object GetType(RegistryKey key, string valueName)
|
||||
{
|
||||
return key.GetValueKind(valueName) switch
|
||||
{
|
||||
RegistryValueKind.None => Resources.RegistryValueKindNone,
|
||||
RegistryValueKind.Unknown => Resources.RegistryValueKindUnknown,
|
||||
RegistryValueKind.String => "REG_SZ",
|
||||
RegistryValueKind.ExpandString => "REG_EXPAND_SZ",
|
||||
RegistryValueKind.MultiString => "REG_MULTI_SZ",
|
||||
RegistryValueKind.Binary => "REG_BINARY",
|
||||
RegistryValueKind.DWord => "REG_DWORD",
|
||||
RegistryValueKind.QWord => "REG_QWORD",
|
||||
_ => throw new ArgumentOutOfRangeException(nameof(valueName)),
|
||||
};
|
||||
}
|
||||
}
|
||||
}
|
||||
Binary file not shown.
|
After Width: | Height: | Size: 2.3 KiB |
Binary file not shown.
|
After Width: | Height: | Size: 2.3 KiB |
@@ -0,0 +1,173 @@
|
||||
// Copyright (c) Microsoft Corporation
|
||||
// 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;
|
||||
using System.Linq;
|
||||
using System.Reflection;
|
||||
using System.Runtime.CompilerServices;
|
||||
using ManagedCommon;
|
||||
using Microsoft.PowerToys.Run.Plugin.Registry.Classes;
|
||||
using Microsoft.PowerToys.Run.Plugin.Registry.Helper;
|
||||
using Microsoft.PowerToys.Run.Plugin.Registry.Properties;
|
||||
using Wox.Plugin;
|
||||
|
||||
[assembly: InternalsVisibleTo("Microsoft.PowerToys.Run.Plugin.Registry.UnitTests")]
|
||||
|
||||
namespace Microsoft.PowerToys.Run.Plugin.Registry
|
||||
{
|
||||
/// <summary>
|
||||
/// Main class of this plugin that implement all used interfaces
|
||||
/// </summary>
|
||||
public class Main : IPlugin, IContextMenu, IPluginI18n, IDisposable
|
||||
{
|
||||
/// <summary>
|
||||
/// The name of this assembly
|
||||
/// </summary>
|
||||
private readonly string _assemblyName;
|
||||
|
||||
/// <summary>
|
||||
/// The initial context for this plugin (contains API and meta-data)
|
||||
/// </summary>
|
||||
private PluginInitContext? _context;
|
||||
|
||||
/// <summary>
|
||||
/// The path to the icon for each result
|
||||
/// </summary>
|
||||
private string _defaultIconPath;
|
||||
|
||||
/// <summary>
|
||||
/// Indicate that the plugin is disposed
|
||||
/// </summary>
|
||||
private bool _disposed;
|
||||
|
||||
/// <summary>
|
||||
/// Initializes a new instance of the <see cref="Main"/> class.
|
||||
/// </summary>
|
||||
public Main()
|
||||
{
|
||||
_assemblyName = Assembly.GetExecutingAssembly().GetName().Name ?? GetTranslatedPluginTitle();
|
||||
_defaultIconPath = "Images/reg.light.png";
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Initialize the plugin with the given <see cref="PluginInitContext"/>
|
||||
/// </summary>
|
||||
/// <param name="context">The <see cref="PluginInitContext"/> for this plugin</param>
|
||||
public void Init(PluginInitContext context)
|
||||
{
|
||||
_context = context ?? throw new ArgumentNullException(nameof(context));
|
||||
_context.API.ThemeChanged += OnThemeChanged;
|
||||
UpdateIconPath(_context.API.GetCurrentTheme());
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Return a filtered list, based on the given query
|
||||
/// </summary>
|
||||
/// <param name="query">The query to filter the list</param>
|
||||
/// <returns>A filtered list, can be empty when nothing was found</returns>
|
||||
public List<Result> Query(Query query)
|
||||
{
|
||||
if (query?.Search is null)
|
||||
{
|
||||
return new List<Result>(0);
|
||||
}
|
||||
|
||||
var searchForValueName = QueryHelper.GetQueryParts(query.Search, out var queryKey, out var queryValueName);
|
||||
|
||||
var (baseKeyList, subKey) = RegistryHelper.GetRegistryBaseKey(queryKey);
|
||||
if (baseKeyList is null)
|
||||
{
|
||||
// no base key found
|
||||
return ResultHelper.GetResultList(RegistryHelper.GetAllBaseKeys(), _defaultIconPath);
|
||||
}
|
||||
else if (baseKeyList.Count() > 1)
|
||||
{
|
||||
// more than one base key was found -> show results
|
||||
return ResultHelper.GetResultList(baseKeyList.Select(found => new RegistryEntry(found)), _defaultIconPath);
|
||||
}
|
||||
|
||||
// only one base key was found -> start search for the sub-key
|
||||
var list = RegistryHelper.SearchForSubKey(baseKeyList.First(), subKey);
|
||||
|
||||
// when only one sub-key was found and a user search for values ("\\")
|
||||
// show the filtered list of values of one sub-key
|
||||
if (searchForValueName && list.Count == 1)
|
||||
{
|
||||
return ResultHelper.GetValuesFromKey(list.First().Key, _defaultIconPath, queryValueName);
|
||||
}
|
||||
|
||||
return ResultHelper.GetResultList(list, _defaultIconPath);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Return a list context menu entries for a given <see cref="Result"/> (shown at the right side of the result)
|
||||
/// </summary>
|
||||
/// <param name="selectedResult">The <see cref="Result"/> for the list with context menu entries</param>
|
||||
/// <returns>A list context menu entries</returns>
|
||||
public List<ContextMenuResult> LoadContextMenus(Result selectedResult)
|
||||
{
|
||||
return ContextMenuHelper.GetContextMenu(selectedResult, _assemblyName);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Change all theme-based elements (typical called when the plugin theme has changed)
|
||||
/// </summary>
|
||||
/// <param name="oldtheme">The old <see cref="Theme"/></param>
|
||||
/// <param name="newTheme">The new <see cref="Theme"/></param>
|
||||
private void OnThemeChanged(Theme oldtheme, Theme newTheme)
|
||||
{
|
||||
UpdateIconPath(newTheme);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Update all icons (typical called when the plugin theme has changed)
|
||||
/// </summary>
|
||||
/// <param name="theme">The new <see cref="Theme"/> for the icons</param>
|
||||
private void UpdateIconPath(Theme theme)
|
||||
{
|
||||
_defaultIconPath = theme == Theme.Light || theme == Theme.HighContrastWhite
|
||||
? "Images/reg.light.png"
|
||||
: "Images/reg.dark.png";
|
||||
}
|
||||
|
||||
/// <inheritdoc/>
|
||||
public void Dispose()
|
||||
{
|
||||
Dispose(true);
|
||||
GC.SuppressFinalize(this);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Wrapper method for <see cref="Dispose"/> that dispose additional objects and events form the plugin itself
|
||||
/// </summary>
|
||||
/// <param name="disposing">Indicate that the plugin is disposed</param>
|
||||
protected virtual void Dispose(bool disposing)
|
||||
{
|
||||
if (_disposed || !disposing)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
if (!(_context is null))
|
||||
{
|
||||
_context.API.ThemeChanged -= OnThemeChanged;
|
||||
}
|
||||
|
||||
_disposed = true;
|
||||
}
|
||||
|
||||
/// <inheritdoc/>
|
||||
public string GetTranslatedPluginTitle()
|
||||
{
|
||||
return Resources.PluginTitle;
|
||||
}
|
||||
|
||||
/// <inheritdoc/>
|
||||
public string GetTranslatedPluginDescription()
|
||||
{
|
||||
return Resources.PluginDescription;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,105 @@
|
||||
<Project Sdk="Microsoft.NET.Sdk">
|
||||
|
||||
<PropertyGroup>
|
||||
<TargetFramework>netcoreapp3.1</TargetFramework>
|
||||
<RootNamespace>Microsoft.PowerToys.Run.Plugin.Registry</RootNamespace>
|
||||
<AssemblyName>Microsoft.PowerToys.Run.Plugin.Registry</AssemblyName>
|
||||
<AppendTargetFrameworkToOutputPath>false</AppendTargetFrameworkToOutputPath>
|
||||
<AppendRuntimeIdentifierToOutputPath>false</AppendRuntimeIdentifierToOutputPath>
|
||||
<Platforms>x64</Platforms>
|
||||
<NeutralLanguage>en-US</NeutralLanguage>
|
||||
<LangVersion>8.0</LangVersion>
|
||||
<Nullable>enable</Nullable>
|
||||
</PropertyGroup>
|
||||
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
|
||||
<DebugSymbols>true</DebugSymbols>
|
||||
<OutputPath>..\..\..\..\..\x64\Debug\modules\launcher\Plugins\Microsoft.PowerToys.Run.Plugin.Registry\</OutputPath>
|
||||
<DefineConstants>DEBUG;TRACE</DefineConstants>
|
||||
<DebugType>full</DebugType>
|
||||
<PlatformTarget>x64</PlatformTarget>
|
||||
<ErrorReport>prompt</ErrorReport>
|
||||
<CodeAnalysisRuleSet>MinimumRecommendedRules.ruleset</CodeAnalysisRuleSet>
|
||||
<WarningLevel>4</WarningLevel>
|
||||
<Optimize>false</Optimize>
|
||||
<TreatWarningsAsErrors>true</TreatWarningsAsErrors>
|
||||
</PropertyGroup>
|
||||
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
|
||||
<OutputPath>..\..\..\..\..\x64\Release\modules\launcher\Plugins\Microsoft.PowerToys.Run.Plugin.Registry\</OutputPath>
|
||||
<DefineConstants>TRACE</DefineConstants>
|
||||
<Optimize>true</Optimize>
|
||||
<DebugType>pdbonly</DebugType>
|
||||
<PlatformTarget>x64</PlatformTarget>
|
||||
<ErrorReport>prompt</ErrorReport>
|
||||
<CodeAnalysisRuleSet>MinimumRecommendedRules.ruleset</CodeAnalysisRuleSet>
|
||||
<WarningLevel>4</WarningLevel>
|
||||
<TreatWarningsAsErrors>true</TreatWarningsAsErrors>
|
||||
</PropertyGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<Compile Remove="Languages\**" />
|
||||
<EmbeddedResource Remove="Languages\**" />
|
||||
<None Remove="Languages\**" />
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<Compile Include="..\..\..\..\codeAnalysis\GlobalSuppressions.cs">
|
||||
<Link>GlobalSuppressions.cs</Link>
|
||||
</Compile>
|
||||
<AdditionalFiles Include="..\..\..\..\codeAnalysis\StyleCop.json">
|
||||
<Link>StyleCop.json</Link>
|
||||
</AdditionalFiles>
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<ProjectReference Include="..\..\Wox.Infrastructure\Wox.Infrastructure.csproj">
|
||||
<Private>false</Private>
|
||||
</ProjectReference>
|
||||
<ProjectReference Include="..\..\Wox.Plugin\Wox.Plugin.csproj">
|
||||
<Private>false</Private>
|
||||
</ProjectReference>
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<None Include="plugin.json">
|
||||
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
|
||||
</None>
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<PackageReference Include="Microsoft.CodeAnalysis.FxCopAnalyzers" Version="3.3.0">
|
||||
<PrivateAssets>all</PrivateAssets>
|
||||
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
|
||||
</PackageReference>
|
||||
<PackageReference Include="StyleCop.Analyzers" Version="1.1.118">
|
||||
<PrivateAssets>all</PrivateAssets>
|
||||
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
|
||||
</PackageReference>
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<Compile Update="Properties\Resources.Designer.cs">
|
||||
<DesignTime>True</DesignTime>
|
||||
<AutoGen>True</AutoGen>
|
||||
<DependentUpon>Resources.resx</DependentUpon>
|
||||
</Compile>
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<EmbeddedResource Update="Properties\Resources.resx">
|
||||
<Generator>ResXFileCodeGenerator</Generator>
|
||||
<LastGenOutput>Resources.Designer.cs</LastGenOutput>
|
||||
</EmbeddedResource>
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<None Update="Images\reg.dark.png">
|
||||
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
|
||||
</None>
|
||||
<None Update="Images\reg.light.png">
|
||||
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
|
||||
</None>
|
||||
</ItemGroup>
|
||||
|
||||
</Project>
|
||||
225
src/modules/launcher/Plugins/Microsoft.PowerToys.Run.Plugin.Registry/Properties/Resources.Designer.cs
generated
Normal file
225
src/modules/launcher/Plugins/Microsoft.PowerToys.Run.Plugin.Registry/Properties/Resources.Designer.cs
generated
Normal file
@@ -0,0 +1,225 @@
|
||||
//------------------------------------------------------------------------------
|
||||
// <auto-generated>
|
||||
// This code was generated by a tool.
|
||||
// Runtime Version:4.0.30319.42000
|
||||
//
|
||||
// Changes to this file may cause incorrect behavior and will be lost if
|
||||
// the code is regenerated.
|
||||
// </auto-generated>
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
namespace Microsoft.PowerToys.Run.Plugin.Registry.Properties {
|
||||
using System;
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// A strongly-typed resource class, for looking up localized strings, etc.
|
||||
/// </summary>
|
||||
// This class was auto-generated by the StronglyTypedResourceBuilder
|
||||
// class via a tool like ResGen or Visual Studio.
|
||||
// To add or remove a member, edit your .ResX file then rerun ResGen
|
||||
// with the /str option, or rebuild your VS project.
|
||||
[global::System.CodeDom.Compiler.GeneratedCodeAttribute("System.Resources.Tools.StronglyTypedResourceBuilder", "16.0.0.0")]
|
||||
[global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
|
||||
[global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()]
|
||||
internal class Resources {
|
||||
|
||||
private static global::System.Resources.ResourceManager resourceMan;
|
||||
|
||||
private static global::System.Globalization.CultureInfo resourceCulture;
|
||||
|
||||
[global::System.Diagnostics.CodeAnalysis.SuppressMessageAttribute("Microsoft.Performance", "CA1811:AvoidUncalledPrivateCode")]
|
||||
internal Resources() {
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Returns the cached ResourceManager instance used by this class.
|
||||
/// </summary>
|
||||
[global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)]
|
||||
internal static global::System.Resources.ResourceManager ResourceManager {
|
||||
get {
|
||||
if (object.ReferenceEquals(resourceMan, null)) {
|
||||
global::System.Resources.ResourceManager temp = new global::System.Resources.ResourceManager("Microsoft.PowerToys.Run.Plugin.Registry.Properties.Resources", typeof(Resources).Assembly);
|
||||
resourceMan = temp;
|
||||
}
|
||||
return resourceMan;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Overrides the current thread's CurrentUICulture property for all
|
||||
/// resource lookups using this strongly typed resource class.
|
||||
/// </summary>
|
||||
[global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)]
|
||||
internal static global::System.Globalization.CultureInfo Culture {
|
||||
get {
|
||||
return resourceCulture;
|
||||
}
|
||||
set {
|
||||
resourceCulture = value;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Looks up a localized string similar to Copy key name (path).
|
||||
/// </summary>
|
||||
internal static string CopyKeyNamePath {
|
||||
get {
|
||||
return ResourceManager.GetString("CopyKeyNamePath", resourceCulture);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Looks up a localized string similar to Copy value data.
|
||||
/// </summary>
|
||||
internal static string CopyValueData {
|
||||
get {
|
||||
return ResourceManager.GetString("CopyValueData", resourceCulture);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Looks up a localized string similar to Copy value name.
|
||||
/// </summary>
|
||||
internal static string CopyValueName {
|
||||
get {
|
||||
return ResourceManager.GetString("CopyValueName", resourceCulture);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Looks up a localized string similar to Key name:.
|
||||
/// </summary>
|
||||
internal static string KeyName {
|
||||
get {
|
||||
return ResourceManager.GetString("KeyName", resourceCulture);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Looks up a localized string similar to Name:.
|
||||
/// </summary>
|
||||
internal static string Name {
|
||||
get {
|
||||
return ResourceManager.GetString("Name", resourceCulture);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Looks up a localized string similar to You do not have enough rights to open the Windows registry editor.
|
||||
/// </summary>
|
||||
internal static string OpenInRegistryEditorAccessExceptionText {
|
||||
get {
|
||||
return ResourceManager.GetString("OpenInRegistryEditorAccessExceptionText", resourceCulture);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Looks up a localized string similar to Error on open registry editor.
|
||||
/// </summary>
|
||||
internal static string OpenInRegistryEditorAccessExceptionTitle {
|
||||
get {
|
||||
return ResourceManager.GetString("OpenInRegistryEditorAccessExceptionTitle", resourceCulture);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Looks up a localized string similar to Open key in registry editor.
|
||||
/// </summary>
|
||||
internal static string OpenKeyInRegistryEditor {
|
||||
get {
|
||||
return ResourceManager.GetString("OpenKeyInRegistryEditor", resourceCulture);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Looks up a localized string similar to Search inside the Windows Registry.
|
||||
/// </summary>
|
||||
internal static string PluginDescription {
|
||||
get {
|
||||
return ResourceManager.GetString("PluginDescription", resourceCulture);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Looks up a localized string similar to Registry Plugin.
|
||||
/// </summary>
|
||||
internal static string PluginTitle {
|
||||
get {
|
||||
return ResourceManager.GetString("PluginTitle", resourceCulture);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Looks up a localized string similar to Registry key.
|
||||
/// </summary>
|
||||
internal static string RegistryKey {
|
||||
get {
|
||||
return ResourceManager.GetString("RegistryKey", resourceCulture);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Looks up a localized string similar to Registry value.
|
||||
/// </summary>
|
||||
internal static string RegistryValue {
|
||||
get {
|
||||
return ResourceManager.GetString("RegistryValue", resourceCulture);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Looks up a localized string similar to No data type.
|
||||
/// </summary>
|
||||
internal static string RegistryValueKindNone {
|
||||
get {
|
||||
return ResourceManager.GetString("RegistryValueKindNone", resourceCulture);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Looks up a localized string similar to Unsupported data type.
|
||||
/// </summary>
|
||||
internal static string RegistryValueKindUnknown {
|
||||
get {
|
||||
return ResourceManager.GetString("RegistryValueKindUnknown", resourceCulture);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Looks up a localized string similar to Subkeys:.
|
||||
/// </summary>
|
||||
internal static string SubKeys {
|
||||
get {
|
||||
return ResourceManager.GetString("SubKeys", resourceCulture);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Looks up a localized string similar to Type:.
|
||||
/// </summary>
|
||||
internal static string Type {
|
||||
get {
|
||||
return ResourceManager.GetString("Type", resourceCulture);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Looks up a localized string similar to Value:.
|
||||
/// </summary>
|
||||
internal static string Value {
|
||||
get {
|
||||
return ResourceManager.GetString("Value", resourceCulture);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Looks up a localized string similar to Values:.
|
||||
/// </summary>
|
||||
internal static string Values {
|
||||
get {
|
||||
return ResourceManager.GetString("Values", resourceCulture);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,182 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<root>
|
||||
<!--
|
||||
Microsoft ResX Schema
|
||||
|
||||
Version 2.0
|
||||
|
||||
The primary goals of this format is to allow a simple XML format
|
||||
that is mostly human readable. The generation and parsing of the
|
||||
various data types are done through the TypeConverter classes
|
||||
associated with the data types.
|
||||
|
||||
Example:
|
||||
|
||||
... ado.net/XML headers & schema ...
|
||||
<resheader name="resmimetype">text/microsoft-resx</resheader>
|
||||
<resheader name="version">2.0</resheader>
|
||||
<resheader name="reader">System.Resources.ResXResourceReader, System.Windows.Forms, ...</resheader>
|
||||
<resheader name="writer">System.Resources.ResXResourceWriter, System.Windows.Forms, ...</resheader>
|
||||
<data name="Name1"><value>this is my long string</value><comment>this is a comment</comment></data>
|
||||
<data name="Color1" type="System.Drawing.Color, System.Drawing">Blue</data>
|
||||
<data name="Bitmap1" mimetype="application/x-microsoft.net.object.binary.base64">
|
||||
<value>[base64 mime encoded serialized .NET Framework object]</value>
|
||||
</data>
|
||||
<data name="Icon1" type="System.Drawing.Icon, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64">
|
||||
<value>[base64 mime encoded string representing a byte array form of the .NET Framework object]</value>
|
||||
<comment>This is a comment</comment>
|
||||
</data>
|
||||
|
||||
There are any number of "resheader" rows that contain simple
|
||||
name/value pairs.
|
||||
|
||||
Each data row contains a name, and value. The row also contains a
|
||||
type or mimetype. Type corresponds to a .NET class that support
|
||||
text/value conversion through the TypeConverter architecture.
|
||||
Classes that don't support this are serialized and stored with the
|
||||
mimetype set.
|
||||
|
||||
The mimetype is used for serialized objects, and tells the
|
||||
ResXResourceReader how to depersist the object. This is currently not
|
||||
extensible. For a given mimetype the value must be set accordingly:
|
||||
|
||||
Note - application/x-microsoft.net.object.binary.base64 is the format
|
||||
that the ResXResourceWriter will generate, however the reader can
|
||||
read any of the formats listed below.
|
||||
|
||||
mimetype: application/x-microsoft.net.object.binary.base64
|
||||
value : The object must be serialized with
|
||||
: System.Runtime.Serialization.Formatters.Binary.BinaryFormatter
|
||||
: and then encoded with base64 encoding.
|
||||
|
||||
mimetype: application/x-microsoft.net.object.soap.base64
|
||||
value : The object must be serialized with
|
||||
: System.Runtime.Serialization.Formatters.Soap.SoapFormatter
|
||||
: and then encoded with base64 encoding.
|
||||
|
||||
mimetype: application/x-microsoft.net.object.bytearray.base64
|
||||
value : The object must be serialized into a byte array
|
||||
: using a System.ComponentModel.TypeConverter
|
||||
: and then encoded with base64 encoding.
|
||||
-->
|
||||
<xsd:schema id="root" xmlns="" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:msdata="urn:schemas-microsoft-com:xml-msdata">
|
||||
<xsd:import namespace="http://www.w3.org/XML/1998/namespace" />
|
||||
<xsd:element name="root" msdata:IsDataSet="true">
|
||||
<xsd:complexType>
|
||||
<xsd:choice maxOccurs="unbounded">
|
||||
<xsd:element name="metadata">
|
||||
<xsd:complexType>
|
||||
<xsd:sequence>
|
||||
<xsd:element name="value" type="xsd:string" minOccurs="0" />
|
||||
</xsd:sequence>
|
||||
<xsd:attribute name="name" use="required" type="xsd:string" />
|
||||
<xsd:attribute name="type" type="xsd:string" />
|
||||
<xsd:attribute name="mimetype" type="xsd:string" />
|
||||
<xsd:attribute ref="xml:space" />
|
||||
</xsd:complexType>
|
||||
</xsd:element>
|
||||
<xsd:element name="assembly">
|
||||
<xsd:complexType>
|
||||
<xsd:attribute name="alias" type="xsd:string" />
|
||||
<xsd:attribute name="name" type="xsd:string" />
|
||||
</xsd:complexType>
|
||||
</xsd:element>
|
||||
<xsd:element name="data">
|
||||
<xsd:complexType>
|
||||
<xsd:sequence>
|
||||
<xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
|
||||
<xsd:element name="comment" type="xsd:string" minOccurs="0" msdata:Ordinal="2" />
|
||||
</xsd:sequence>
|
||||
<xsd:attribute name="name" type="xsd:string" use="required" msdata:Ordinal="1" />
|
||||
<xsd:attribute name="type" type="xsd:string" msdata:Ordinal="3" />
|
||||
<xsd:attribute name="mimetype" type="xsd:string" msdata:Ordinal="4" />
|
||||
<xsd:attribute ref="xml:space" />
|
||||
</xsd:complexType>
|
||||
</xsd:element>
|
||||
<xsd:element name="resheader">
|
||||
<xsd:complexType>
|
||||
<xsd:sequence>
|
||||
<xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
|
||||
</xsd:sequence>
|
||||
<xsd:attribute name="name" type="xsd:string" use="required" />
|
||||
</xsd:complexType>
|
||||
</xsd:element>
|
||||
</xsd:choice>
|
||||
</xsd:complexType>
|
||||
</xsd:element>
|
||||
</xsd:schema>
|
||||
<resheader name="resmimetype">
|
||||
<value>text/microsoft-resx</value>
|
||||
</resheader>
|
||||
<resheader name="version">
|
||||
<value>2.0</value>
|
||||
</resheader>
|
||||
<resheader name="reader">
|
||||
<value>System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
|
||||
</resheader>
|
||||
<resheader name="writer">
|
||||
<value>System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
|
||||
</resheader>
|
||||
<data name="PluginTitle" xml:space="preserve">
|
||||
<value>Registry Plugin</value>
|
||||
</data>
|
||||
<data name="PluginDescription" xml:space="preserve">
|
||||
<value>Search inside the Windows Registry</value>
|
||||
<comment>"this built into Windows the OS. translate accordingly, https://docs.microsoft.com/de-de/troubleshoot/windows-server/performance/windows-registry-advanced-users is an example of it translated in German"</comment>
|
||||
</data>
|
||||
<data name="CopyKeyNamePath" xml:space="preserve">
|
||||
<value>Copy key name (path)</value>
|
||||
<comment>'The maximum size of a key name is 255 characters.'</comment>
|
||||
</data>
|
||||
<data name="KeyName" xml:space="preserve">
|
||||
<value>Key name:</value>
|
||||
<comment>'The maximum size of a key name is 255 characters.'</comment>
|
||||
</data>
|
||||
<data name="Name" xml:space="preserve">
|
||||
<value>Name:</value>
|
||||
</data>
|
||||
<data name="CopyValueName" xml:space="preserve">
|
||||
<value>Copy value name</value>
|
||||
</data>
|
||||
<data name="OpenKeyInRegistryEditor" xml:space="preserve">
|
||||
<value>Open key in registry editor</value>
|
||||
<comment>"registry editor" is the name of the OS built-in application</comment>
|
||||
</data>
|
||||
<data name="OpenInRegistryEditorAccessExceptionText" xml:space="preserve">
|
||||
<value>You do not have enough rights to open the Windows registry editor</value>
|
||||
<comment>"registry editor" is the name of the OS built-in application </comment>
|
||||
</data>
|
||||
<data name="OpenInRegistryEditorAccessExceptionTitle" xml:space="preserve">
|
||||
<value>Error on open registry editor</value>
|
||||
<comment>"registry editor" is the name of the OS built-in application</comment>
|
||||
</data>
|
||||
<data name="SubKeys" xml:space="preserve">
|
||||
<value>Subkeys:</value>
|
||||
</data>
|
||||
<data name="Values" xml:space="preserve">
|
||||
<value>Values:</value>
|
||||
</data>
|
||||
<data name="RegistryKey" xml:space="preserve">
|
||||
<value>Registry key</value>
|
||||
</data>
|
||||
<data name="RegistryValue" xml:space="preserve">
|
||||
<value>Registry value</value>
|
||||
</data>
|
||||
<data name="Type" xml:space="preserve">
|
||||
<value>Type:</value>
|
||||
<comment>See https://docs.microsoft.com/en-us/windows/win32/sysinfo/registry-value-types for proper context of how to translate 'type'</comment>
|
||||
</data>
|
||||
<data name="Value" xml:space="preserve">
|
||||
<value>Value:</value>
|
||||
<comment>See https://docs.microsoft.com/en-us/windows/win32/sysinfo/registry-value-types for proper context of how to translate 'value'</comment>
|
||||
</data>
|
||||
<data name="RegistryValueKindNone" xml:space="preserve">
|
||||
<value>No data type</value>
|
||||
</data>
|
||||
<data name="RegistryValueKindUnknown" xml:space="preserve">
|
||||
<value>Unsupported data type</value>
|
||||
</data>
|
||||
<data name="CopyValueData" xml:space="preserve">
|
||||
<value>Copy value data</value>
|
||||
</data>
|
||||
</root>
|
||||
@@ -0,0 +1,12 @@
|
||||
{
|
||||
"ID": "303417D927BF4C97BCFFC78A123BE0C8",
|
||||
"ActionKeyword": ":",
|
||||
"Name": "Registry",
|
||||
"Description": "Search inside the Windows Registry",
|
||||
"Author": "TobiasSekan",
|
||||
"Version": "1.0.0",
|
||||
"Language": "csharp",
|
||||
"Website": "https://aka.ms/powertoys",
|
||||
"ExecuteFileName": "Microsoft.PowerToys.Run.Plugin.Registry.dll",
|
||||
"IcoPath": "Images\\reg.dark.png"
|
||||
}
|
||||
Reference in New Issue
Block a user