Skip to content

Commit 841aefb

Browse files
authored
Fix: Fixed opening an executable pinned to start menu (#10771)
1 parent 696f361 commit 841aefb

File tree

3 files changed

+82
-74
lines changed

3 files changed

+82
-74
lines changed

src/Files.App/Helpers/ShellContextMenuHelper.cs

+6-2
Original file line numberDiff line numberDiff line change
@@ -37,8 +37,12 @@ Func<string, bool> FilterMenuItems(bool showOpenMenu)
3737
"eject", "rename", "explore", "openinfiles", "extract",
3838
"copyaspath", "undelete", "empty",
3939
Win32API.ExtractStringFromDLL("shell32.dll", 30312), // SendTo menu
40-
Win32API.ExtractStringFromDLL("shell32.dll", 34593), // Add to collection
41-
};
40+
Win32API.ExtractStringFromDLL("shell32.dll", 34593), // Add to collection
41+
Win32API.ExtractStringFromDLL("shell32.dll", 5384), // Pin to Start
42+
Win32API.ExtractStringFromDLL("shell32.dll", 5385), // Unpin from Start
43+
Win32API.ExtractStringFromDLL("shell32.dll", 5386), // Pin to taskbar
44+
Win32API.ExtractStringFromDLL("shell32.dll", 5387), // Unpin from taskbar
45+
};
4246

4347
bool filterMenuItemsImpl(string menuItem) => !string.IsNullOrEmpty(menuItem)
4448
&& (knownItems.Contains(menuItem) || (!showOpenMenu && menuItem.Equals("open", StringComparison.OrdinalIgnoreCase)));

src/Files.App/MainWindow.xaml.cs

