diff --git a/src/modules/launcher/Plugins/Microsoft.Plugin.Program/Programs/Win32.cs b/src/modules/launcher/Plugins/Microsoft.Plugin.Program/Programs/Win32.cs index 7e214e8d9f..a2875eb8a9 100644 --- a/src/modules/launcher/Plugins/Microsoft.Plugin.Program/Programs/Win32.cs +++ b/src/modules/launcher/Plugins/Microsoft.Plugin.Program/Programs/Win32.cs @@ -12,8 +12,8 @@ using Wox.Infrastructure; using Microsoft.Plugin.Program.Logger; using Wox.Plugin; using System.Windows.Input; -using System.Reflection; - +using System.Reflection; + namespace Microsoft.Plugin.Program.Programs { @@ -32,10 +32,15 @@ namespace Microsoft.Plugin.Program.Programs public bool Enabled { get; set; } public bool hasArguments { get; set; } = false; public string Location => ParentDirectory; + public string AppType { get; set; } private const string ShortcutExtension = "lnk"; private const string ApplicationReferenceExtension = "appref-ms"; private const string ExeExtension = "exe"; + private const string InternetShortcutExtension = "url"; + + private const string InternetShortcutApplication = "Internet shortcut application"; + private const string Win32Application = "Win32 application"; private int Score(string query) { @@ -46,7 +51,6 @@ namespace Microsoft.Plugin.Program.Programs return score; } - public Result Result(string query, IPublicAPI api) { var score = Score(query); @@ -63,7 +67,7 @@ namespace Microsoft.Plugin.Program.Programs var result = new Result { - SubTitle = "Win32 application", + SubTitle = AppType, IcoPath = IcoPath, Score = score, ContextData = this, @@ -100,6 +104,29 @@ namespace Microsoft.Plugin.Program.Programs public List ContextMenus(IPublicAPI api) { + // To add a context menu only to open file location as Internet shortcut applications do not have the functionality to run as admin + if(AppType.Equals(InternetShortcutApplication)) + { + var contextMenuItems = new List + { + new ContextMenuResult + { + PluginName = Assembly.GetExecutingAssembly().GetName().Name, + Title = api.GetTranslation("wox_plugin_program_open_containing_folder"), + Glyph = "\xE838", + FontFamily = "Segoe MDL2 Assets", + AcceleratorKey = Key.E, + AcceleratorModifiers = (ModifierKeys.Control | ModifierKeys.Shift), + Action = _ => + { + Main.StartProcess(Process.Start, new ProcessStartInfo("explorer", ParentDirectory)); + return true; + } + } + }; + return contextMenuItems; + } + var contextMenus = new List { new ContextMenuResult @@ -167,7 +194,8 @@ namespace Microsoft.Plugin.Program.Programs ParentDirectory = Directory.GetParent(path).FullName, Description = string.Empty, Valid = true, - Enabled = true + Enabled = true, + AppType = Win32Application }; return p; } @@ -180,6 +208,74 @@ namespace Microsoft.Plugin.Program.Programs } } + // This function filters Internet Shortcut programs + private static Win32 InternetShortcutProgram(string path) + { + string[] lines = System.IO.File.ReadAllLines(path); + string appName = string.Empty; + string iconPath = string.Empty; + string scheme = string.Empty; + bool validApp = false; + + const string steamScheme = "steam"; + const string urlPrefix = "URL="; + const string iconFilePrefix = "IconFile="; + const string hostnameRun = "run"; + const string hostnameRunGameId = "rungameid"; + + foreach(string line in lines) + { + if(line.StartsWith(urlPrefix)) + { + var urlPath = line.Substring(urlPrefix.Length); + Uri uri = new Uri(urlPath); + + // To filter out only those steam shortcuts which have 'run' or 'rungameid' as the hostname + if(uri.Scheme.Equals(steamScheme, StringComparison.OrdinalIgnoreCase) + && (uri.Host.Equals(hostnameRun, StringComparison.OrdinalIgnoreCase) + || uri.Host.Equals(hostnameRunGameId, StringComparison.OrdinalIgnoreCase))) + { + validApp = true; + } + } + + if(line.StartsWith(iconFilePrefix)) + { + iconPath = line.Substring(iconFilePrefix.Length); + } + } + + if(!validApp) + { + return new Win32() { Valid = false, Enabled = false }; + } + + try + { + var p = new Win32 + { + Name = Path.GetFileNameWithoutExtension(path), + ExecutableName = Path.GetFileName(path), + IcoPath = iconPath, + FullPath = path.ToLower(), + UniqueIdentifier = path, + ParentDirectory = Directory.GetParent(path).FullName, + Description = InternetShortcutApplication, + Valid = true, + Enabled = true, + AppType = InternetShortcutApplication + }; + return p; + } + catch (Exception e) when (e is SecurityException || e is UnauthorizedAccessException) + { + ProgramLogger.LogException($"|Win32|InternetShortcutProgram|{path}" + + $"|Permission denied when trying to load the program from {path}", e); + + return new Win32() { Valid = false, Enabled = false }; + } + } + private static Win32 LnkProgram(string path) { var program = Win32Program(path); @@ -364,10 +460,11 @@ namespace Microsoft.Plugin.Program.Programs .Distinct() .ToArray(); - var programs1 = paths.AsParallel().Where(p => Extension(p) == ShortcutExtension).Select(LnkProgram); - var programs2 = paths.AsParallel().Where(p => Extension(p) == ApplicationReferenceExtension).Select(Win32Program); + var programs1 = paths.AsParallel().Where(p => Extension(p).Equals(ShortcutExtension, StringComparison.OrdinalIgnoreCase)).Select(LnkProgram); + var programs2 = paths.AsParallel().Where(p => Extension(p).Equals(ApplicationReferenceExtension, StringComparison.OrdinalIgnoreCase)).Select(Win32Program); + var programs3 = paths.AsParallel().Where(p => Extension(p).Equals(InternetShortcutExtension, StringComparison.OrdinalIgnoreCase)).Select(InternetShortcutProgram); - return programs1.Concat(programs2).Where(p => p.Valid); + return programs1.Concat(programs2).Where(p => p.Valid).Concat(programs3).Where(p => p.Valid); } private static ParallelQuery AppPathsPrograms(string[] suffixes) diff --git a/src/modules/launcher/Plugins/Microsoft.Plugin.Program/Settings.cs b/src/modules/launcher/Plugins/Microsoft.Plugin.Program/Settings.cs index 8fbe4ba489..b49b7c7773 100644 --- a/src/modules/launcher/Plugins/Microsoft.Plugin.Program/Settings.cs +++ b/src/modules/launcher/Plugins/Microsoft.Plugin.Program/Settings.cs @@ -9,7 +9,7 @@ namespace Microsoft.Plugin.Program public DateTime LastIndexTime { get; set; } public List ProgramSources { get; set; } = new List(); public List DisabledProgramSources { get; set; } = new List(); - public string[] ProgramSuffixes { get; set; } = {"bat", "appref-ms", "exe", "lnk"}; + public string[] ProgramSuffixes { get; set; } = {"bat", "appref-ms", "exe", "lnk", "url"}; public bool EnableStartMenuSource { get; set; } = true;