From 42a305ba3683572a7a7f67edf91f29c4b48789ca Mon Sep 17 00:00:00 2001 From: 0x5bfa <62196528+0x5bfa@users.noreply.github.com> Date: Sat, 3 Aug 2024 11:37:38 +0900 Subject: [PATCH] Init --- .../Contracts/IWindowsAppLauncherService.cs | 14 + .../Helpers/Application/AppLifecycleHelper.cs | 1 + .../Helpers/Win32/Win32Helper.Process.cs | 3 +- src/Files.App/Program.cs | 3 +- .../Windows/WindowsAppLauncherService.cs | 245 +++++++++++++++++ .../UserControls/Widgets/DrivesWidget.xaml.cs | 3 +- src/Files.App/Utils/Shell/LaunchHelper.cs | 257 ------------------ .../Storage/Helpers/StorageSenseHelper.cs | 24 -- .../Operations/ShellFilesystemOperations.cs | 12 +- .../Properties/BasePropertiesPage.cs | 3 +- .../Properties/CompatibilityViewModel.cs | 5 +- .../UserControls/AddressToolbarViewModel.cs | 9 +- 12 files changed, 283 insertions(+), 296 deletions(-) create mode 100644 src/Files.App/Data/Contracts/IWindowsAppLauncherService.cs create mode 100644 src/Files.App/Services/Windows/WindowsAppLauncherService.cs delete mode 100644 src/Files.App/Utils/Shell/LaunchHelper.cs delete mode 100644 src/Files.App/Utils/Storage/Helpers/StorageSenseHelper.cs diff --git a/src/Files.App/Data/Contracts/IWindowsAppLauncherService.cs b/src/Files.App/Data/Contracts/IWindowsAppLauncherService.cs new file mode 100644 index 000000000000..42e39814f61c --- /dev/null +++ b/src/Files.App/Data/Contracts/IWindowsAppLauncherService.cs @@ -0,0 +1,14 @@ +// Copyright (c) 2024 Files Community +// Licensed under the MIT License. See the LICENSE. + +namespace Files.App.Data.Contracts +{ + public interface IWindowsAppLauncherService + { + Task LaunchStorageSensePolicySettingsAsync(); + + Task LaunchProgramCompatibilityTroubleshooterAsync(string path); + + Task LaunchApplicationAsync(string path, string arguments, string workingDirectory); + } +} diff --git a/src/Files.App/Helpers/Application/AppLifecycleHelper.cs b/src/Files.App/Helpers/Application/AppLifecycleHelper.cs index 59af809138c7..70bddd77a0fb 100644 --- a/src/Files.App/Helpers/Application/AppLifecycleHelper.cs +++ b/src/Files.App/Helpers/Application/AppLifecycleHelper.cs @@ -164,6 +164,7 @@ public static IHost ConfigureHost() .AddSingleton() .AddSingleton() // Services + .AddSingleton() .AddSingleton() .AddSingleton() .AddSingleton() diff --git a/src/Files.App/Helpers/Win32/Win32Helper.Process.cs b/src/Files.App/Helpers/Win32/Win32Helper.Process.cs index 1f73eeb9d795..104994de256a 100644 --- a/src/Files.App/Helpers/Win32/Win32Helper.Process.cs +++ b/src/Files.App/Helpers/Win32/Win32Helper.Process.cs @@ -83,7 +83,8 @@ public static async Task InvokeWin32ComponentsAsync(IEnumerable ap } else { - return await LaunchHelper.LaunchAppAsync(application, arguments, workingDirectory); + var windowsLaunchAppService = Ioc.Default.GetRequiredService(); + return await windowsLaunchAppService.LaunchApplicationAsync(application, arguments, workingDirectory); } } diff --git a/src/Files.App/Program.cs b/src/Files.App/Program.cs index a0239827dc27..aa6a9e1391f8 100644 --- a/src/Files.App/Program.cs +++ b/src/Files.App/Program.cs @@ -275,7 +275,8 @@ public static void OpenFileFromTile(string filePath) Task.Run(() => { - LaunchHelper.LaunchAppAsync(filePath, null, null).Wait(); + var windowsLaunchAppService = Ioc.Default.GetRequiredService(); + windowsLaunchAppService.LaunchApplicationAsync(filePath, null, null).Wait(); SetEvent(eventHandle); }); diff --git a/src/Files.App/Services/Windows/WindowsAppLauncherService.cs b/src/Files.App/Services/Windows/WindowsAppLauncherService.cs new file mode 100644 index 000000000000..50ec46249b5e --- /dev/null +++ b/src/Files.App/Services/Windows/WindowsAppLauncherService.cs @@ -0,0 +1,245 @@ +// Copyright (c) 2024 Files Community +// Licensed under the MIT License. See the LICENSE. + +using Files.Shared.Helpers; +using Microsoft.Extensions.Logging; +using Windows.System; + +namespace Files.App.Services +{ + /// + public class WindowsAppLauncherService : IWindowsAppLauncherService + { + /// + public async Task LaunchStorageSensePolicySettingsAsync() + { + bool result = await Launcher.LaunchUriAsync(new Uri("ms-settings:storagepolicies")); + return result; + } + + /// + public async Task LaunchProgramCompatibilityTroubleshooterAsync(string path) + { + var compatibilityTroubleshooterAnswerFile = SystemIO.Path.Combine(SystemIO.Path.GetTempPath(), "CompatibilityTroubleshooterAnswerFile.xml"); + string troubleshooterAnswerFileText = $@"CompatTab{path}"; + + try + { + SystemIO.File.WriteAllText(compatibilityTroubleshooterAnswerFile, troubleshooterAnswerFileText); + } + catch (SystemIO.IOException) + { + // Try with a different file name + SafetyExtensions.IgnoreExceptions(() => + { + compatibilityTroubleshooterAnswerFile = SystemIO.Path.Combine(SystemIO.Path.GetTempPath(), "CompatibilityTroubleshooterAnswerFile1.xml"); + SystemIO.File.WriteAllText(compatibilityTroubleshooterAnswerFile, troubleshooterAnswerFileText); + }); + } + + return await LaunchApplicationAsync("MSDT.exe", @$"/id PCWDiagnostic /af ""{compatibilityTroubleshooterAnswerFile}""", ""); + } + + /// + public async Task LaunchApplicationAsync(string path, string arguments, string workingDirectory) + { + var currentWindows = Win32Helper.GetDesktopWindows(); + + // Use PowerShell to mount Vhd Disk as this requires admin rights + if (FileExtensionHelpers.IsVhdFile(path)) + return await Win32Helper.MountVhdDisk(path); + + try + { + using Process process = new Process(); + process.StartInfo.UseShellExecute = false; + process.StartInfo.FileName = path; + + // Show window if workingDirectory (opening terminal) + process.StartInfo.CreateNoWindow = string.IsNullOrEmpty(workingDirectory); + + if (arguments.Equals("RunAs", StringComparison.OrdinalIgnoreCase)) + { + process.StartInfo.UseShellExecute = true; + process.StartInfo.Verb = "RunAs"; + + if (FileExtensionHelpers.IsMsiFile(path)) + { + process.StartInfo.FileName = "MSIEXEC.exe"; + process.StartInfo.Arguments = $"/a \"{path}\""; + } + } + else if (arguments.Equals("RunAsUser", StringComparison.OrdinalIgnoreCase)) + { + process.StartInfo.UseShellExecute = true; + process.StartInfo.Verb = "RunAsUser"; + + if (FileExtensionHelpers.IsMsiFile(path)) + { + process.StartInfo.FileName = "MSIEXEC.exe"; + process.StartInfo.Arguments = $"/i \"{path}\""; + } + } + else + { + process.StartInfo.Arguments = arguments; + + // Refresh env variables for the child process + foreach (DictionaryEntry ent in Environment.GetEnvironmentVariables(EnvironmentVariableTarget.User)) + process.StartInfo.EnvironmentVariables[(string)ent.Key] = (string)ent.Value; + + process.StartInfo.EnvironmentVariables["PATH"] = string.Join(';', + Environment.GetEnvironmentVariable("PATH", EnvironmentVariableTarget.Machine), + Environment.GetEnvironmentVariable("PATH", EnvironmentVariableTarget.User)); + } + + process.StartInfo.WorkingDirectory = string.IsNullOrEmpty(workingDirectory) ? PathNormalization.GetParentDir(path) : workingDirectory; + process.Start(); + + Win32Helper.BringToForeground(currentWindows); + + return true; + } + catch (Win32Exception) + { + using Process process = new Process(); + process.StartInfo.UseShellExecute = true; + process.StartInfo.FileName = path; + process.StartInfo.CreateNoWindow = true; + process.StartInfo.Arguments = arguments; + process.StartInfo.WorkingDirectory = string.IsNullOrEmpty(workingDirectory) ? PathNormalization.GetParentDir(path) : workingDirectory; + + try + { + process.Start(); + + Win32Helper.BringToForeground(currentWindows); + + return true; + } + catch (Win32Exception ex) when (ex.NativeErrorCode == 50) + { + // ShellExecute return code 50 (ERROR_NOT_SUPPORTED) for some exes (#15179) + return Win32Helper.RunPowershellCommand($"\"{path}\"", PowerShellExecutionOptions.Hidden); + } + catch (Win32Exception) + { + try + { + var opened = await Win32Helper.StartSTATask(async () => + { + var split = path.Split('|').Where(x => !string.IsNullOrWhiteSpace(x)).Select(x => GetMtpPath(x)); + if (split.Count() == 1) + { + Process.Start(split.First()); + + Win32Helper.BringToForeground(currentWindows); + } + else + { + var groups = split.GroupBy(x => new + { + Dir = SystemIO.Path.GetDirectoryName(x), + Prog = Win32Helper.GetFileAssociationAsync(x).Result ?? SystemIO.Path.GetExtension(x) + }); + + foreach (var group in groups) + { + if (!group.Any()) + continue; + + using var cMenu = await ContextMenu.GetContextMenuForFiles(group.ToArray(), Vanara.PInvoke.Shell32.CMF.CMF_DEFAULTONLY); + + if (cMenu is not null) + await cMenu.InvokeVerb(Vanara.PInvoke.Shell32.CMDSTR_OPEN); + } + } + + return true; + }); + + if (!opened) + { + if (path.StartsWith(@"\\SHELL\", StringComparison.Ordinal)) + { + opened = await Win32Helper.StartSTATask(async () => + { + using var cMenu = await ContextMenu.GetContextMenuForFiles(new[] { path }, Vanara.PInvoke.Shell32.CMF.CMF_DEFAULTONLY); + + if (cMenu is not null) + await cMenu.InvokeItem(cMenu.Items.FirstOrDefault()?.ID ?? -1); + + return true; + }); + } + } + + if (!opened) + { + var isAlternateStream = RegexHelpers.AlternateStream().IsMatch(path); + if (isAlternateStream) + { + var basePath = SystemIO.Path.Combine(Environment.GetEnvironmentVariable("TEMP"), Guid.NewGuid().ToString("n")); + Vanara.PInvoke.Kernel32.CreateDirectory(basePath); + + var tempPath = SystemIO.Path.Combine(basePath, new string(SystemIO.Path.GetFileName(path).SkipWhile(x => x != ':').Skip(1).ToArray())); + using var hFileSrc = Vanara.PInvoke.Kernel32.CreateFile(path, Vanara.PInvoke.Kernel32.FileAccess.GENERIC_READ, SystemIO.FileShare.ReadWrite, null, SystemIO.FileMode.Open, Vanara.PInvoke.FileFlagsAndAttributes.FILE_ATTRIBUTE_NORMAL); + using var hFileDst = Vanara.PInvoke.Kernel32.CreateFile(tempPath, Vanara.PInvoke.Kernel32.FileAccess.GENERIC_WRITE, 0, null, SystemIO.FileMode.Create, Vanara.PInvoke.FileFlagsAndAttributes.FILE_ATTRIBUTE_NORMAL | Vanara.PInvoke.FileFlagsAndAttributes.FILE_ATTRIBUTE_READONLY); + + if (!hFileSrc.IsInvalid && !hFileDst.IsInvalid) + { + // Copy ADS to temp folder and open + using (var inStream = new SystemIO.FileStream(hFileSrc.DangerousGetHandle(), SystemIO.FileAccess.Read)) + using (var outStream = new SystemIO.FileStream(hFileDst.DangerousGetHandle(), SystemIO.FileAccess.Write)) + { + await inStream.CopyToAsync(outStream); + await outStream.FlushAsync(); + } + + opened = await LaunchApplicationAsync(tempPath, arguments, workingDirectory); + } + } + } + + return opened; + } + catch (Win32Exception) + { + // Cannot open file (e.g DLL) + return false; + } + catch (ArgumentException) + { + // Cannot open file (e.g DLL) + return false; + } + } + } + catch (InvalidOperationException) + { + // Invalid file path + return false; + } + catch (Exception ex) + { + // Generic error, log + App.Logger.LogWarning(ex, $"Error launching: {path}"); + return false; + } + + string GetMtpPath(string executable) + { + if (executable.StartsWith("\\\\?\\", StringComparison.Ordinal)) + { + using var computer = new Vanara.Windows.Shell.ShellFolder(Vanara.PInvoke.Shell32.KNOWNFOLDERID.FOLDERID_ComputerFolder); + using var device = computer.FirstOrDefault(i => executable.Replace("\\\\?\\", "", StringComparison.Ordinal).StartsWith(i.Name, StringComparison.Ordinal)); + var deviceId = device?.ParsingName; + var itemPath = RegexHelpers.WindowsPath().Replace(executable, ""); + return deviceId is not null ? SystemIO.Path.Combine(deviceId, itemPath) : executable; + } + + return executable; + } + } + } +} diff --git a/src/Files.App/UserControls/Widgets/DrivesWidget.xaml.cs b/src/Files.App/UserControls/Widgets/DrivesWidget.xaml.cs index 7cfef19e8ddc..dbbadfa1a603 100644 --- a/src/Files.App/UserControls/Widgets/DrivesWidget.xaml.cs +++ b/src/Files.App/UserControls/Widgets/DrivesWidget.xaml.cs @@ -13,6 +13,7 @@ namespace Files.App.UserControls.Widgets public sealed partial class DrivesWidget : UserControl { public DrivesWidgetViewModel ViewModel { get; set; } = Ioc.Default.GetRequiredService(); + private IWindowsAppLauncherService WindowsLaunchAppService = Ioc.Default.GetRequiredService(); public DrivesWidget() { @@ -52,7 +53,7 @@ private async void GoToStorageSense_Click(object sender, RoutedEventArgs e) button.Tag.ToString() is not string path) return; - await StorageSenseHelper.OpenStorageSenseAsync(path); + await WindowsLaunchAppService.LaunchStorageSensePolicySettingsAsync(); } } } diff --git a/src/Files.App/Utils/Shell/LaunchHelper.cs b/src/Files.App/Utils/Shell/LaunchHelper.cs deleted file mode 100644 index 049a0b741dea..000000000000 --- a/src/Files.App/Utils/Shell/LaunchHelper.cs +++ /dev/null @@ -1,257 +0,0 @@ -// Copyright (c) 2024 Files Community -// Licensed under the MIT License. See the LICENSE. - -using Files.Shared.Helpers; -using Microsoft.Extensions.Logging; -using System.IO; -using Vanara.PInvoke; -using Vanara.Windows.Shell; - -namespace Files.App.Utils.Shell -{ - /// - /// Provides static helper for launching external executable files. - /// - public static class LaunchHelper - { - public static void LaunchSettings(string page) - { - var appActiveManager = new Shell32.IApplicationActivationManager(); - - appActiveManager.ActivateApplication( - "windows.immersivecontrolpanel_cw5n1h2txyewy!microsoft.windows.immersivecontrolpanel", - page, - Shell32.ACTIVATEOPTIONS.AO_NONE, - out _); - } - - public static Task LaunchAppAsync(string application, string arguments, string workingDirectory) - { - return HandleApplicationLaunch(application, arguments, workingDirectory); - } - - public static Task RunCompatibilityTroubleshooterAsync(string filePath) - { - var compatibilityTroubleshooterAnswerFile = Path.Combine(Path.GetTempPath(), "CompatibilityTroubleshooterAnswerFile.xml"); - - try - { - File.WriteAllText(compatibilityTroubleshooterAnswerFile, string.Format("CompatTab{0}", filePath)); - } - catch (IOException) - { - // Try with a different file name - SafetyExtensions.IgnoreExceptions(() => - { - compatibilityTroubleshooterAnswerFile = Path.Combine(Path.GetTempPath(), "CompatibilityTroubleshooterAnswerFile1.xml"); - File.WriteAllText(compatibilityTroubleshooterAnswerFile, string.Format("CompatTab{0}", filePath)); - }); - } - - return HandleApplicationLaunch("MSDT.exe", $"/id PCWDiagnostic /af \"{compatibilityTroubleshooterAnswerFile}\"", ""); - } - - private static async Task HandleApplicationLaunch(string application, string arguments, string workingDirectory) - { - var currentWindows = Win32Helper.GetDesktopWindows(); - - if (FileExtensionHelpers.IsVhdFile(application)) - { - // Use PowerShell to mount Vhd Disk as this requires admin rights - return await Win32Helper.MountVhdDisk(application); - } - - try - { - using Process process = new Process(); - process.StartInfo.UseShellExecute = false; - process.StartInfo.FileName = application; - - // Show window if workingDirectory (opening terminal) - process.StartInfo.CreateNoWindow = string.IsNullOrEmpty(workingDirectory); - - if (arguments == "RunAs") - { - process.StartInfo.UseShellExecute = true; - process.StartInfo.Verb = "RunAs"; - - if (FileExtensionHelpers.IsMsiFile(application)) - { - process.StartInfo.FileName = "MSIEXEC.exe"; - process.StartInfo.Arguments = $"/a \"{application}\""; - } - } - else if (arguments == "RunAsUser") - { - process.StartInfo.UseShellExecute = true; - process.StartInfo.Verb = "RunAsUser"; - - if (FileExtensionHelpers.IsMsiFile(application)) - { - process.StartInfo.FileName = "MSIEXEC.exe"; - process.StartInfo.Arguments = $"/i \"{application}\""; - } - } - else - { - process.StartInfo.Arguments = arguments; - - // Refresh env variables for the child process - foreach (DictionaryEntry ent in Environment.GetEnvironmentVariables(EnvironmentVariableTarget.User)) - process.StartInfo.EnvironmentVariables[(string)ent.Key] = (string)ent.Value; - - process.StartInfo.EnvironmentVariables["PATH"] = string.Join(';', - Environment.GetEnvironmentVariable("PATH", EnvironmentVariableTarget.Machine), - Environment.GetEnvironmentVariable("PATH", EnvironmentVariableTarget.User)); - } - - process.StartInfo.WorkingDirectory = string.IsNullOrEmpty(workingDirectory) ? PathNormalization.GetParentDir(application) : workingDirectory; - process.Start(); - - Win32Helper.BringToForeground(currentWindows); - - return true; - } - catch (Win32Exception) - { - using Process process = new Process(); - process.StartInfo.UseShellExecute = true; - process.StartInfo.FileName = application; - process.StartInfo.CreateNoWindow = true; - process.StartInfo.Arguments = arguments; - process.StartInfo.WorkingDirectory = string.IsNullOrEmpty(workingDirectory) ? PathNormalization.GetParentDir(application) : workingDirectory; - - try - { - process.Start(); - - Win32Helper.BringToForeground(currentWindows); - - return true; - } - catch (Win32Exception ex) when (ex.NativeErrorCode == 50) - { - // ShellExecute return code 50 (ERROR_NOT_SUPPORTED) for some exes (#15179) - return Win32Helper.RunPowershellCommand($"\"{application}\"", PowerShellExecutionOptions.Hidden); - } - catch (Win32Exception) - { - try - { - var opened = await Win32Helper.StartSTATask(async () => - { - var split = application.Split('|').Where(x => !string.IsNullOrWhiteSpace(x)).Select(x => GetMtpPath(x)); - if (split.Count() == 1) - { - Process.Start(split.First()); - - Win32Helper.BringToForeground(currentWindows); - } - else - { - var groups = split.GroupBy(x => new - { - Dir = Path.GetDirectoryName(x), - Prog = Win32Helper.GetFileAssociationAsync(x).Result ?? Path.GetExtension(x) - }); - - foreach (var group in groups) - { - if (!group.Any()) - continue; - - using var cMenu = await ContextMenu.GetContextMenuForFiles(group.ToArray(), Shell32.CMF.CMF_DEFAULTONLY); - - if (cMenu is not null) - await cMenu.InvokeVerb(Shell32.CMDSTR_OPEN); - } - } - - return true; - }); - - if (!opened) - { - if (application.StartsWith(@"\\SHELL\", StringComparison.Ordinal)) - { - opened = await Win32Helper.StartSTATask(async () => - { - using var cMenu = await ContextMenu.GetContextMenuForFiles(new[] { application }, Shell32.CMF.CMF_DEFAULTONLY); - - if (cMenu is not null) - await cMenu.InvokeItem(cMenu.Items.FirstOrDefault()?.ID ?? -1); - - return true; - }); - } - } - - if (!opened) - { - var isAlternateStream = RegexHelpers.AlternateStream().IsMatch(application); - if (isAlternateStream) - { - var basePath = Path.Combine(Environment.GetEnvironmentVariable("TEMP"), Guid.NewGuid().ToString("n")); - Kernel32.CreateDirectory(basePath); - - var tempPath = Path.Combine(basePath, new string(Path.GetFileName(application).SkipWhile(x => x != ':').Skip(1).ToArray())); - using var hFileSrc = Kernel32.CreateFile(application, Kernel32.FileAccess.GENERIC_READ, FileShare.ReadWrite, null, FileMode.Open, FileFlagsAndAttributes.FILE_ATTRIBUTE_NORMAL); - using var hFileDst = Kernel32.CreateFile(tempPath, Kernel32.FileAccess.GENERIC_WRITE, 0, null, FileMode.Create, FileFlagsAndAttributes.FILE_ATTRIBUTE_NORMAL | FileFlagsAndAttributes.FILE_ATTRIBUTE_READONLY); - - if (!hFileSrc.IsInvalid && !hFileDst.IsInvalid) - { - // Copy ADS to temp folder and open - using (var inStream = new FileStream(hFileSrc.DangerousGetHandle(), FileAccess.Read)) - using (var outStream = new FileStream(hFileDst.DangerousGetHandle(), FileAccess.Write)) - { - await inStream.CopyToAsync(outStream); - await outStream.FlushAsync(); - } - - opened = await HandleApplicationLaunch(tempPath, arguments, workingDirectory); - } - } - } - - return opened; - } - catch (Win32Exception) - { - // Cannot open file (e.g DLL) - return false; - } - catch (ArgumentException) - { - // Cannot open file (e.g DLL) - return false; - } - } - } - catch (InvalidOperationException) - { - // Invalid file path - return false; - } - catch (Exception ex) - { - // Generic error, log - App.Logger.LogWarning(ex, $"Error launching: {application}"); - return false; - } - } - - private static string GetMtpPath(string executable) - { - if (executable.StartsWith("\\\\?\\", StringComparison.Ordinal)) - { - using var computer = new ShellFolder(Shell32.KNOWNFOLDERID.FOLDERID_ComputerFolder); - using var device = computer.FirstOrDefault(i => executable.Replace("\\\\?\\", "", StringComparison.Ordinal).StartsWith(i.Name, StringComparison.Ordinal)); - var deviceId = device?.ParsingName; - var itemPath = RegexHelpers.WindowsPath().Replace(executable, ""); - return deviceId is not null ? Path.Combine(deviceId, itemPath) : executable; - } - - return executable; - } - } -} diff --git a/src/Files.App/Utils/Storage/Helpers/StorageSenseHelper.cs b/src/Files.App/Utils/Storage/Helpers/StorageSenseHelper.cs deleted file mode 100644 index 4679ee851af2..000000000000 --- a/src/Files.App/Utils/Storage/Helpers/StorageSenseHelper.cs +++ /dev/null @@ -1,24 +0,0 @@ -// Copyright (c) 2024 Files Community -// Licensed under the MIT License. See the LICENSE. - -using Windows.Foundation.Metadata; -using Windows.System; - -namespace Files.App.Utils.Storage -{ - internal sealed class StorageSenseHelper - { - public static async Task OpenStorageSenseAsync(string path) - { - if (!path.StartsWith(Constants.UserEnvironmentPaths.SystemDrivePath, StringComparison.OrdinalIgnoreCase) - && ApiInformation.IsApiContractPresent("Windows.Foundation.UniversalApiContract", 8)) - { - LaunchHelper.LaunchSettings("page=SettingsPageStorageSenseStorageOverview&target=SystemSettings_StorageSense_VolumeListLink"); - } - else - { - await Launcher.LaunchUriAsync(new Uri("ms-settings:storagesense")); - } - } - } -} diff --git a/src/Files.App/Utils/Storage/Operations/ShellFilesystemOperations.cs b/src/Files.App/Utils/Storage/Operations/ShellFilesystemOperations.cs index bcab988dc692..193cbfad4574 100644 --- a/src/Files.App/Utils/Storage/Operations/ShellFilesystemOperations.cs +++ b/src/Files.App/Utils/Storage/Operations/ShellFilesystemOperations.cs @@ -224,13 +224,13 @@ await sourceMatch.Select(x => x.dest).ToListAsync(), var args = CommandLineParser.SplitArguments(newEntryInfo.Command); if (args.Any()) { - if (await LaunchHelper.LaunchAppAsync( - args[0].Replace("\"", "", StringComparison.Ordinal), - string.Join(' ', args.Skip(1)).Replace("%1", source.Path), - PathNormalization.GetParentDir(source.Path))) - { + var windowsLaunchAppService = Ioc.Default.GetRequiredService(); + + if (await windowsLaunchAppService.LaunchApplicationAsync( + args[0].Replace("\"", "", StringComparison.Ordinal), + string.Join(' ', args.Skip(1)).Replace("%1", source.Path), + PathNormalization.GetParentDir(source.Path))) success = true; - } } } else diff --git a/src/Files.App/ViewModels/Properties/BasePropertiesPage.cs b/src/Files.App/ViewModels/Properties/BasePropertiesPage.cs index 5524d9e5bc24..c569c99afdef 100644 --- a/src/Files.App/ViewModels/Properties/BasePropertiesPage.cs +++ b/src/Files.App/ViewModels/Properties/BasePropertiesPage.cs @@ -13,6 +13,7 @@ namespace Files.App.ViewModels.Properties public abstract class BasePropertiesPage : Page, IDisposable { private ICommonDialogService CommonDialogService { get; } = Ioc.Default.GetRequiredService(); + private IWindowsAppLauncherService WindowsLaunchAppService = Ioc.Default.GetRequiredService(); public IShellPage AppInstance = null; @@ -41,7 +42,7 @@ protected override void OnNavigatedTo(NavigationEventArgs e) ViewModel.CleanupVisibility = props.Drive.Type != DriveType.Network; ViewModel.FormatVisibility = !(props.Drive.Type == DriveType.Network || string.Equals(props.Drive.Path, $@"{Constants.UserEnvironmentPaths.SystemDrivePath}\", StringComparison.OrdinalIgnoreCase)); - ViewModel.CleanupDriveCommand = new AsyncRelayCommand(() => StorageSenseHelper.OpenStorageSenseAsync(props.Drive.Path)); + ViewModel.CleanupDriveCommand = new AsyncRelayCommand(() => WindowsLaunchAppService.LaunchStorageSensePolicySettingsAsync()); ViewModel.FormatDriveCommand = new RelayCommand(async () => { try diff --git a/src/Files.App/ViewModels/Properties/CompatibilityViewModel.cs b/src/Files.App/ViewModels/Properties/CompatibilityViewModel.cs index c5ed13885e91..27034227552b 100644 --- a/src/Files.App/ViewModels/Properties/CompatibilityViewModel.cs +++ b/src/Files.App/ViewModels/Properties/CompatibilityViewModel.cs @@ -12,7 +12,8 @@ public sealed class CompatibilityViewModel : ObservableObject { // Dependency injections - private IWindowsCompatibilityService WindowsCompatibilityService { get; } = Ioc.Default.GetRequiredService(); + private IWindowsCompatibilityService WindowsCompatibilityService = Ioc.Default.GetRequiredService(); + private IWindowsAppLauncherService WindowsLaunchAppService = Ioc.Default.GetRequiredService(); // Properties @@ -118,7 +119,7 @@ public bool SetCompatibilityOptions() private Task ExecuteRunTroubleshooterCommand() { - return LaunchHelper.RunCompatibilityTroubleshooterAsync(ItemPath); + return WindowsLaunchAppService.LaunchProgramCompatibilityTroubleshooterAsync(ItemPath); } } } diff --git a/src/Files.App/ViewModels/UserControls/AddressToolbarViewModel.cs b/src/Files.App/ViewModels/UserControls/AddressToolbarViewModel.cs index c71ed669c2c8..a1138b3edb40 100644 --- a/src/Files.App/ViewModels/UserControls/AddressToolbarViewModel.cs +++ b/src/Files.App/ViewModels/UserControls/AddressToolbarViewModel.cs @@ -816,9 +816,12 @@ private void SavePathToHistory(string path) private static async Task LaunchApplicationFromPath(string currentInput, string workingDir) { var args = CommandLineParser.SplitArguments(currentInput); - return await LaunchHelper.LaunchAppAsync( - args.FirstOrDefault("").Trim('"'), string.Join(' ', args.Skip(1)), workingDir - ); + + var windowsLaunchAppService = Ioc.Default.GetRequiredService(); + return await windowsLaunchAppService.LaunchApplicationAsync( + args.FirstOrDefault("").Trim('"'), + string.Join(' ', args.Skip(1)), + workingDir); } public async Task SetAddressBarSuggestionsAsync(AutoSuggestBox sender, IShellPage shellpage)