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

Proposal: simple context menu entries in app manifest #1082

Open
sylveon opened this issue Jul 18, 2021 · 16 comments
Open

Proposal: simple context menu entries in app manifest #1082

sylveon opened this issue Jul 18, 2021 · 16 comments

Comments

@sylveon
Copy link

sylveon commented Jul 18, 2021

Proposal: simple context menu entries in app manifest

Summary

Support declaring a context menu entry with a specific icon, display name and executable in app manifest instead of requiring to provide an IExplorerCommand implementation.

Rationale

  • Currently, to have an entry in the new Windows 11 context menu (instead of the legacy Windows 10 menu, which shows up under "Show more options"), one needs to implement IExplorerCommand
  • This is needlessly complicated if the context menu entry is just a simple entry which launches the app executable with a certain command line argument (which I'd wager is most context menu entries out there, people who need more already have a shell extension).
  • It also requires implementing it in C++, as C# and other managed languages are heavily discouraged by Microsoft for in-process shell extensions (and IExplorerCommand indeed only supports in-process activation).
  • This will cause the DLL to be loaded in any process with a save as/browse dialog, causing potential runtime version conflicts. So, even if one disregards the MS recommendations and goes ahead with a managed implementation, this will cause problems in the real world.
  • This means that, in practice, many projects might skip this altogether because of implementation complexity.

Scope

Capability Priority
This proposal will allow developers to register context menu entries that launch an app when clicked Must
This proposal will allow developers to pass command line arguments including the selected file, if any, to the Win32 app Must
This proposal will allow developers to activate UWP apps in response to a context menu entry click Should
This proposal will allow end users to show/hide undesired context menu entries from the Settings app Could
This proposal will allow end users to register their own context menu entries Won't

Important Notes

The app manifest entry could look something like this:

<desktop4:Extension Category="windows.fileExplorerContextMenus">
    <desktop4:FileExplorerContextMenus>
        <!-- add a context menu entry on a folder, with no icon -->
        <desktop5:ItemType Type="Directory">
            <desktop7:SimpleVerb Id="OpenFolderWin32" Executable="myappwin32.exe" EntryPoint="Windows.FullTrustApplication" Parameters='--folder "%1"'>
                <uap:DisplayName>Open folder in App</uap:DisplayName>
            </desktop7:SimpleVerb>
        </desktop5:ItemType>

        <!-- add a context menu entry on the desktop wallpaper, activating a UWP app -->
        <desktop5:ItemType Type="Directory\Background">
            <desktop7:SimpleVerb Id="OpenBackgroundUWP" Executable="myappuwp.exe" EntryPoint="Contoso.App">
                <uap:DisplayName>Do something</uap:DisplayName>
            </desktop7:SimpleVerb>
        </desktop5:ItemType>

        <!-- add a context menu entry on the desktop wallpaper, opening a Win32 app without command line parameters -->
        <desktop5:ItemType Type="Directory\Background">
            <desktop7:SimpleVerb Id="OpenBackgroundWin32" Executable="myappwin32.exe" EntryPoint="Windows.FullTrustApplication">
                <uap:DisplayName>Do something but with Win32</uap:DisplayName>
            </desktop7:SimpleVerb>
        </desktop5:ItemType>

        <!-- add a context menu entry on the desktop wallpaper, opening a Win32 app with command line parameters -->
        <desktop5:ItemType Type="Directory\Background">
            <desktop7:SimpleVerb Id="OpenBackgroundWin32" Executable="myappwin32.exe" EntryPoint="Windows.FullTrustApplication" Parameters='--background'>
                <uap:DisplayName>Do something but with Win32</uap:DisplayName>
            </desktop7:SimpleVerb>
        </desktop5:ItemType>

        <!-- add a context menu entry on all files, using a package resource as display name -->
        <desktop5:ItemType Type="*">
            <desktop7:SimpleVerb Id="OpenFileWin32" Executable="myappwin32.exe" EntryPoint="Windows.FullTrustApplication" Parameters='--file "%1"'>
                <uap:DisplayName>ms-resource:OpenFileVerbDescription</uap:DisplayName>
            </desktop7:SimpleVerb>
        </desktop5:ItemType>

        <!-- add a context menu entry on text files, with an icon -->
        <desktop5:ItemType Type=".txt">
            <desktop7:SimpleVerb Id="OpenTxtWin32" Executable="myappwin32.exe" EntryPoint="Windows.FullTrustApplication" Parameters='--text-file "%1"'>
                <uap:DisplayName>Edit file in App</uap:DisplayName>
                <uap:Logo>Assets\EditFile.ico</uap:Logo>
            </Verb>
        </desktop5:ItemType>

        <!-- add a context menu entry on log files, with a PNG file as icon -->
        <desktop5:ItemType Type=".log">
            <desktop7:SimpleVerb Id="OpenLogWin32" Executable="myappwin32.exe" EntryPoint="Windows.FullTrustApplication" Parameters='--log-file "%1"'>
                <uap:DisplayName>View log file in App</uap:DisplayName>
                <uap:Logo>Assets\ViewLog.png</uap:Logo>
            </desktop7:SimpleVerb>
        </desktop5:ItemType>

        <!-- add a context menu entry on C++ files, activating a UWP app -->
        <desktop5:ItemType Type=".cpp">
            <desktop7:SimpleVerb Id="OpenCodeUWP" Executable="myappuwp.exe" EntryPoint="Contoso.App">
                <uap:DisplayName>Edit C++ in App</uap:DisplayName>
            </desktop7:SimpleVerb>
        </desktop5:ItemType>
    </desktop4:FileExplorerContextMenus>
</desktop4:Extension>

In command line arguments, %1 is a placeholder for the file/folder name, if any.

One could then use activation APIs to determine if the app was launched in response to a context menu entry (or for Win32 apps, they can read command line arguments). It wouldn't be unlike the File activation API:

 namespace Windows.ApplicationModel.Activation
 {
     public enum ActivationKind
     {
+        ContextMenu = 1023
     }
 
+    public sealed class ContextMenuTargetActivatedEventArgs : IActivatedEventArgsWithUser
+    {
+        public string ItemType { get; }
+        public string Verb { get; }
+        public IStorageItem? File { get; } // null if something like Directory\Background was activated
+    }
 }
 
 namespace Windows.UI.Xaml
 {
     public class Application
     {
+        protected virtual void OnContextMenuTargetActivated(ContextMenuTargetActivatedEventArgs args);
     }
 }

Command line arguments are supported to simplify the migration of an existing Win32 app to MSIX, as the app might already have command line arguments for context menu entries and adding code checking for the activation kind is not possible or too costly. It's not needed for UWP/Windows App SDK apps, which use activation from the start.

Open Questions

None that I can think of.

@asklar
Copy link
Member

asklar commented Jul 18, 2021

FYI @ChrisGuzak. Agree that the current approach is unnecessarily complicated.

@mrlacey
Copy link

mrlacey commented Jul 18, 2021

There are some bigger questions to ask in relation to this.

  • Assuming there was a reason for the change in the Windows 11 context menu, it would be good to understand why it was made before trying to work around it.
  • When there are primary and secondary lists, it's human nature to want the thing you've made to be on the primary list. What would stop every developer from trying to put their entry on the main list? Of course, to them, it's the most important thing but it would easily become a commons and result in everybody losing out in the long run.
  • Are there any metrics available on how many apps actually extend the context menu? (how many people would benefit if this was made easier?)
  • Is there any other feedback from other developers/apps that would like to do this but haven't/can't because it is so (too?) complicated?
  • Rather than changing the way the functionality is implemented, would it be suitable to instead make it quicker and easier to implement? I'm thinking of having a template (possibly through template studio--this is the kind of thing it was created for) that would produce the basic structure of the project and files needed and then only require the developer to provide the (for example) path/filename, icon, and details of the parameters to pass.

@sylveon
Copy link
Author

sylveon commented Jul 18, 2021

Assuming there was a reason for the change in the Windows 11 context menu, it would be good to understand why it was made before trying to work around it.

The change was made mostly to bring organization to the menu (for example when an app has more than 1 entry, it's automatically put in a submenu, and all app entries are in the same region of the menu). We are not working around it, there is a documented way to add your own entries in there, it's just needlessly complicated.

When there are primary and secondary lists, it's human nature to want the thing you've made to be on the primary list. What would stop every developer from trying to put their entry on the main list? Of course, to them, it's the most important thing but it would easily become a commons and result in everybody losing out in the long run.

If there is more than 1 entry from a single app, Windows 11 automatically puts them in a submenu. And I don't see this as a valid point, seeing as there's already a way to add entries there.

Allowing users to hide entries is also a could in the scope table.

Are there any metrics available on how many apps actually extend the context menu? (how many people would benefit if this was made easier?)

To name a few:

  • Visual Studio (when right clicking a folder)
  • Visual Studio Code (when right clicking a folder)
  • Windows Terminal (when right clicking a folder or the desktop background)
    • They currently implement IExplorerCommand for this because they are packaged but could completely remove that if this feature was implemented.
  • ShareX (when right clicking a file)
    • The packaged versions of ShareX are completely missing this because it used not to be possible and they do not want to add C++ code for IExplorerCommand.
  • Intel/AMD/Nvidia graphics (when right clicking the desktop background)
  • x64dbg (when right clicking a .exe/.dll file)
  • Jetbrains dotPeek (when right clicking a .exe/.dll file)

These are the ones on my system, there are most likely many more out there.

Is there any other feedback from other developers/apps that would like to do this but haven't/can't because it is so (too?) complicated?

See ShareX above.

Rather than changing the way the functionality is implemented, would it be suitable to instead make it quicker and easier to implement? I'm thinking of having a template (possibly through template studio--this is the kind of thing it was created for) that would produce the basic structure of the project and files needed and then only require the developer to provide the (for example) path/filename, icon, and details of the parameters to pass.

This still adds deployment and build complexity. You need to ship a different binary for every architecture, even though your app would otherwise be architecture neutral. You also need the C++ build tools installed, and to have your build system capable of building C++ (e.g., packaged Electron apps can't as easily add C++ stuff to their build). It's a maintenance burden for people who do not know C++ well, as well.

Template Studio is VS-only (and an optional extension install), so a template added there would not reach a significant part of the audience.

@mrlacey
Copy link

mrlacey commented Jul 18, 2021

The change was made mostly to bring organization to the menu (for example when an app has more than 1 entry, it's automatically put in a submenu, and all app entries are in the same region of the menu).

What's the source for this explanation?
This is also different--as I understand it--from the issue defined in the OP, which was about the "show more options" menu added in Windows 11.

If there is more than 1 entry from a single app, Windows 11 automatically puts them in a submenu. And I don't see this as a valid point, seeing as there's already a way to add entries there.

My point was about this being a request to make it easier to add entries to the context menu. If such a change was made and it was then promoted on the grounds of "we've made it easier to add windows explorer context menu entries." Many developers would see this as an excuse to add such an entry for their app too, regardless of whether it makes sense or adds value to the people using the app. (I make this claim based on years of watching developers add pointless and irrelevant features to their apps because they're new and/or easy to do. "What's the harm they feel?" And then users end up with a context menu full of irrelevant entries and the Windows team has to come up with another way to reorganize and prioritize all the entries.

My request for metrics was meant for the Windows team.
Just listing 7 apps (3 from Microsoft) is unlikely to be enough to raise the priority of this.
Knowing how many people/apps/developers are affected by the issue will help understand how this request might be prioritized.

Template Studio is VS-only (and an optional extension install), so a template added there would not reach a significant part of the audience.

Is being VS-only a big blocker for this given that it's a Windows-only feature?

My reason for suggesting this as something that could be added to Template Studio is that this feels like a very niche request and so is unlikely to be something that would quickly get up the priority queue for a change in the build system. Adding templates would be a couple of days' effort at most and would then at least make the process simpler. It's also something that could be community-contributed rather than waiting for a space in the WindowsAppsSDK backlog. I suspect (and hope) there are a lot of other things that are a higher priority and would be done first.

Still, this is all good extra context for those who make the decisions.

@sylveon
Copy link
Author

sylveon commented Jul 19, 2021

What's the source for this explanation?
This is also different--as I understand it--from the issue defined in the OP, which was about the "show more options" menu added in Windows 11.

Right here and here. All of the points listed are organizational changes. The OP is about being able to show up in the new Windows 11 menu, not the old one under "show more options", without needing to implement IExplorerCommand in a shell extension, which is needlessly complicated.

And then users end up with a context menu full of irrelevant entries and the Windows team has to come up with another way to reorganize and prioritize all the entries.

That's why "This proposal will allow end users to show/hide undesired context menu entries from the Settings app" is a could. Collapsing apps with multiple verbs under a dropdown also helps it from being invasive. The menu is also more organized by default because app verbs are all grouped under the same subsection of the menu

My request for metrics was meant for the Windows team.
Just listing 7 apps (3 from Microsoft) is unlikely to be enough to raise the priority of this.
Knowing how many people/apps/developers are affected by the issue will help understand how this request might be prioritized.

Then it's not possible for me to answer that in an appropriate manner, since I am not a MS employee with access to Windows telemetry that could provide this data. I can only speak of personal experience.

Is being VS-only a big blocker for this given that it's a Windows-only feature?

Yes, as there are many Windows apps which are being developed without Visual Studio. For example Electron, React Native, Rust, MSYS2/mingw, etc. In all of those except one, integrating C++ code is a pain.

@JaiganeshKumaran
Copy link
Contributor

Please provide an option to completely disable all third-party context menu items and just have the default ones.

@sylveon
Copy link
Author

sylveon commented Jul 20, 2021

Allowing users to hide entries is also a could in the scope table.

@xandfis
Copy link

xandfis commented Jul 22, 2021

Thank you for the thorough suggestion! One thing I want to quickly clarify is that IExplorerCommand will run Out of Proc when invoked in the way described in the blog post and sample.

@sylveon
Copy link
Author

sylveon commented Jul 22, 2021

Thanks for the info! I tried to find information of whether IExplorerCommand is in-proc or out-of-proc, and I've only found documentation mentioning in-proc. I imagine out-of-proc support is something new for Windows 11?

This does remove concerns with regards to managed implementations (which is awesome), but I think there is still value to simplifying it, as this is currently additional complexity to adopting packaged support for some apps (where the unpackaged version just directly registers context menu verbs in the registry instead of using a shell extension). Or just additional complexity in general compared to writing a few entries in XML.

@xandfis
Copy link

xandfis commented Jul 22, 2021

Out-of-proc support extends back into Windows 10 for some time but the documentation needs work.

I agree we should consider making this easier. We're discussing options internally.

@riverar
Copy link
Contributor

riverar commented Jul 22, 2021

We're chatting in another thread already but just want to mirror here.

There doesn't appear to be a good story for folks that were previously just doing:

Windows Registry Editor Version 5.00

[HKEY_CLASSES_ROOT\exefile\shell\symchk]

[HKEY_CLASSES_ROOT\exefile\shell\symchk\command]
@=hex(2):63,00,6d,00,64,00,20,00,2f,00,63,00,20,00,22,00,20,00,22,00,43,00,3a,\
  00,5c,00,50,00,72,00,6f,00,67,00,72,00,61,00,6d,00,20,00,46,00,69,00,6c,00,\
  65,00,73,00,20,00,28,00,78,00,38,00,36,00,29,00,5c,00,57,00,69,00,6e,00,64,\
  00,6f,00,77,00,73,00,20,00,4b,00,69,00,74,00,73,00,5c,00,31,00,30,00,5c,00,\
  44,00,65,00,62,00,75,00,67,00,67,00,65,00,72,00,73,00,5c,00,78,00,36,00,34,\
  00,5c,00,73,00,79,00,6d,00,63,00,68,00,6b,00,2e,00,65,00,78,00,65,00,22,00,\
  20,00,2f,00,69,00,66,00,20,00,22,00,25,00,31,00,22,00,20,00,2f,00,73,00,75,\
  00,20,00,22,00,25,00,5f,00,4e,00,54,00,5f,00,53,00,59,00,4d,00,42,00,4f,00,\
  4c,00,5f,00,50,00,41,00,54,00,48,00,25,00,22,00,20,00,22,00,00,00

(This just calls cmd /c " "C:\Program Files (x86)\Windows Kits\10\Debuggers\x64\symchk.exe" /if "%1" /su "%_NT_SYMBOL_PATH%" ")

Right now, it appears I have to write an app, take a dependency on a runtime/process creation API, package it (or sparse package it), sign it, deploy it, all to simply shell out to an executable.

@xandfis
Copy link

xandfis commented Jul 22, 2021

This is why we have "Show more options" - it's important to recognize that it's still possible to add a Shell extension in this way, but it's no longer easy to put it at the top level of the context menu.

@sylveon
Copy link
Author

sylveon commented Jul 22, 2021

I'm going to imagine at some point in the future there'll be an app that registers its own shell extension under * and allows you to add custom verbs to it. IExplorerCommand supports submenus (EnumSubCommands) so it's possible to have multiple entries in there.

@asklar
Copy link
Member

asklar commented Jul 22, 2021

yeah I was planning on doing something like that next week :) LMK if you want to collab :)

stefankueng added a commit to stefankueng/BowPad that referenced this issue Aug 19, 2021
@yao-msft yao-msft removed their assignment Jan 25, 2022
@ghost1372
Copy link
Contributor

Any news?

@JasonWues
Copy link

Any progress?

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests