Skip to content

Added support for opening applications from the pathbox #7859

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 5 commits into from
Jan 23, 2022
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
37 changes: 16 additions & 21 deletions src/Files.Launcher/MessageHandlers/ApplicationLaunchHandler.cs
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@
using System.Threading.Tasks;
using Vanara.PInvoke;
using Vanara.Windows.Shell;
using Windows.Foundation.Collections;

namespace FilesFullTrust.MessageHandlers
{
Expand All @@ -21,7 +22,7 @@ public void Initialize(PipeStream connection)
{
}

public Task ParseArgumentsAsync(PipeStream connection, Dictionary<string, object> message, string arguments)
public async Task ParseArgumentsAsync(PipeStream connection, Dictionary<string, object> message, string arguments)
{
switch (arguments)
{
Expand All @@ -38,12 +39,11 @@ public Task ParseArgumentsAsync(PipeStream connection, Dictionary<string, object
if (message.ContainsKey("Application"))
{
var application = (string)message["Application"];
HandleApplicationLaunch(application, message);
}
else if (message.ContainsKey("ApplicationList"))
{
var applicationList = JsonConvert.DeserializeObject<IEnumerable<string>>((string)message["ApplicationList"]);
HandleApplicationsLaunch(applicationList, message);
var success = await HandleApplicationLaunch(application, message);
await Win32API.SendMessageAsync(connection, new ValueSet()
{
{ "Success", success }
}, message.Get("RequestID", (string)null));
}
break;

Expand All @@ -53,22 +53,13 @@ public Task ParseArgumentsAsync(PipeStream connection, Dictionary<string, object
var afPath = Path.Combine(Path.GetTempPath(), "CompatibilityTroubleshooterAnswerFile.xml");
File.WriteAllText(afPath, string.Format("<?xml version=\"1.0\" encoding=\"UTF-8\"?><Answers Version=\"1.0\"><Interaction ID=\"IT_LaunchMethod\"><Value>CompatTab</Value></Interaction><Interaction ID=\"IT_BrowseForFile\"><Value>{0}</Value></Interaction></Answers>", filePath));
message["Parameters"] = $"/id PCWDiagnostic /af \"{afPath}\"";
HandleApplicationLaunch("msdt.exe", message);
await HandleApplicationLaunch("msdt.exe", message);
}
break;
}
return Task.CompletedTask;
}

private void HandleApplicationsLaunch(IEnumerable<string> applications, Dictionary<string, object> message)
{
foreach (var application in applications)
{
HandleApplicationLaunch(application, message);
}
}

private async void HandleApplicationLaunch(string application, Dictionary<string, object> message)
private async Task<bool> HandleApplicationLaunch(string application, Dictionary<string, object> message)
{
var arguments = message.Get("Parameters", "");
var workingDirectory = message.Get("WorkingDirectory", "");
Expand All @@ -77,8 +68,7 @@ private async void HandleApplicationLaunch(string application, Dictionary<string
if (new[] { ".vhd", ".vhdx" }.Contains(Path.GetExtension(application).ToLowerInvariant()))
{
// Use powershell to mount vhds as this requires admin rights
Win32API.MountVhdDisk(application);
return;
return Win32API.MountVhdDisk(application);
}

try
Expand Down Expand Up @@ -123,6 +113,7 @@ private async void HandleApplicationLaunch(string application, Dictionary<string
process.StartInfo.WorkingDirectory = workingDirectory;
process.Start();
Win32API.BringToForeground(currentWindows);
return true;
}
catch (Win32Exception)
{
Expand All @@ -136,12 +127,13 @@ private async void HandleApplicationLaunch(string application, Dictionary<string
{
process.Start();
Win32API.BringToForeground(currentWindows);
return true;
}
catch (Win32Exception)
{
try
{
await Win32API.StartSTATask(() =>
return await Win32API.StartSTATask(() =>
{
var split = application.Split('|').Where(x => !string.IsNullOrWhiteSpace(x)).Select(x => GetMtpPath(x));
if (split.Count() == 1)
Expand Down Expand Up @@ -172,16 +164,19 @@ await Win32API.StartSTATask(() =>
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;
}
}

Expand Down
4 changes: 2 additions & 2 deletions src/Files.Launcher/Win32API.cs
Original file line number Diff line number Diff line change
Expand Up @@ -354,10 +354,10 @@ public static void SetVolumeLabel(string driveName, string newLabel)
RunPowershellCommand($"-command \"$Signature = '[DllImport(\\\"kernel32.dll\\\", SetLastError = false)]public static extern bool SetVolumeLabel(string lpRootPathName, string lpVolumeName);'; $SetVolumeLabel = Add-Type -MemberDefinition $Signature -Name \"Win32SetVolumeLabel\" -Namespace Win32Functions -PassThru; $SetVolumeLabel::SetVolumeLabel('{driveName}', '{newLabel}')\"", true);
}

public static void MountVhdDisk(string vhdPath)
public static bool MountVhdDisk(string vhdPath)
{
// mounting requires elevation
RunPowershellCommand($"-command \"Mount-DiskImage -ImagePath '{vhdPath}'\"", true);
return RunPowershellCommand($"-command \"Mount-DiskImage -ImagePath '{vhdPath}'\"", true);
}

public static Bitmap GetBitmapFromHBitmap(HBITMAP hBitmap)
Expand Down
3 changes: 1 addition & 2 deletions src/Files/Helpers/Win32Helpers.cs
Original file line number Diff line number Diff line change
Expand Up @@ -32,8 +32,7 @@ public static async Task<bool> InvokeWin32ComponentsAsync(IEnumerable<string> ap
{
{ "Arguments", "LaunchApp" },
{ "WorkingDirectory", string.IsNullOrEmpty(workingDirectory) ? associatedInstance?.FilesystemViewModel?.WorkingDirectory : workingDirectory },
{ "Application", applicationPaths.FirstOrDefault() },
{ "ApplicationList", JsonConvert.SerializeObject(applicationPaths) },
{ "Application", applicationPaths.FirstOrDefault() }
};

if (runAsAdmin)
Expand Down
35 changes: 35 additions & 0 deletions src/Files/ViewModels/NavToolbarViewModel.cs
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@
using System;
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.Diagnostics;
using System.IO;
using System.Linq;
using System.Threading.Tasks;
Expand Down Expand Up @@ -955,6 +956,11 @@ public async Task CheckPathInput(string currentInput, string currentSelectedPath
}
}

if (await LaunchApplicationFromPath(currentInput, workingDir))
{
return;
}

try
{
if (!await Launcher.LaunchUriAsync(new Uri(currentInput)))
Expand All @@ -976,6 +982,35 @@ await DialogDisplayHelper.ShowDialogAsync("InvalidItemDialogTitle".GetLocalized(
}
}

private static async Task<bool> LaunchApplicationFromPath(string currentInput, string workingDir)
{
var trimmedInput= currentInput.Trim();
var fileName = trimmedInput;
var arguments = "";
if (trimmedInput.Contains(' '))
{
var positionOfBlank = trimmedInput.IndexOf(' ');
fileName = trimmedInput.Substring(0, positionOfBlank);
arguments = currentInput.Substring(currentInput.IndexOf(' '));
}

var connection = await AppServiceConnectionHelper.Instance;
if (connection != null)
{
var value = new ValueSet()
{
{ "Arguments", "LaunchApp" },
{ "WorkingDirectory", workingDir },
{ "Application", fileName },
{ "Parameters", arguments }
};
var (status, response) = await connection.SendMessageForResponseAsync(value);
return status == Windows.ApplicationModel.AppService.AppServiceResponseStatus.Success && response.Get("Success", false);
}

return false;
}

public async void SetAddressBarSuggestions(AutoSuggestBox sender, IShellPage shellpage, int maxSuggestions = 7)
{
if (!string.IsNullOrWhiteSpace(sender.Text) && shellpage.FilesystemViewModel != null)
Expand Down