mirror of
https://github.com/microsoft/PowerToys.git
synced 2026-01-11 23:06:45 +01:00
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:
@@ -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}
|
||||
|
||||
@@ -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();
|
||||
}
|
||||
}
|
||||
@@ -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,
|
||||
}
|
||||
@@ -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() });
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -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();
|
||||
}
|
||||
}
|
||||
@@ -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>
|
||||
@@ -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();
|
||||
}
|
||||
}
|
||||
@@ -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)];
|
||||
}
|
||||
261
src/modules/cmdpal/Exts/Microsoft.CmdPal.Ext.Shell/Properties/Resources.Designer.cs
generated
Normal file
261
src/modules/cmdpal/Exts/Microsoft.CmdPal.Ext.Shell/Properties/Resources.Designer.cs
generated
Normal 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. 'ping', 'cmd').
|
||||
/// </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);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -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>
|
||||
@@ -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];
|
||||
}
|
||||
@@ -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;
|
||||
|
||||
@@ -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"));
|
||||
@@ -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))];
|
||||
}
|
||||
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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" />
|
||||
|
||||
@@ -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));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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)}";
|
||||
}
|
||||
}
|
||||
@@ -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,
|
||||
}
|
||||
Reference in New Issue
Block a user