Add the shell plugin from PT Run, and a ChoiceSet settings helper (#185)

* not super happy with this approach - scratch that, not happy at all

* that's a bit better, still gonna need a review, but it works atm

* going home is better than not... for save action in settings

* welp, undoing that. that did NOT work. something is going on with RaiseSettingsChanged

* hmmm... update() doesn't work the way I want it to - on to the next one

* working on file saving... not working yet

* saving to/loading from file works... but needs some refactoring I'd imagine

* we should dismiss palette on launch...

* make settings a context menu command

* add icon as content in .csproj

* fix icon name

* remove hardcoding settings file

* move SettingsJsonPath to Settings Manager class

* more sensical version of saved settings

* remove settings.json from csproj

* removing comment

* whoops, removing unused Settings.json idea

* no more hadcorded strings... helo Resources!

* here you go

* dont do anything to setting if key is not found in payload

* ChoiceSetSetting example working with fake setting in terminal...

* remove random extra terminal settings changes

* working on shell plugin from PT Run

* getting closer to a reasonable prototype

* it kinda makes some sense now

* maybe ChoiceSetSetting should should only take in array of Choices with the default one being just the first choice

* I think this fixes our winmd pains, but at what cost

* fix naming for command

* fixing vd extension publish profiles + a few other things

* Add choice setting example to the sample pages

* add an additional choice in sample pages choice set example

* add icon

* whoops, forgot the command context menu was broken before this fix!

* address first few PR comments

* removed extra file + removing wox refs in .resx

* changed for loop to for each

* fixing some things for PR review

---------

Co-authored-by: Jordi Adoumie <jordiadoumie@microsoft.com>
Co-authored-by: Mike Griese <migrie@microsoft.com>
This commit is contained in:
Jordi Adoumie
2024-12-06 09:51:39 -05:00
committed by GitHub
parent aeb39043fe
commit d881cf89a6
20 changed files with 1228 additions and 6 deletions

View File

@@ -705,6 +705,8 @@ Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "WorkspacesCsharpLibrary", "
EndProject
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "NewPlus.ShellExtension.win10", "src\modules\NewPlus\NewShellExtensionContextMenu.win10\NewPlus.ShellExtension.win10.vcxproj", "{0DB0F63A-D2F8-4DA3-A650-2D0B8724218E}"
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Microsoft.CmdPal.Ext.Shell", "src\modules\cmdpal\Exts\Microsoft.CmdPal.Ext.Shell\Microsoft.CmdPal.Ext.Shell.csproj", "{C0CE3B5E-16D3-495D-B335-CA791B660162}"
EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
Debug|ARM64 = Debug|ARM64
@@ -3291,6 +3293,18 @@ Global
{89D0E199-B17A-418C-B2F8-7375B6708357}.Release|x64.Build.0 = Release|x64
{89D0E199-B17A-418C-B2F8-7375B6708357}.Release|x86.ActiveCfg = Release|x64
{89D0E199-B17A-418C-B2F8-7375B6708357}.Release|x86.Build.0 = Release|x64
{C0CE3B5E-16D3-495D-B335-CA791B660162}.Debug|ARM64.ActiveCfg = Debug|ARM64
{C0CE3B5E-16D3-495D-B335-CA791B660162}.Debug|ARM64.Build.0 = Debug|ARM64
{C0CE3B5E-16D3-495D-B335-CA791B660162}.Debug|x64.ActiveCfg = Debug|x64
{C0CE3B5E-16D3-495D-B335-CA791B660162}.Debug|x64.Build.0 = Debug|x64
{C0CE3B5E-16D3-495D-B335-CA791B660162}.Debug|x86.ActiveCfg = Debug|x64
{C0CE3B5E-16D3-495D-B335-CA791B660162}.Debug|x86.Build.0 = Debug|x64
{C0CE3B5E-16D3-495D-B335-CA791B660162}.Release|ARM64.ActiveCfg = Release|ARM64
{C0CE3B5E-16D3-495D-B335-CA791B660162}.Release|ARM64.Build.0 = Release|ARM64
{C0CE3B5E-16D3-495D-B335-CA791B660162}.Release|x64.ActiveCfg = Release|x64
{C0CE3B5E-16D3-495D-B335-CA791B660162}.Release|x64.Build.0 = Release|x64
{C0CE3B5E-16D3-495D-B335-CA791B660162}.Release|x86.ActiveCfg = Release|x64
{C0CE3B5E-16D3-495D-B335-CA791B660162}.Release|x86.Build.0 = Release|x64
{0DB0F63A-D2F8-4DA3-A650-2D0B8724218E}.Debug|ARM64.ActiveCfg = Debug|ARM64
{0DB0F63A-D2F8-4DA3-A650-2D0B8724218E}.Debug|ARM64.Build.0 = Debug|ARM64
{0DB0F63A-D2F8-4DA3-A650-2D0B8724218E}.Debug|x64.ActiveCfg = Debug|x64
@@ -3569,6 +3583,7 @@ Global
{8ABE2195-7514-425E-9A89-685FA42CEFC3} = {071E18A4-A530-46B8-AB7D-B862EE55E24E}
{B79B52FB-8B2E-4CF5-B0FE-37E3E981AC7A} = {071E18A4-A530-46B8-AB7D-B862EE55E24E}
{89D0E199-B17A-418C-B2F8-7375B6708357} = {A2221D7E-55E7-4BEA-90D1-4F162D670BBF}
{C0CE3B5E-16D3-495D-B335-CA791B660162} = {ECB8E0D1-7603-4E5C-AB10-D1E545E6F8E2}
{02EA681E-C7D8-13C7-8484-4AC65E1B71E8} = {3846508C-77EB-4034-A702-F8BB263C4F79}
{89D0E199-B17A-418C-B2F8-7375B6708357} = {A2221D7E-55E7-4BEA-90D1-4F162D670BBF}
{0DB0F63A-D2F8-4DA3-A650-2D0B8724218E} = {CA716AE6-FE5C-40AC-BB8F-2C87912687AC}

View File

@@ -0,0 +1,257 @@
// 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.ComponentModel;
using System.Diagnostics;
using System.IO;
using Microsoft.CmdPal.Ext.Shell.Helpers;
using Microsoft.CmdPal.Ext.Shell.Properties;
using Microsoft.CmdPal.Extensions.Helpers;
namespace Microsoft.CmdPal.Ext.Shell.Commands;
internal sealed partial class ExecuteItem : InvokableCommand
{
private readonly SettingsManager _settings;
private readonly string _cmd;
private readonly RunAsType _runas;
private static readonly char[] Separator = [' '];
public ExecuteItem(string cmd, SettingsManager settings, RunAsType type = RunAsType.None)
{
if (type == RunAsType.Administrator)
{
Name = Properties.Resources.cmd_run_as_administrator;
Icon = new("\xE7EF"); // Admin Icon
}
else if (type == RunAsType.OtherUser)
{
Name = Properties.Resources.cmd_run_as_user;
Icon = new("\xE7EE"); // User Icon
}
else
{
Name = Properties.Resources.generic_run_command;
Icon = new("\uE751"); // Return Key Icon
}
_cmd = cmd;
_settings = settings;
_runas = type;
}
private static bool ExistInPath(string filename)
{
if (File.Exists(filename))
{
return true;
}
else
{
var values = Environment.GetEnvironmentVariable("PATH");
if (values != null)
{
foreach (var path in values.Split(';'))
{
var path1 = Path.Combine(path, filename);
var path2 = Path.Combine(path, filename + ".exe");
if (File.Exists(path1) || File.Exists(path2))
{
return true;
}
}
return false;
}
else
{
return false;
}
}
}
private void Execute(Func<ProcessStartInfo, Process?> startProcess, ProcessStartInfo info)
{
if (startProcess == null)
{
return;
}
try
{
startProcess(info);
}
catch (FileNotFoundException e)
{
var name = "Plugin: " + Properties.Resources.cmd_plugin_name;
var message = $"{Properties.Resources.cmd_command_not_found}: {e.Message}";
// GH TODO #138 -- show this message once that's wired up
// _context.API.ShowMsg(name, message);
}
catch (Win32Exception e)
{
var name = "Plugin: " + Properties.Resources.cmd_plugin_name;
var message = $"{Properties.Resources.cmd_command_failed}: {e.Message}";
ExtensionHost.LogMessage(new LogMessage() { Message = name + message });
// GH TODO #138 -- show this message once that's wired up
// _context.API.ShowMsg(name, message);
}
}
public static ProcessStartInfo SetProcessStartInfo(string fileName, string workingDirectory = "", string arguments = "", string verb = "")
{
var info = new ProcessStartInfo
{
FileName = fileName,
WorkingDirectory = workingDirectory,
Arguments = arguments,
Verb = verb,
};
return info;
}
private ProcessStartInfo PrepareProcessStartInfo(string command, RunAsType runAs = RunAsType.None)
{
command = Environment.ExpandEnvironmentVariables(command);
var workingDirectory = Environment.GetFolderPath(Environment.SpecialFolder.UserProfile);
// Set runAsArg
var runAsVerbArg = string.Empty;
if (runAs == RunAsType.OtherUser)
{
runAsVerbArg = "runAsUser";
}
else if (runAs == RunAsType.Administrator || _settings.RunAsAdministrator)
{
runAsVerbArg = "runAs";
}
if (Enum.TryParse<ExecutionShell>(_settings.ShellCommandExecution, out var executionShell))
{
ProcessStartInfo info;
if (executionShell == ExecutionShell.Cmd)
{
var arguments = _settings.LeaveShellOpen ? $"/k \"{command}\"" : $"/c \"{command}\" & pause";
info = SetProcessStartInfo("cmd.exe", workingDirectory, arguments, runAsVerbArg);
}
else if (executionShell == ExecutionShell.Powershell)
{
var arguments = _settings.LeaveShellOpen
? $"-NoExit \"{command}\""
: $"\"{command} ; Read-Host -Prompt \\\"{Resources.run_plugin_cmd_wait_message}\\\"\"";
info = SetProcessStartInfo("powershell.exe", workingDirectory, arguments, runAsVerbArg);
}
else if (executionShell == ExecutionShell.PowerShellSeven)
{
var arguments = _settings.LeaveShellOpen
? $"-NoExit -C \"{command}\""
: $"-C \"{command} ; Read-Host -Prompt \\\"{Resources.run_plugin_cmd_wait_message}\\\"\"";
info = SetProcessStartInfo("pwsh.exe", workingDirectory, arguments, runAsVerbArg);
}
else if (executionShell == ExecutionShell.WindowsTerminalCmd)
{
var arguments = _settings.LeaveShellOpen ? $"cmd.exe /k \"{command}\"" : $"cmd.exe /c \"{command}\" & pause";
info = SetProcessStartInfo("wt.exe", workingDirectory, arguments, runAsVerbArg);
}
else if (executionShell == ExecutionShell.WindowsTerminalPowerShell)
{
var arguments = _settings.LeaveShellOpen ? $"powershell -NoExit -C \"{command}\"" : $"powershell -C \"{command}\"";
info = SetProcessStartInfo("wt.exe", workingDirectory, arguments, runAsVerbArg);
}
else if (executionShell == ExecutionShell.WindowsTerminalPowerShellSeven)
{
var arguments = _settings.LeaveShellOpen ? $"pwsh.exe -NoExit -C \"{command}\"" : $"pwsh.exe -C \"{command}\"";
info = SetProcessStartInfo("wt.exe", workingDirectory, arguments, runAsVerbArg);
}
else if (executionShell == ExecutionShell.RunCommand)
{
// Open explorer if the path is a file or directory
if (Directory.Exists(command) || File.Exists(command))
{
info = SetProcessStartInfo("explorer.exe", arguments: command, verb: runAsVerbArg);
}
else
{
var parts = command.Split(Separator, 2);
if (parts.Length == 2)
{
var filename = parts[0];
if (ExistInPath(filename))
{
var arguments = parts[1];
if (_settings.LeaveShellOpen)
{
// Wrap the command in a cmd.exe process
info = SetProcessStartInfo("cmd.exe", workingDirectory, $"/k \"{filename} {arguments}\"", runAsVerbArg);
}
else
{
info = SetProcessStartInfo(filename, workingDirectory, arguments, runAsVerbArg);
}
}
else
{
if (_settings.LeaveShellOpen)
{
// Wrap the command in a cmd.exe process
info = SetProcessStartInfo("cmd.exe", workingDirectory, $"/k \"{command}\"", runAsVerbArg);
}
else
{
info = SetProcessStartInfo(command, verb: runAsVerbArg);
}
}
}
else
{
if (_settings.LeaveShellOpen)
{
// Wrap the command in a cmd.exe process
info = SetProcessStartInfo("cmd.exe", workingDirectory, $"/k \"{command}\"", runAsVerbArg);
}
else
{
info = SetProcessStartInfo(command, verb: runAsVerbArg);
}
}
}
}
else
{
throw new NotImplementedException();
}
info.UseShellExecute = true;
_settings.AddCmdHistory(command);
return info;
}
else
{
ExtensionHost.LogMessage(new LogMessage() { Message = "Error extracting setting" });
throw new NotImplementedException();
}
}
public override CommandResult Invoke()
{
try
{
Execute(Process.Start, PrepareProcessStartInfo(_cmd, _runas));
}
catch
{
ExtensionHost.LogMessage(new LogMessage() { Message = "Error starting the process " });
}
return CommandResult.Dismiss();
}
}

View File

@@ -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.Shell.Helpers;
public enum RunAsType
{
None,
Administrator,
OtherUser,
}

View File

@@ -0,0 +1,135 @@
// 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.IO;
using System.Linq;
using System.Text.Json;
using System.Text.Json.Nodes;
using System.Text.Json.Serialization;
using Microsoft.CmdPal.Ext.Shell.Properties;
using Microsoft.CmdPal.Extensions.Helpers;
namespace Microsoft.CmdPal.Ext.Shell.Helpers;
public class SettingsManager
{
private readonly string _filePath;
private readonly Settings _settings = new();
private readonly List<ChoiceSetSetting.Choice> _choices = new()
{
new ChoiceSetSetting.Choice(Resources.find_executable_file_and_run_it, "2"), // idk why but this is how PT Run did it? Maybe ordering matters there
new ChoiceSetSetting.Choice(Resources.run_command_in_command_prompt, "0"),
new ChoiceSetSetting.Choice(Resources.run_command_in_powershell, "1"),
new ChoiceSetSetting.Choice(Resources.run_command_in_powershell_seven, "6"),
new ChoiceSetSetting.Choice(Resources.run_command_in_windows_terminal_cmd, "5"),
new ChoiceSetSetting.Choice(Resources.run_command_in_windows_terminal_powershell, "3"),
new ChoiceSetSetting.Choice(Resources.run_command_in_windows_terminal_powershell_seven, "4"),
};
private readonly ToggleSetting _leaveShellOpen = new(nameof(LeaveShellOpen), Resources.leave_shell_open, Resources.leave_shell_open, false); // TODO -- double check default value
private readonly ChoiceSetSetting _shellCommandExecution;
public bool LeaveShellOpen => _leaveShellOpen.Value;
public string ShellCommandExecution => _shellCommandExecution.Value != null ? _shellCommandExecution.Value : string.Empty;
public bool RunAsAdministrator { get; set; }
public Dictionary<string, int> Count { get; } = new Dictionary<string, int>();
public void AddCmdHistory(string cmdName)
{
if (Count.TryGetValue(cmdName, out var currentCount))
{
Count[cmdName] = currentCount + 1;
}
else
{
Count[cmdName] = 1;
}
}
private static readonly JsonSerializerOptions _serializerOptions = new()
{
WriteIndented = true,
Converters = { new JsonStringEnumConverter() },
};
internal static string SettingsJsonPath()
{
// Get the path to our exe
var path = System.Reflection.Assembly.GetExecutingAssembly().Location;
// Get the directory of the exe
var directory = Path.GetDirectoryName(path) ?? string.Empty;
// now, the state is just next to the exe
return Path.Combine(directory, "shell-state.json");
}
public SettingsManager()
{
_filePath = SettingsJsonPath();
_shellCommandExecution = new(nameof(ShellCommandExecution), Resources.shell_command_execution, Resources.shell_command_execution_description, _choices);
_settings.Add(_leaveShellOpen);
_settings.Add(_shellCommandExecution);
// Load settings from file upon initialization
LoadSettings();
}
public Settings GetSettings()
{
return _settings;
}
public void SaveSettings()
{
try
{
// Serialize the main dictionary to JSON and save it to the file
var settingsJson = _settings.ToJson();
File.WriteAllText(_filePath, settingsJson);
}
catch (Exception ex)
{
ExtensionHost.LogMessage(new LogMessage() { Message = ex.ToString() });
}
}
public void LoadSettings()
{
if (!File.Exists(_filePath))
{
ExtensionHost.LogMessage(new LogMessage() { Message = "The provided settings file does not exist" });
return;
}
try
{
// Read the JSON content from the file
var jsonContent = File.ReadAllText(_filePath);
// Is it valid JSON?
if (JsonNode.Parse(jsonContent) is JsonObject savedSettings)
{
_settings.Update(jsonContent);
}
else
{
ExtensionHost.LogMessage(new LogMessage() { Message = "Failed to parse settings file as JsonObject." });
}
}
catch (Exception ex)
{
ExtensionHost.LogMessage(new LogMessage() { Message = ex.ToString() });
}
}
}

View File

@@ -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 System.Collections.Generic;
using System.Globalization;
using System.Linq;
using System.Reflection;
using System.Text;
using System.Threading.Tasks;
using Microsoft.CmdPal.Ext.Shell.Commands;
using Microsoft.CmdPal.Extensions.Helpers;
namespace Microsoft.CmdPal.Ext.Shell.Helpers;
public class ShellListPageHelpers
{
private static readonly CompositeFormat CmdHasBeenExecutedTimes = System.Text.CompositeFormat.Parse(Properties.Resources.cmd_has_been_executed_times);
private readonly SettingsManager _settings;
public ShellListPageHelpers(SettingsManager settings)
{
_settings = settings;
}
private ListItem GetCurrentCmd(string cmd)
{
ListItem result = new ListItem(new ExecuteItem(cmd, _settings))
{
Title = cmd,
Subtitle = Properties.Resources.cmd_plugin_name + ": " + Properties.Resources.cmd_execute_through_shell,
Icon = new(string.Empty),
};
return result;
}
private List<ListItem> GetHistoryCmds(string cmd, ListItem result)
{
IEnumerable<ListItem?> history = _settings.Count.Where(o => o.Key.Contains(cmd, StringComparison.CurrentCultureIgnoreCase))
.OrderByDescending(o => o.Value)
.Select(m =>
{
if (m.Key == cmd)
{
// Using CurrentCulture since this is user facing
result.Subtitle = Properties.Resources.cmd_plugin_name + ": " + string.Format(CultureInfo.CurrentCulture, CmdHasBeenExecutedTimes, m.Value);
return null;
}
var ret = new ListItem(new ExecuteItem(m.Key, _settings))
{
Title = m.Key,
// Using CurrentCulture since this is user facing
Subtitle = Properties.Resources.cmd_plugin_name + ": " + string.Format(CultureInfo.CurrentCulture, CmdHasBeenExecutedTimes, m.Value),
Icon = new("\uE81C"),
};
return ret;
}).Where(o => o != null).Take(4);
return history.Select(o => o!).ToList();
}
public List<ListItem> Query(string query)
{
ArgumentNullException.ThrowIfNull(query);
List<ListItem> results = new List<ListItem>();
var cmd = query;
if (string.IsNullOrEmpty(cmd))
{
results = ResultsFromlHistory();
}
else
{
var queryCmd = GetCurrentCmd(cmd);
results.Add(queryCmd);
var history = GetHistoryCmds(cmd, queryCmd);
results.AddRange(history);
}
foreach (var currItem in results)
{
currItem.MoreCommands = LoadContextMenus(currItem).ToArray();
}
return results;
}
public List<CommandContextItem> LoadContextMenus(ListItem listItem)
{
var resultlist = new List<CommandContextItem>
{
new(new ExecuteItem(listItem.Title, _settings, RunAsType.Administrator)),
new(new ExecuteItem(listItem.Title, _settings, RunAsType.OtherUser )),
};
return resultlist;
}
private List<ListItem> ResultsFromlHistory()
{
IEnumerable<ListItem> history = _settings.Count.OrderByDescending(o => o.Value)
.Select(m => new ListItem(new ExecuteItem(m.Key, _settings))
{
Title = m.Key,
// Using CurrentCulture since this is user facing
Subtitle = Properties.Resources.cmd_plugin_name + ": " + string.Format(CultureInfo.CurrentCulture, CmdHasBeenExecutedTimes, m.Value),
Icon = new("\uE81C"),
}).Take(5);
return history.ToList();
}
}

View File

@@ -0,0 +1,26 @@
<Project Sdk="Microsoft.NET.Sdk">
<Import Project="..\..\..\..\Common.Dotnet.CsWinRT.props" />
<PropertyGroup>
<Nullable>enable</Nullable>
<RootNamespace>Microsoft.CmdPal.Ext.Shell</RootNamespace>
<OutputPath>$(SolutionDir)$(Platform)\$(Configuration)\WinUI3Apps\CmdPal</OutputPath>
<AppendTargetFrameworkToOutputPath>false</AppendTargetFrameworkToOutputPath>
<AppendRuntimeIdentifierToOutputPath>false</AppendRuntimeIdentifierToOutputPath>
</PropertyGroup>
<ItemGroup>
<ProjectReference Include="..\..\extensionsdk\Microsoft.CmdPal.Extensions.Helpers\Microsoft.CmdPal.Extensions.Helpers.csproj" />
</ItemGroup>
<ItemGroup>
<Compile Update="Properties\Resources.Designer.cs">
<DependentUpon>Resources.resx</DependentUpon>
<DesignTime>True</DesignTime>
<AutoGen>True</AutoGen>
</Compile>
</ItemGroup>
<ItemGroup>
<EmbeddedResource Update="Properties\Resources.resx">
<LastGenOutput>Resources.Designer.cs</LastGenOutput>
<Generator>PublicResXFileCodeGenerator</Generator>
</EmbeddedResource>
</ItemGroup>
</Project>

View File

@@ -0,0 +1,36 @@
// 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.Shell.Helpers;
using Microsoft.CmdPal.Extensions;
using Microsoft.CmdPal.Extensions.Helpers;
namespace Microsoft.CmdPal.Ext.Shell.Pages;
internal sealed partial class SettingsPage : FormPage
{
private readonly Settings _settings;
private readonly SettingsManager _settingsManager;
public override IForm[] Forms()
{
var s = _settings.ToForms();
return s;
}
public SettingsPage(SettingsManager settingsManager)
{
Name = Properties.Resources.settings_page_name;
Icon = new("\uE713"); // Settings icon
_settings = settingsManager.GetSettings();
_settingsManager = settingsManager;
_settings.SettingsChanged += SettingsChanged;
}
private void SettingsChanged(object sender, Settings args)
{
_settingsManager.SaveSettings();
}
}

View File

@@ -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.CmdPal.Ext.Shell.Helpers;
using Microsoft.CmdPal.Ext.Shell.Properties;
using Microsoft.CmdPal.Extensions;
using Microsoft.CmdPal.Extensions.Helpers;
namespace Microsoft.CmdPal.Ext.Shell.Pages;
internal sealed partial class ShellListPage : DynamicListPage
{
private readonly ShellListPageHelpers _helper;
public ShellListPage(SettingsManager settingsManager)
{
Icon = new("\uE756");
Id = "com.microsoft.cmdpal.shell";
Name = Resources.cmd_plugin_name;
_helper = new(settingsManager);
}
public override void UpdateSearchText(string oldSearch, string newSearch) => RaiseItemsChanged(0);
public override IListItem[] GetItems() => [.. _helper.Query(SearchText)];
}

View File

@@ -0,0 +1,261 @@
//------------------------------------------------------------------------------
// <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.CmdPal.Ext.Shell.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", "17.0.0.0")]
[global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
[global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()]
public 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)]
public static global::System.Resources.ResourceManager ResourceManager {
get {
if (object.ReferenceEquals(resourceMan, null)) {
global::System.Resources.ResourceManager temp = new global::System.Resources.ResourceManager("Microsoft.CmdPal.Ext.Shell.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)]
public static global::System.Globalization.CultureInfo Culture {
get {
return resourceCulture;
}
set {
resourceCulture = value;
}
}
/// <summary>
/// Looks up a localized string similar to Error running the command.
/// </summary>
public static string cmd_command_failed {
get {
return ResourceManager.GetString("cmd_command_failed", resourceCulture);
}
}
/// <summary>
/// Looks up a localized string similar to Command not found.
/// </summary>
public static string cmd_command_not_found {
get {
return ResourceManager.GetString("cmd_command_not_found", resourceCulture);
}
}
/// <summary>
/// Looks up a localized string similar to execute command through command shell.
/// </summary>
public static string cmd_execute_through_shell {
get {
return ResourceManager.GetString("cmd_execute_through_shell", resourceCulture);
}
}
/// <summary>
/// Looks up a localized string similar to this command has been executed {0} times.
/// </summary>
public static string cmd_has_been_executed_times {
get {
return ResourceManager.GetString("cmd_has_been_executed_times", resourceCulture);
}
}
/// <summary>
/// Looks up a localized string similar to Executes commands (e.g. &apos;ping&apos;, &apos;cmd&apos;).
/// </summary>
public static string cmd_plugin_description {
get {
return ResourceManager.GetString("cmd_plugin_description", resourceCulture);
}
}
/// <summary>
/// Looks up a localized string similar to Shell.
/// </summary>
public static string cmd_plugin_name {
get {
return ResourceManager.GetString("cmd_plugin_name", resourceCulture);
}
}
/// <summary>
/// Looks up a localized string similar to Run as administrator (Ctrl+Shift+Enter).
/// </summary>
public static string cmd_run_as_administrator {
get {
return ResourceManager.GetString("cmd_run_as_administrator", resourceCulture);
}
}
/// <summary>
/// Looks up a localized string similar to Run as different user (Ctrl+Shift+U).
/// </summary>
public static string cmd_run_as_user {
get {
return ResourceManager.GetString("cmd_run_as_user", resourceCulture);
}
}
/// <summary>
/// Looks up a localized string similar to Find and run the executable file.
/// </summary>
public static string find_executable_file_and_run_it {
get {
return ResourceManager.GetString("find_executable_file_and_run_it", resourceCulture);
}
}
/// <summary>
/// Looks up a localized string similar to Run.
/// </summary>
public static string generic_run_command {
get {
return ResourceManager.GetString("generic_run_command", resourceCulture);
}
}
/// <summary>
/// Looks up a localized string similar to Keep shell open.
/// </summary>
public static string leave_shell_open {
get {
return ResourceManager.GetString("leave_shell_open", resourceCulture);
}
}
/// <summary>
/// Looks up a localized string similar to Run in Command Prompt (cmd.exe).
/// </summary>
public static string run_command_in_command_prompt {
get {
return ResourceManager.GetString("run_command_in_command_prompt", resourceCulture);
}
}
/// <summary>
/// Looks up a localized string similar to Run in PowerShell (PowerShell.exe).
/// </summary>
public static string run_command_in_powershell {
get {
return ResourceManager.GetString("run_command_in_powershell", resourceCulture);
}
}
/// <summary>
/// Looks up a localized string similar to Run in PowerShell 7 (pwsh.exe).
/// </summary>
public static string run_command_in_powershell_seven {
get {
return ResourceManager.GetString("run_command_in_powershell_seven", resourceCulture);
}
}
/// <summary>
/// Looks up a localized string similar to Run in Command Prompt (cmd.exe) using Windows Terminal.
/// </summary>
public static string run_command_in_windows_terminal_cmd {
get {
return ResourceManager.GetString("run_command_in_windows_terminal_cmd", resourceCulture);
}
}
/// <summary>
/// Looks up a localized string similar to Run in PowerShell (PowerShell.exe) using Windows Terminal.
/// </summary>
public static string run_command_in_windows_terminal_powershell {
get {
return ResourceManager.GetString("run_command_in_windows_terminal_powershell", resourceCulture);
}
}
/// <summary>
/// Looks up a localized string similar to Run in PowerShell 7 (pwsh.exe) using Windows Terminal.
/// </summary>
public static string run_command_in_windows_terminal_powershell_seven {
get {
return ResourceManager.GetString("run_command_in_windows_terminal_powershell_seven", resourceCulture);
}
}
/// <summary>
/// Looks up a localized string similar to Press Enter to continue.
/// </summary>
public static string run_plugin_cmd_wait_message {
get {
return ResourceManager.GetString("run_plugin_cmd_wait_message", resourceCulture);
}
}
/// <summary>
/// Looks up a localized string similar to Settings.
/// </summary>
public static string settings_page_name {
get {
return ResourceManager.GetString("settings_page_name", resourceCulture);
}
}
/// <summary>
/// Looks up a localized string similar to Command execution.
/// </summary>
public static string shell_command_execution {
get {
return ResourceManager.GetString("shell_command_execution", resourceCulture);
}
}
/// <summary>
/// Looks up a localized string similar to All entries using the Windows Terminal force the Windows Terminal as the console host regardless of the system settings.
/// </summary>
public static string shell_command_execution_description {
get {
return ResourceManager.GetString("shell_command_execution_description", resourceCulture);
}
}
/// <summary>
/// Looks up a localized string similar to Execute shell commands.
/// </summary>
public static string shell_command_name {
get {
return ResourceManager.GetString("shell_command_name", resourceCulture);
}
}
}
}

View File

@@ -0,0 +1,187 @@
<?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="cmd_plugin_name" xml:space="preserve">
<value>Shell</value>
</data>
<data name="cmd_plugin_description" xml:space="preserve">
<value>Executes commands (e.g. 'ping', 'cmd')</value>
</data>
<data name="cmd_has_been_executed_times" xml:space="preserve">
<value>this command has been executed {0} times</value>
</data>
<data name="cmd_execute_through_shell" xml:space="preserve">
<value>execute command through command shell</value>
</data>
<data name="cmd_run_as_administrator" xml:space="preserve">
<value>Run as administrator (Ctrl+Shift+Enter)</value>
</data>
<data name="cmd_command_failed" xml:space="preserve">
<value>Error running the command</value>
</data>
<data name="cmd_command_not_found" xml:space="preserve">
<value>Command not found</value>
</data>
<data name="cmd_run_as_user" xml:space="preserve">
<value>Run as different user (Ctrl+Shift+U)</value>
</data>
<data name="leave_shell_open" xml:space="preserve">
<value>Keep shell open</value>
</data>
<data name="shell_command_execution" xml:space="preserve">
<value>Command execution</value>
</data>
<data name="run_command_in_command_prompt" xml:space="preserve">
<value>Run in Command Prompt (cmd.exe)</value>
</data>
<data name="run_command_in_powershell" xml:space="preserve">
<value>Run in PowerShell (PowerShell.exe)</value>
</data>
<data name="find_executable_file_and_run_it" xml:space="preserve">
<value>Find and run the executable file</value>
</data>
<data name="run_command_in_powershell_seven" xml:space="preserve">
<value>Run in PowerShell 7 (pwsh.exe)</value>
</data>
<data name="run_command_in_windows_terminal_cmd" xml:space="preserve">
<value>Run in Command Prompt (cmd.exe) using Windows Terminal</value>
</data>
<data name="run_command_in_windows_terminal_powershell" xml:space="preserve">
<value>Run in PowerShell (PowerShell.exe) using Windows Terminal</value>
</data>
<data name="run_command_in_windows_terminal_powershell_seven" xml:space="preserve">
<value>Run in PowerShell 7 (pwsh.exe) using Windows Terminal</value>
</data>
<data name="run_plugin_cmd_wait_message" xml:space="preserve">
<value>Press Enter to continue</value>
<comment>"Enter" means the Enter key on the keyboard.</comment>
</data>
<data name="shell_command_execution_description" xml:space="preserve">
<value>All entries using the Windows Terminal force the Windows Terminal as the console host regardless of the system settings</value>
</data>
<data name="shell_command_name" xml:space="preserve">
<value>Execute shell commands</value>
</data>
<data name="generic_run_command" xml:space="preserve">
<value>Run</value>
</data>
<data name="settings_page_name" xml:space="preserve">
<value>Settings</value>
</data>
</root>

View File

@@ -0,0 +1,33 @@
// 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.IO;
using Microsoft.CmdPal.Ext.Shell.Helpers;
using Microsoft.CmdPal.Ext.Shell.Pages;
using Microsoft.CmdPal.Ext.Shell.Properties;
using Microsoft.CmdPal.Extensions;
using Microsoft.CmdPal.Extensions.Helpers;
namespace Microsoft.CmdPal.Ext.Shell;
public partial class ShellCommandsProvider : CommandProvider
{
private readonly CommandItem _shellPageItem;
private readonly SettingsManager _settingsManager = new();
public ShellCommandsProvider()
{
DisplayName = Resources.cmd_plugin_name;
_shellPageItem = new CommandItem(new ShellListPage(_settingsManager))
{
Icon = new("\uE756"),
Title = Resources.shell_command_name,
Subtitle = Resources.cmd_plugin_description,
MoreCommands = [new CommandContextItem(new SettingsPage(_settingsManager))],
};
}
public override ICommandItem[] TopLevelCommands() => [_shellPageItem];
}

View File

@@ -3,6 +3,7 @@
// See the LICENSE file in the project root for more information.
using System;
using System.Collections.Generic;
using System.IO;
using System.Text.Json;
using System.Text.Json.Nodes;

View File

@@ -13,9 +13,9 @@ using Microsoft.CmdPal.Extensions.Helpers;
namespace Microsoft.CmdPal.Ext.WindowsTerminal;
public partial class TerminalTopLevelListItem : CommandItem
public partial class TerminalTopLevelCommandItem : CommandItem
{
public TerminalTopLevelListItem(SettingsManager settingsManager)
public TerminalTopLevelCommandItem(SettingsManager settingsManager)
: base(new ProfilesListPage(settingsManager.GetSettings()))
{
Icon = new(Path.Combine(AppDomain.CurrentDomain.BaseDirectory.ToString(), "Images\\WindowsTerminal.dark.png"));

View File

@@ -16,14 +16,14 @@ namespace Microsoft.CmdPal.Ext.WindowsTerminal;
public partial class WindowsTerminalCommandsProvider : CommandProvider
{
private readonly TerminalTopLevelListItem _terminalCommand;
private readonly TerminalTopLevelCommandItem _terminalCommand;
private readonly SettingsManager _settingsManager = new();
public WindowsTerminalCommandsProvider()
{
DisplayName = Resources.extension_name;
_terminalCommand = new TerminalTopLevelListItem(_settingsManager);
_terminalCommand = new TerminalTopLevelCommandItem(_settingsManager);
_terminalCommand.MoreCommands = [new CommandContextItem(new SettingsPage(_settingsManager))];
}

View File

@@ -2,6 +2,8 @@
// 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.Generic;
using System.Reflection.Emit;
using Microsoft.CmdPal.Extensions;
using Microsoft.CmdPal.Extensions.Helpers;
@@ -11,6 +13,15 @@ internal sealed partial class SampleSettingsPage : FormPage
{
private readonly Settings _settings = new();
private readonly List<ChoiceSetSetting.Choice> _choices = new()
{
new ChoiceSetSetting.Choice("The first choice in the list is the default choice", "0"),
new ChoiceSetSetting.Choice("Choices have titles and values", "1"),
new ChoiceSetSetting.Choice("Title", "Value"),
new ChoiceSetSetting.Choice("The options are endless", "3"),
new ChoiceSetSetting.Choice("So many choices", "4"),
};
public override IForm[] Forms()
{
var s = _settings.ToForms();
@@ -31,6 +42,11 @@ internal sealed partial class SampleSettingsPage : FormPage
Label = "This is a text box",
Description = "For some string of text",
});
_settings.Add(new ChoiceSetSetting("choiceSetExample", _choices)
{
Label = "It also has a label",
Description = "Describe your choice set setting here",
});
_settings.SettingsChanged += SettingsChanged;
}

View File

@@ -1,4 +1,4 @@
<Project Sdk="Microsoft.NET.Sdk">
<Project Sdk="Microsoft.NET.Sdk">
<Import Project="..\..\..\..\Common.Dotnet.CsWinRT.props" />
<PropertyGroup>
<OutputType>WinExe</OutputType>
@@ -46,7 +46,6 @@
<ItemGroup Condition="'$(DisableMsixProjectCapabilityAddedByProject)'!='true' and '$(EnableMsixTooling)'=='true'">
<ProjectCapability Include="Msix" />
</ItemGroup>
<!--
Defining the "HasPackageAndPublishMenuAddedByProject" property here allows the Solution
Explorer "Package and Publish" context menu entry to be enabled for this project even if

View File

@@ -78,6 +78,7 @@
<ProjectReference Include="..\Exts\Microsoft.CmdPal.Ext.Calc\Microsoft.CmdPal.Ext.Calc.csproj" />
<ProjectReference Include="..\Exts\Microsoft.CmdPal.Ext.CmdPalSettings\Microsoft.CmdPal.Ext.Settings.csproj" />
<ProjectReference Include="..\Exts\Microsoft.CmdPal.Ext.Registry\Microsoft.CmdPal.Ext.Registry.csproj" />
<ProjectReference Include="..\Exts\Microsoft.CmdPal.Ext.Shell\Microsoft.CmdPal.Ext.Shell.csproj" />
<ProjectReference Include="..\Exts\Microsoft.CmdPal.Ext.WindowsServices\Microsoft.CmdPal.Ext.WindowsServices.csproj" />
<ProjectReference Include="..\Exts\Microsoft.CmdPal.Ext.WindowsSettings\Microsoft.CmdPal.Ext.WindowsSettings.csproj" />
<ProjectReference Include="..\Exts\Microsoft.CmdPal.Ext.WindowsTerminal\Microsoft.CmdPal.Ext.WindowsTerminal.csproj" />

View File

@@ -8,6 +8,7 @@ using Microsoft.CmdPal.Ext.Bookmarks;
using Microsoft.CmdPal.Ext.Calc;
using Microsoft.CmdPal.Ext.Registry;
using Microsoft.CmdPal.Ext.Settings;
using Microsoft.CmdPal.Ext.Shell;
using Microsoft.CmdPal.Ext.WindowsServices;
using Microsoft.CmdPal.Ext.WindowsSettings;
using Microsoft.CmdPal.Ext.WindowsTerminal;
@@ -61,6 +62,7 @@ public sealed class MainViewModel : IDisposable
BuiltInCommands.Add(new WindowsServicesCommandsProvider());
BuiltInCommands.Add(new RegistryCommandsProvider());
BuiltInCommands.Add(new WindowsSettingsCommandsProvider());
BuiltInCommands.Add(new ShellCommandsProvider());
ResetTopLevel();
@@ -159,5 +161,6 @@ public sealed class MainViewModel : IDisposable
this.AddAlias(new CommandAlias(":", "com.microsoft.cmdpal.registry", true));
this.AddAlias(new CommandAlias("$", "com.microsoft.cmdpal.windowsSettings", true));
this.AddAlias(new CommandAlias("=", "com.microsoft.cmdpal.calculator", true));
this.AddAlias(new CommandAlias(">", "com.microsoft.cmdpal.shell", true));
}
}

View File

@@ -0,0 +1,81 @@
// 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.Text.Json;
using System.Text.Json.Nodes;
using System.Text.Json.Serialization;
namespace Microsoft.CmdPal.Extensions.Helpers;
public sealed class ChoiceSetSetting : Setting<string>
{
public sealed class Choice
{
[JsonPropertyName("value")]
public string Value { get; set; }
[JsonPropertyName("title")]
public string Title { get; set; }
public Choice(string title, string value)
{
Value = value;
Title = title;
}
}
public List<Choice> Choices { get; set; }
private ChoiceSetSetting()
: base()
{
Choices = new();
}
public ChoiceSetSetting(string key, List<Choice> choices)
: base(key, choices.ElementAt(0).Value)
{
Choices = choices;
}
public ChoiceSetSetting(string key, string label, string description, List<Choice> choices)
: base(key, label, description, choices.ElementAt(0).Value)
{
Choices = choices;
}
public override Dictionary<string, object> ToDictionary()
{
return new Dictionary<string, object>
{
{ "type", "Input.ChoiceSet" },
{ "title", Label },
{ "id", Key },
{ "label", Description },
{ "choices", Choices },
{ "value", Value ?? string.Empty },
{ "isRequired", IsRequired },
{ "errorMessage", ErrorMessage },
};
}
public static ChoiceSetSetting LoadFromJson(JsonObject jsonObject)
{
return new ChoiceSetSetting() { Value = jsonObject["value"]?.GetValue<string>() ?? string.Empty };
}
public override void Update(JsonObject payload)
{
// If the key doesn't exist in the payload, don't do anything
if (payload[Key] != null)
{
Value = payload[Key]?.GetValue<string>();
}
}
public override string ToState()
{
return $"\"{Key}\": {JsonSerializer.Serialize(Value)}";
}
}

View File

@@ -0,0 +1,16 @@
// 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.Shell.Helpers;
public enum ExecutionShell
{
Cmd = 0,
Powershell = 1,
RunCommand = 2,
WindowsTerminalPowerShell = 3,
WindowsTerminalPowerShellSeven = 4,
WindowsTerminalCmd = 5,
PowerShellSeven = 6,
}