+1-1
Original file line numberDiff line numberDiff line change
@@ -71,7 +71,7 @@ public async Task InitializeApplication(object activatedEventArgs)
7171
switch (activatedEventArgs)
7272
{
7373
case ILaunchActivatedEventArgs launchArgs:
74-
if (launchArgs.Arguments is not null && launchArgs.Arguments.Contains($"{Package.Current.Id.FamilyName}\\files.exe", StringComparison.OrdinalIgnoreCase))
74+
if (launchArgs.Arguments is not null && launchArgs.Arguments.Contains($"files.exe", StringComparison.OrdinalIgnoreCase))
7575
{
7676
// WINUI3 bug: when launching from commandline the argument is not ICommandLineActivatedEventArgs (#10370)
7777
var ppm = CommandLineParser.ParseUntrustedCommands(launchArgs.Arguments);

src/Files.App/Program.cs

+75-71
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@
77
using Microsoft.Windows.AppLifecycle;
88
using System;
99
using System.Diagnostics;
10+
using System.IO;
1011
using System.Linq;
1112
using System.Threading;
1213
using System.Threading.Tasks;
@@ -26,64 +27,10 @@ private static void Main()
2627
{
2728
WinRT.ComWrappersSupport.InitializeComWrappers();
2829

29-
var proc = System.Diagnostics.Process.GetCurrentProcess();
30+
var proc = Process.GetCurrentProcess();
3031
var alwaysOpenNewInstance = ApplicationData.Current.LocalSettings.Values.Get("AlwaysOpenANewInstance", false);
3132
var activatedArgs = AppInstance.GetCurrent().GetActivatedEventArgs();
3233

33-
if (!alwaysOpenNewInstance)
34-
{
35-
if (activatedArgs.Kind is ExtendedActivationKind.Launch)
36-
{
37-
var launchArgs = activatedArgs.Data as ILaunchActivatedEventArgs;
38-
39-
if (false)
40-
{
41-
// WINUI3: remove
42-
}
43-
else
44-
{
45-
if (false)
46-
{
47-
// WINUI3: remove
48-
}
49-
else
50-
{
51-
var activePid = ApplicationData.Current.LocalSettings.Values.Get("INSTANCE_ACTIVE", -1);
52-
var instance = AppInstance.FindOrRegisterForKey(activePid.ToString());
53-
if (!instance.IsCurrent && !string.IsNullOrWhiteSpace(launchArgs.Arguments))
54-
{
55-
RedirectActivationTo(instance, activatedArgs);
56-
return;
57-
}
58-
}
59-
}
60-
}
61-
else if (activatedArgs.Data is IProtocolActivatedEventArgs protocolArgs)
62-
{
63-
var parsedArgs = protocolArgs.Uri.Query.TrimStart('?').Split('=');
64-
if (parsedArgs.Length == 2 && parsedArgs[0] == "cmd") // Treat as command line launch
65-
{
66-
var activePid = ApplicationData.Current.LocalSettings.Values.Get("INSTANCE_ACTIVE", -1);
67-
var instance = AppInstance.FindOrRegisterForKey(activePid.ToString());
68-
if (!instance.IsCurrent)
69-
{
70-
RedirectActivationTo(instance, activatedArgs);
71-
return;
72-
}
73-
}
74-
}
75-
else if (activatedArgs.Data is IFileActivatedEventArgs)
76-
{
77-
var activePid = ApplicationData.Current.LocalSettings.Values.Get("INSTANCE_ACTIVE", -1);
78-
var instance = AppInstance.FindOrRegisterForKey(activePid.ToString());
79-
if (!instance.IsCurrent)
80-
{
81-
RedirectActivationTo(instance, activatedArgs);
82-
return;
83-
}
84-
}
85-
}
86-
8734
if (activatedArgs.Data is ICommandLineActivatedEventArgs cmdLineArgs)
8835
{
8936
var operation = cmdLineArgs.Operation;
@@ -123,6 +70,58 @@ private static void Main()
12370
}
12471
}
12572

73+
if (activatedArgs.Data is ILaunchActivatedEventArgs tileArgs)
74+
{
75+
if (tileArgs.Arguments is not null &&
76+
!tileArgs.Arguments.Contains($"files.exe", StringComparison.OrdinalIgnoreCase) &&
77+
new[] { ".exe", ".bat", ".cmd" }.Contains(Path.GetExtension(tileArgs.Arguments), StringComparer.OrdinalIgnoreCase))
78+
{
79+
if (File.Exists(tileArgs.Arguments))
80+
{
81+
OpenFileFromTile(tileArgs.Arguments);
82+
return;
83+
}
84+
}
85+
}
86+
87+
if (!alwaysOpenNewInstance)
88+
{
89+
if (activatedArgs.Data is ILaunchActivatedEventArgs launchArgs)
90+
{
91+
var activePid = ApplicationData.Current.LocalSettings.Values.Get("INSTANCE_ACTIVE", -1);
92+
var instance = AppInstance.FindOrRegisterForKey(activePid.ToString());
93+
if (!instance.IsCurrent && !string.IsNullOrWhiteSpace(launchArgs.Arguments))
94+
{
95+
RedirectActivationTo(instance, activatedArgs);
96+
return;
97+
}
98+
}
99+
else if (activatedArgs.Data is IProtocolActivatedEventArgs protocolArgs)
100+
{
101+
var parsedArgs = protocolArgs.Uri.Query.TrimStart('?').Split('=');
102+
if (parsedArgs.Length == 2 && parsedArgs[0] == "cmd") // Treat as command line launch
103+
{
104+
var activePid = ApplicationData.Current.LocalSettings.Values.Get("INSTANCE_ACTIVE", -1);
105+
var instance = AppInstance.FindOrRegisterForKey(activePid.ToString());
106+
if (!instance.IsCurrent)
107+
{
108+
RedirectActivationTo(instance, activatedArgs);
109+
return;
110+
}
111+
}
112+
}
113+
else if (activatedArgs.Data is IFileActivatedEventArgs)
114+
{
115+
var activePid = ApplicationData.Current.LocalSettings.Values.Get("INSTANCE_ACTIVE", -1);
116+
var instance = AppInstance.FindOrRegisterForKey(activePid.ToString());
117+
if (!instance.IsCurrent)
118+
{
119+
RedirectActivationTo(instance, activatedArgs);
120+
return;
121+
}
122+
}
123+
}
124+
126125
var currentInstance = AppInstance.FindOrRegisterForKey((-proc.Id).ToString());
127126
if (currentInstance.IsCurrent)
128127
{
@@ -148,34 +147,39 @@ private static void OnActivated(object? sender, AppActivationArguments args)
148147
}
149148
}
150149

151-
public static void OpenShellCommandInExplorer(string shellCommand, int pid)
152-
{
153-
Win32API.OpenFolderInExistingShellWindow(shellCommand);
154-
SafetyExtensions.IgnoreExceptions(() =>
155-
{
156-
using var process = Process.GetProcessById(pid);
157-
process?.Kill();
158-
});
159-
}
160-
161-
private static IntPtr redirectEventHandle = IntPtr.Zero;
150+
private const uint CWMO_DEFAULT = 0;
151+
private const uint INFINITE = 0xFFFFFFFF;
162152

163153
// Do the redirection on another thread, and use a non-blocking
164154
// wait method to wait for the redirection to complete.
165155
public static void RedirectActivationTo(
166156
AppInstance keyInstance, AppActivationArguments args)
167157
{
168-
redirectEventHandle = CreateEvent(IntPtr.Zero, true, false, null);
158+
IntPtr eventHandle = CreateEvent(IntPtr.Zero, true, false, null);
169159
Task.Run(() =>
170160
{
171161
keyInstance.RedirectActivationToAsync(args).AsTask().Wait();
172-
SetEvent(redirectEventHandle);
162+
SetEvent(eventHandle);
163+
});
164+
_ = CoWaitForMultipleObjects(
165+
CWMO_DEFAULT, INFINITE, 1,
166+
new IntPtr[] { eventHandle }, out uint handleIndex);
167+
}
168+
169+
public static void OpenShellCommandInExplorer(string shellCommand, int pid)
170+
=> Win32API.OpenFolderInExistingShellWindow(shellCommand);
171+
172+
public static void OpenFileFromTile(string filePath)
173+
{
174+
IntPtr eventHandle = CreateEvent(IntPtr.Zero, true, false, null);
175+
Task.Run(() =>
176+
{
177+
LaunchHelper.LaunchAppAsync(filePath, null, null).Wait();
178+
SetEvent(eventHandle);
173179
});
174-
uint CWMO_DEFAULT = 0;
175-
uint INFINITE = 0xFFFFFFFF;
176180
_ = CoWaitForMultipleObjects(
177181
CWMO_DEFAULT, INFINITE, 1,
178-
new IntPtr[] { redirectEventHandle }, out uint handleIndex);
182+
new IntPtr[] { eventHandle }, out uint handleIndex);
179183
}
180184
}
181185
}

0 commit comments

Comments
 (0)