Skip to content

Commit

Permalink
Adding Windows Services, Registry Core Ext from PT Run (#120)
Browse files Browse the repository at this point in the history
* first pass for windows services core ext

* added Windows Registry Plugin

* updated PR to reflect wt profiles, registry, and services extensions and incorporating feedback

* fixing dead code
  • Loading branch information
joadoumie authored Oct 31, 2024
1 parent ae5e6ed commit 580fe99
Show file tree
Hide file tree
Showing 38 changed files with 2,674 additions and 7 deletions.
Original file line number Diff line number Diff line change
@@ -0,0 +1,116 @@
// 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.CmdPal.Ext.Registry.Helpers;
using Microsoft.Win32;

namespace Microsoft.CmdPal.Ext.Registry.Classes;

/// <summary>
/// A entry of the registry.
/// </summary>
internal sealed class RegistryEntry
{
#pragma warning disable CS8632
/// <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; }

#pragma warning restore CS8632

/// <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);
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,49 @@
// 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.CmdPal.Ext.Registry.Classes;
using Microsoft.CmdPal.Ext.Registry.Properties;
using Microsoft.CmdPal.Extensions;
using Microsoft.CmdPal.Extensions.Helpers;
using Windows.ApplicationModel.DataTransfer;
using Windows.UI;

namespace Microsoft.CmdPal.Ext.Registry.Commands;

internal sealed partial class CopyRegistryInfoCommand : InvokableCommand
{
private readonly RegistryEntry _entry;
private readonly string _stringToCopy;

internal CopyRegistryInfoCommand(RegistryEntry entry, CopyType typeToCopy)
{
if (typeToCopy == CopyType.Key)
{
Name = Resources.CopyKeyNamePath;
Icon = new("\xE8C8"); // Copy Icon
_stringToCopy = entry.GetRegistryKey();
}
else if (typeToCopy == CopyType.ValueData)
{
Name = Resources.CopyValueData;
Icon = new("\xF413"); // CopyTo Icon
_stringToCopy = entry.GetValueData();
}
else if (typeToCopy == CopyType.ValueName)
{
Name = Resources.CopyValueName;
Icon = new("\xE8C8"); // Copy Icon
_stringToCopy = entry.GetValueNameWithKey();
}

_entry = entry;
}

public override CommandResult Invoke()
{
ClipboardHelper.SetText(_stringToCopy);

return CommandResult.KeepOpen();
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,66 @@
// 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.Diagnostics;
using System.Linq;
using System.Resources;
using System.Text;
using System.Threading.Tasks;
using Microsoft.CmdPal.Ext.Registry.Classes;
using Microsoft.CmdPal.Ext.Registry.Helpers;
using Microsoft.CmdPal.Ext.Registry.Properties;
using Microsoft.CmdPal.Extensions;
using Microsoft.CmdPal.Extensions.Helpers;
using Windows.ApplicationModel.DataTransfer;
using Windows.UI;

namespace Microsoft.CmdPal.Ext.Registry.Commands;

internal sealed partial class OpenKeyInEditorCommand : InvokableCommand
{
private readonly RegistryEntry _entry;

internal OpenKeyInEditorCommand(RegistryEntry entry)
{
Name = Resources.OpenKeyInRegistryEditor;
Icon = new("\xE8A7"); // OpenInNewWindow icon
_entry = entry;
}

internal static bool TryToOpenInRegistryEditor(in RegistryEntry entry)
{
try
{
RegistryHelper.OpenRegistryKey(entry.Key?.Name ?? entry.KeyPath);
return true;
}
catch (System.ComponentModel.Win32Exception)
{
// TODO GH #118 We need a convenient way to show errors to a user
// MessageBox.Show(
// Resources.OpenInRegistryEditorAccessExceptionText,
// Resources.OpenInRegistryEditorAccessExceptionTitle,
// MessageBoxButton.OK,
// MessageBoxImage.Error);
return false;
}
#pragma warning disable CS0168, IDE0059
catch (Exception exception)
{
// TODO GH #108: Logging
// Log.Exception("Error on opening Windows registry editor", exception, typeof(Main));
return false;
}
#pragma warning restore CS0168, IDE0059
}

public override CommandResult Invoke()
{
TryToOpenInRegistryEditor(_entry);

return CommandResult.KeepOpen();
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,51 @@
// 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.CmdPal.Ext.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";
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
// 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.CmdPal.Ext.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;
}
12 changes: 12 additions & 0 deletions src/modules/cmdpal/Exts/Microsoft.CmdPal.Ext.Registry/CopyType.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
// 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.CmdPal.Ext.Registry;

public enum CopyType
{
Key,
ValueData,
ValueName,
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
// 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.CmdPal.Ext.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,
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
// 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.CmdPal.Ext.Registry.Classes;
using Microsoft.CmdPal.Ext.Registry.Commands;
using Microsoft.CmdPal.Ext.Registry.Properties;
using Microsoft.CmdPal.Extensions.Helpers;

namespace Microsoft.CmdPal.Ext.Registry.Helpers;

/// <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://learn.microsoft.com/windows/uwp/design/style/segoe-ui-symbol-font"/></para>
/// </summary>
internal static List<CommandContextItem> GetContextMenu(RegistryEntry entry)
{
var list = new List<CommandContextItem>();

if (string.IsNullOrEmpty(entry.ValueName))
{
list.Add(new CommandContextItem(new CopyRegistryInfoCommand(entry, CopyType.Key)));
}
else
{
list.Add(new CommandContextItem(new CopyRegistryInfoCommand(entry, CopyType.ValueData)));
list.Add(new CommandContextItem(new CopyRegistryInfoCommand(entry, CopyType.ValueName)));
}

// list.Add(new CommandContextItem(new OpenKeyInEditorCommand(entry)));
return list;
}
}
Loading

0 comments on commit 580fe99

Please sign in to comment.