RunExeItem.cs
  1  // Copyright (c) Microsoft Corporation
  2  // The Microsoft Corporation licenses this file to you under the MIT license.
  3  // See the LICENSE file in the project root for more information.
  4  
  5  using Microsoft.CmdPal.Core.Common.Services;
  6  using Microsoft.CmdPal.Ext.Shell.Helpers;
  7  using Microsoft.CommandPalette.Extensions;
  8  using Microsoft.CommandPalette.Extensions.Toolkit;
  9  using Windows.Storage.Streams;
 10  using Windows.System;
 11  
 12  namespace Microsoft.CmdPal.Ext.Shell.Pages;
 13  
 14  internal sealed partial class RunExeItem : ListItem
 15  {
 16      private readonly Lazy<IconInfo> _icon;
 17      private readonly Action<string>? _addToHistory;
 18      private readonly ITelemetryService? _telemetryService;
 19  
 20      public override IIconInfo? Icon { get => _icon.Value; set => base.Icon = value; }
 21  
 22      internal string FullExePath { get; private set; }
 23  
 24      internal string Exe { get; private set; }
 25  
 26      private string _args = string.Empty;
 27  
 28      private string FullString => string.IsNullOrEmpty(_args) ? Exe : $"{Exe} {_args}";
 29  
 30      public RunExeItem(
 31          string exe,
 32          string args,
 33          string fullExePath,
 34          Action<string>? addToHistory,
 35          ITelemetryService? telemetryService = null)
 36      {
 37          FullExePath = fullExePath;
 38          Exe = exe;
 39          var command = new AnonymousCommand(Run)
 40          {
 41              Name = ResourceLoaderInstance.GetString("generic_run_command"),
 42              Result = CommandResult.Dismiss(),
 43          };
 44          Command = command;
 45          Subtitle = FullExePath;
 46  
 47          _icon = new Lazy<IconInfo>(() =>
 48          {
 49              var t = FetchIcon();
 50              t.Wait();
 51              return t.Result;
 52          });
 53  
 54          _addToHistory = addToHistory;
 55          _telemetryService = telemetryService;
 56  
 57          UpdateArgs(args);
 58  
 59          MoreCommands = [
 60              new CommandContextItem(
 61                  new AnonymousCommand(RunAsAdmin)
 62              {
 63                  Name = ResourceLoaderInstance.GetString("cmd_run_as_administrator"),
 64                  Icon = Icons.AdminIcon,
 65              }) { RequestedShortcut = KeyChordHelpers.FromModifiers(ctrl: true, shift: true, vkey: VirtualKey.Enter) },
 66              new CommandContextItem(
 67                  new AnonymousCommand(RunAsOther)
 68              {
 69                  Name = ResourceLoaderInstance.GetString("cmd_run_as_user"),
 70                  Icon = Icons.UserIcon,
 71              }) { RequestedShortcut = KeyChordHelpers.FromModifiers(ctrl: true, shift: true, vkey: VirtualKey.U) },
 72          ];
 73      }
 74  
 75      internal void UpdateArgs(string args)
 76      {
 77          _args = args;
 78          Title = string.IsNullOrEmpty(_args) ? Exe : Exe + " " + _args; // todo! you're smarter than this
 79      }
 80  
 81      public async Task<IconInfo> FetchIcon()
 82      {
 83          IconInfo? icon = null;
 84  
 85          try
 86          {
 87              var stream = await ThumbnailHelper.GetThumbnail(FullExePath);
 88              if (stream is not null)
 89              {
 90                  var data = new IconData(RandomAccessStreamReference.CreateFromStream(stream));
 91                  icon = new IconInfo(data, data);
 92                  ((AnonymousCommand?)Command)!.Icon = icon;
 93              }
 94          }
 95          catch
 96          {
 97          }
 98  
 99          icon = icon ?? new IconInfo(FullExePath);
100          return icon;
101      }
102  
103      public void Run()
104      {
105          _addToHistory?.Invoke(FullString);
106  
107          var success = ShellHelpers.OpenInShell(FullExePath, _args);
108  
109          _telemetryService?.LogRunCommand(FullString, false, success);
110      }
111  
112      public void RunAsAdmin()
113      {
114          _addToHistory?.Invoke(FullString);
115  
116          var success = ShellHelpers.OpenInShell(FullExePath, _args, runAs: ShellHelpers.ShellRunAsType.Administrator);
117  
118          _telemetryService?.LogRunCommand(FullString, true, success);
119      }
120  
121      public void RunAsOther()
122      {
123          _addToHistory?.Invoke(FullString);
124  
125          var success = ShellHelpers.OpenInShell(FullExePath, _args, runAs: ShellHelpers.ShellRunAsType.OtherUser);
126  
127          _telemetryService?.LogRunCommand(FullString, false, success);
128      }
129  }