Skip to content
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

Respect default app for zip files #6457

Merged
merged 4 commits into from Oct 12, 2021
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.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
7 changes: 7 additions & 0 deletions Files.Launcher/MessageHandlers/Win32MessageHandler.cs
Expand Up @@ -165,6 +165,13 @@ await Win32API.SendMessageAsync(connection, new ValueSet()
}
}
break;

case "GetFileAssociation":
{
var filePath = (string)message["filepath"];
await Win32API.SendMessageAsync(connection, new ValueSet() { { "FileAssociation", await Win32API.GetFileAssociationAsync(filePath, true) } }, message.Get("RequestID", (string)null));
}
break;
}
}

Expand Down
35 changes: 25 additions & 10 deletions Files.Launcher/Win32API.cs
Expand Up @@ -83,24 +83,39 @@ public static Task<T> StartSTATask<T>(Func<Task<T>> func)
return tcs.Task;
}

public static async Task<string> GetFileAssociationAsync(string filename)
public static async Task<string> GetFileAssociationAsync(string filename, bool checkDesktopFirst = false)
{
// Find UWP apps
var uwpApps = await Launcher.FindFileHandlersAsync(Path.GetExtension(filename));
if (uwpApps.Any())
async Task<string> GetUwpAssoc()
{
return uwpApps.First().PackageFamilyName;
}
var uwpApps = await Launcher.FindFileHandlersAsync(Path.GetExtension(filename));
if (uwpApps.Any())
{
return uwpApps.First().PackageFamilyName;
}
return null;
};

// Find desktop apps
var lpResult = new StringBuilder(2048);
var hResult = Shell32.FindExecutable(filename, null, lpResult);
if (hResult.ToInt64() > 32)
string GetDesktopAssoc()
{
return lpResult.ToString();
var lpResult = new StringBuilder(2048);
var hResult = Shell32.FindExecutable(filename, null, lpResult);
if (hResult.ToInt64() > 32)
{
return lpResult.ToString();
}
return null;
}

return null;
if (checkDesktopFirst)
{
return GetDesktopAssoc() ?? await GetUwpAssoc();
}
else
{
return await GetUwpAssoc() ?? GetDesktopAssoc();
}
}

public static string ExtractStringFromDLL(string file, int number)
Expand Down
@@ -1,5 +1,6 @@
using ByteSizeLib;
using Files.Extensions;
using Files.Filesystem.StorageItems;
using Files.Helpers;
using Files.Helpers.FileListCache;
using Files.Services;
Expand Down Expand Up @@ -305,7 +306,7 @@ CancellationToken cancellationToken
opacity = Constants.UI.DimItemOpacity;
}

if (itemFileExtension == ".zip")
if (itemFileExtension == ".zip" && await ZipStorageFolder.CheckDefaultZipApp(itemPath))
{
return new ZipItem(null, dateReturnFormat)
{
Expand Down
38 changes: 31 additions & 7 deletions Files/Filesystem/StorageItems/ZipStorageFolder.cs
Expand Up @@ -9,6 +9,7 @@
using System.Runtime.InteropServices.WindowsRuntime;
using System.Text;
using System.Threading.Tasks;
using Windows.ApplicationModel;
using Windows.Foundation;
using Windows.Storage;
using Windows.Storage.FileProperties;
Expand All @@ -20,6 +21,22 @@ public sealed class ZipStorageFolder : BaseStorageFolder
{
public Encoding ZipEncoding { get; set; } = null;

private static bool? IsDefaultZipApp;
public static async Task<bool> CheckDefaultZipApp(string filePath)
{
Func<Task<bool>> queryFileAssoc = async () =>
{
var assoc = await NativeWinApiHelper.GetFileAssociationAsync(filePath);
if (assoc != null)
{
IsDefaultZipApp = assoc == Package.Current.Id.FamilyName
|| assoc.Equals(System.IO.Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.Windows), "explorer.exe"), StringComparison.OrdinalIgnoreCase);
}
return true;
};
return IsDefaultZipApp ?? await queryFileAssoc();
}

static ZipStorageFolder()
{
// Register all supported codepages (default is UTF-X only)
Expand Down Expand Up @@ -488,16 +505,23 @@ public override IAsyncOperation<IStorageItem> TryGetItemAsync(string name)

public static IAsyncOperation<BaseStorageFolder> FromPathAsync(string path)
{
var marker = path.IndexOf(".zip");
if (marker != -1)
return AsyncInfo.Run<BaseStorageFolder>(async (cancellationToken) =>
{
var containerPath = path.Substring(0, marker + ".zip".Length);
if (CheckAccess(containerPath))
var marker = path.IndexOf(".zip");
if (marker != -1)
{
return Task.FromResult<BaseStorageFolder>(new ZipStorageFolder(path, containerPath)).AsAsyncOperation();
var containerPath = path.Substring(0, marker + ".zip".Length);
if (!await CheckDefaultZipApp(path))
{
return null;
}
if (CheckAccess(containerPath))
{
return new ZipStorageFolder(path, containerPath);
}
}
}
return Task.FromResult<BaseStorageFolder>(null).AsAsyncOperation();
return null;
});
}

public static bool IsZipPath(string path)
Expand Down
20 changes: 20 additions & 0 deletions Files/Helpers/NativeWinApiHelper.cs
@@ -1,6 +1,8 @@
using System;
using System.Runtime.InteropServices;
using System.Text;
using System.Threading.Tasks;
using Windows.Foundation.Collections;

namespace Files.Helpers
{
Expand Down Expand Up @@ -258,5 +260,23 @@ internal interface ICoreWindowInterop
}

public static IntPtr CoreWindowHandle => ((ICoreWindowInterop)(object)Windows.UI.Core.CoreWindow.GetForCurrentThread()).WindowHandle;

public static async Task<string> GetFileAssociationAsync(string filePath)
{
var connection = await AppServiceConnectionHelper.Instance;
if (connection != null)
{
var (status, response) = await connection.SendMessageForResponseAsync(new ValueSet()
{
{ "Arguments", "GetFileAssociation" },
{ "filepath", filePath }
});
if (status == Windows.ApplicationModel.AppService.AppServiceResponseStatus.Success && response.ContainsKey("FileAssociation"))
{
return (string)response["FileAssociation"];
}
}
return null;
}
}
}