Giter Site home page Giter Site logo

end2endzone / shellanything Goto Github PK

View Code? Open in Web Editor NEW
155.0 7.0 24.0 3.82 MB

ShellAnything is a C++ open-source software which allow one to easily customize and add new options to *Windows Explorer* context menu. Define specific actions when a user right-click on a file or a directory.

License: MIT License

CMake 4.18% Batchfile 3.28% C++ 85.62% PowerShell 0.05% VBScript 0.06% C 6.50% Python 0.31%
windows explorer contextmenu context-menu menu-customization menu-personalize personalize shell-extension utf-8 file-explorer

shellanything's Introduction

ShellAnything logo

ShellAnything

License: MIT Github Releases Downloads (all time) Downloads (latest)

ShellAnything is a C++ open-source software which allow one to easily customize and add new options to Windows Explorer context menu. Define specific actions when a user right-click on a file or a directory.

Status

Build:

Service Build Tests
AppVeyor, Visual Studio 2019 Build status Tests status
Github Actions, Windows Server 2019 Build on Windows Tests on Windows

Statistics:

Statistics

Screenshots

Files context menu:

ShellAnything screenshot

Directories context menu:

ShellAnything screenshot

Purpose

Adding new options to Windows Explorer context menu can be done in many ways. One can create new context menus by manually editing the registry but this option is limited in support (static text, no submenus). If you are technical person, you can also follow this guide on StackOverflow.

With Shell Extension, you can dynamically create a context menu item (or submenu) that is more relevant to the selected file(s). Shell extension are dynamic by nature because they are runtime DLL inside Windows Explorer. They can show or hide options based on the selected file's name, size, content, etc. Shell extensions also have the ability to handle multiple selected files simultaneously.

On the downside, writing shell extensions is complicated, tedious and difficult to debug.

This is where ShellAnything is useful. It provides a simple xml-based way of adding new dynamic options to Windows Explorer context menu.

ShellAnything is implemented in C++ which, for writing Shell Extension, is a safe programming language compared to C#. See Writing Shell Extensions with C# for details.

Writing Shell Extensions with C#.

Writing Shell Extensions with C# is possible but highly discouraged and probably not a good idea.

Many articles already discussed the subject and they all comes to the same conslusion: Don't do it.

For instance, the following articles are good references:

Features

The main features of ShellAnything are:

  • Easily add custom menus and submenus.
  • Dynamic content based on xml files. Change xml configuration files to see the menu options update automatically.
  • Support for custom icons for each menu.
  • Support activation and visibility filters based on selected files.
  • Define actions executed when a menu option is selected:
    • Launch an application.
    • Open a document.
    • Prompt for a value.
    • Change the clipboard.
    • and many more.
  • Powerful property-based system for rich dynamic content and filters.
  • Extendable with a custom plugin system.
  • Easily integrate any third party application with custom menus.
  • Supports windows keyboard mnemonics.

For more details about ShellAnything features, please refer to the User Manual.

Usage

For instructions on how to use ShellAnything, please refer to the User Manual.

The User Manual also features Use Case with the following examples:

Build

Please refer to file INSTALL.md for details on how installing/building the application.

Platform

ShellAnything has been tested with the following platform:

  • Windows 8.1 (32 and 64 bit)
  • Windows 10 (32 and 64 bit)

NOTE: Version 0.6.1 is the last version of ShellAnything that supports 32-bit Windows.

NOTE: Version 0.7 is the last version of ShellAnything that supports Windows 7.

Versioning

This project use Semantic Versioning 2.0.0 for versioning. For the versions available, see the tags on this repository.

Authors

See also the list of contributors who participated in this project.

License

This project is licensed under the MIT License - see the LICENSE file for details

shellanything's People

Contributors

cirn09 avatar end2endzone avatar gasdaumin avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar

shellanything's Issues

Prompt action does not expand default property value

The default value in a <prompt> action does not expand properties.
For example:

  <prompt name="new_path" title="Define administrator username" default="${env.USERNAME}" />

The prompt will be displayed with the literal value ${env.USERNAME} instead of expanding to Antoine.

Support custom or default properties defined at load time.

It would be interesting to be able to define default properties (defined by the user) when a file is loaded.

The proposed method is as follows:

<?xml version="1.0" encoding="utf-8"?>
<root>
  <default>
    <property name="myapp.installation.date" value="2019-01-24" />
  </default>
  <shell>
  </shell>
</root>

The feature could also be usefull for implementing mutually exclusive menus.
For instance, by defining a default value of property display_menu_a to true, one can implement the following toggling menus:

  <menu name="A">
    <visibility properties="display_menu_a" />
    <actions>
      <!--Do something meaningful-->

      <!--Change the property to only show B.-->
      <property name="display_menu_a" value="" />
      <property name="display_menu_b" value="true" />
    </actions>
  </menu>
  <menu name="B">
    <visibility properties="display_menu_b" />
    <actions>
      <!--Do something meaningful-->

      <!--Change the property to only show A.-->
      <property name="display_menu_a" value="true" />
      <property name="display_menu_b" value="" />
    </actions>
  </menu>

Modify InputBox to support Unicode strings

  • bool DoModal(const std::wstring & caption, const std::wstring & prompt);
  • Add utf_strings.h and utf_strings.cpp to the project.
  • Modify DoModal(ansi strings) to convert from ansi to Unicode and call the DoModal(unicode strings) version.
  • std::wstring m_Text;
  • Create ‘TestInputBox.cpp’ with all tests disabled by default.
    • Ansi version
    • Unicode version
  • Should we create DoModalUnicode(…), DoModalAnsi(…) and DoModalUtf8(…) ?

Fail to extract icon from *.sdf file extension.

For some file extension, the function win32_registry::getFileTypeIcon(file_extension) fails to extract the icon from the registry. On the of file extension that fails is the sdf file extension.

Multi-select filename handling and complex visibility judgment

  1. I found that when select multiple files, the selection.filename will be filenames string separated by \n, which makes it impossible to add quotes to one of filenames with spaces.

  2. WinRar's "Open with WinRar" can judge visibility according to the actual file type instead of file extension, I hope ShellAnything can also support such complex judgment logic.

I think a good way to achieve the above two functions is to add plug-in or script engine support.

Change the log directory if run from the unit tests

  • This feature should impact the GetLogDirectory() function.
  • This is required since running the unit tests may generate many ERROR and WARNING logs (expected). Since they are expected it may be preferable to output the logs to a directory that is not the official one.
  • One option is to generate the logs in unit_tests_exe_dir/logs or unit_tests_exe_dir/shellext-logs
  • Another option would be C:\Users\%USERNAME%\ShellAnything\tests

Unregister the shell extension for DragDropHandlers.

When a file is dragged & dropped, the shell extension is displayed which does not really help and provide useful information. The implementation should be re-think to allow special actions.

Would also be required to implement new attribute for <validity> and visibility.

Executing a program with arguments is missing characters

The issue can be reproduced with the following example:

  <exec path="C:\Windows\system32\cmd.exe" arguments="/k echo You clicked on file '${selection.path}'" />

For example, if the user right-click on file named issue36.psiΨpsi.ico, the following message will be displayed:

You clicked on file 'C:\Users\Mark\ShellAnything\issue36.psi?psi.ico'

(note the ? character instead of Ψ character)

Change the default filename format for log files

Change the default format for log files. In other words, remove %COMPUTERNAME% and %USERNAME% from the filenames.

NATIVE FORMAT: shellext-d.dll.SES-MBL-WPC0866.beauchamp.a3.log.INFO.20180120-124422.8732.log
DESIRED FORMAT: shellext-d.dll.INFO.20180120-124422.8732.log

Remove Context argument from Action::execute()

None of the Action implementation requires an instance of Context to execute. The current implementation of the shell extension is registering all the context's properties before the call to execute().

The Action interface should be modified to remote the deprecated argument

Do not delete log files that are less than 5 days old.

  • The code should list the logs filenames, extract the created date, and if they are older than 10 days, they should be deleted.
  • This would allow proper investigation following a reboot. (When rebooting, the old log files are deleted as soon as you open a file explorer or click-click a file)

Support utf-8 strings in configuration files

Parsing from an xml configuration file encoded in utf-8 does not seems to be working as expected.

For example, the following menu is not displayed properly:

    <menu name="_Ψ_" description="test for psi letter" />

The action does not support utf-8 strings. For example, the following prompt message is not displayed as expected:

    <menu name="test" description="test for copyright and omega characters">
      <actions>
        <prompt name="myarguments" title="z©z" default="Hugh _Ω_ Jass" />
      </actions>
    </menu>

Prompt with a Yes/No answer

The <prompt> action should be modified to support asking for a yes/no question.

Proposed solution:

<prompt name="myanswer" type="yesno" title="Do you want verbose output?" valueyes="/Verbose" valueno="" />

This should display a "Yes/No/Cancel" message box.
If the user select Cancel, the prompt action would fail.
If the user select Yes, the property myanswer should be set to value /Verbose
If the user select No, the property myanswer should be set to an empty string.

Typical usage of the YesNo prompt would be to use the property as an argument. For instance:

<exec path="${selection.path}" arguments="${myanswer}" />

Implement menu validation based on a string expression

The system should implement a way to define a a menu validation based on an expression that contains a property, an operator and a expected value.

For instance, ${myproperty}=="true" would validate a <visibility> or <visibility> node only if the value of property myproperty is set to the value true.

The attribute sugested for specifying an expression would be propertyexpression.
For instance:

<visibility propertyexpression="&quot;%{myproperty}&quot; == &quot;&quot;" />

This kind of validation would allow the application to support "exclusive menus". For instance, in a 2 menu scenario, the application would be able to only show one of the two menus at a time.
For instance, the following could be implemented:

  <menu name="A">
    <visibility propertyexpression="&quot;%{next_menu}&quot; == &quot;&quot; || &quot;%{next_menu}&quot; == &quot;A&quot;" />
    <actions>
      <!--Do something meaningful-->
      
      <!--Change the property to only show B.-->
      <property name="next_menu" value="B" />
    </actions>
  </menu>
  <menu name="B">
    <visibility propertyexpression="&quot;%{next_menu}&quot; == &quot;B&quot;" />
    <actions>
      <!--Do something meaningful-->

      <!--Change the property to only show C.-->
      <property name="next_menu" value="C" />
    </actions>
  </menu>
  <menu name="C">
    <visibility propertyexpression="&quot;%{next_menu}&quot; == &quot;C&quot;" />
    <actions>
      <!--Do something meaningful-->

      <!--Change the property to only show A.-->
      <property name="next_menu" value="A" />
    </actions>
  </menu>

Validator with 'exists' attribute

Implement a Validator “exists” attribute for and tags. This would allow creating menu item only if a specific file is found / software is installed.

Find application a new name

Logs are deleted after 10 days instead of 5 days

The logs files are deleted after 10 days instead of 5 days. Delete logs as soon as possible is better for security reason as they may contains sensitive information.

Note: this issue is related to issue #1.

Allow ordering of custom menu entries

Right now all ShellAnything menu entries are inserted near the middle of the context menu.
I'm interested in heavy configuration of the menu and I would like to be able to add options near the top(ex "Edit" or "Open with Notepad++") and bottom(ex Properties) as well.

From my research I believe this may not be a straight forward change.

Clarify functions that are RapidAssist improvements

Move some functions of Platform.h to rapidassist_extension.h (which is a ShellAnything local file) which refers each function implementation with an issue in RapidAssist repository.

This way we properly define that we already use the latest version of RapidAssist but we extend its functionalities based on future content.

ConfigManager::assignCommandIds() should skip invisible menus

The available command id range provided by IContextMenu::QueryContextMenu() is a limited resource and should not be wasted. The assignCommandIds() function should be given a Context to allow skipping the menus that will not be displayed.

This make sure (at least delay) that the application will not ran out of command id.

Note: be sure to verify the implementation of ConfigManager::findMenuByCommandId() as well.

Create a <message> action to show a simple popup message

This feature could be useful to show a confirmation message following another action.
For example:

  <message title="Created configuration file '${config_file_path}' without error." icon="information" />

Possible values for icon attribute should match "positive" icons of MessageBox() function:

  • information (default)
  • exclamation
  • none

The 'error' value and error icons shall not be supported since when an executed action returns an error, the following action (in this case a <message>) will not be executed.

The question icon shall not be supported since it is associated with a <prompt> action.

Silence warnings from glog library.

Each time we include #include <glog/logging.h>, we get the following warning message:

glog\install_dir\include\glog/logging.h(1167): warning C4355: 'this' : used in base member initializer list

Each glog include statements should be wrapped with a proper #pragma directive to silence the warning. ie:

 #pragma warning( push )
 #pragma warning( disable: ThatWarning )
 //code with ThatWarning here
 #pragma warning( pop )

Assign icon based on file extension

Implement support to add menu icon's based on a given file extension instead of a path to a file.

The following sample code would automatically pick the icon associated to html files:

<icon fileextension="html" />

Add support for loading *.ico files with <icon> tag

Proposed icon samples available on all systems:

  • c:\Program Files (x86)\Adobe\Acrobat Reader DC\Reader\WebResources\Resource0\static\images\favicon.ico
  • c:\Program Files (x86)\Adobe\Acrobat Reader DC\Reader\WebResources\Resource0\static\images\themes\dark\favicon.ico
  • c:\Program Files (x86)\Common Files\microsoft shared\Web Server Extensions\12\BIN\FPDBW.ICO
  • c:\Program Files (x86)\Microsoft Office\Office15\GRAPH.ICO
  • c:\Program Files (x86)\Microsoft Office\Office15\MYSL.ICO

Allow icon's fileextension attribute to be dynamic.

The current implementation of the attribute is to call shellanything::Menu::resolveFileExtensionIcons() which converts the file extension's icon to an actual file path and index. This conversion breaks the dynamic part of the xml.

See issue #26 for details.

Implement a new strategy for handling the visible menus

  • Remove context sensitive functions
    • isVisible(context)
    • isEnabled(context)
  • Replace by generic setter/getter like the following:
    • bool isVisible()
    • void setVisible(bool visible)
    • bool isEnable()
    • void setEnable(bool enable)
  • Implement ConfigManager::update(const Context & c) and Menu::update(const Context & c)
    • Browse to the list of menus
    • Update the visible & enable flags based on the given context
    • Move the logic from validation logic from CContextMenu::BuildMenuTree() to these functions.
    • This should facilitate the implementation of issue #4 and issue #5.

Validity / Visibility should have an `inverse` attribute

The Validity / Visibility xml element in Configuration Files should have an attribute to inverse the logic of the validity/visibility. For instance, inverse the fileextensions attribute.

A typical use case is the following:

  • A split file menu accept only a single file. When executed, it generates multiple files of which the first "part" has the file extension 001.
  • A join files menu accept all files that matches fileextensions="001"

Edit:
To prevent the split file menu to be displayed when user selects a *.001 file (we don't need to split a file twice), the menu should also not accept files that matches fileextensions="001".

In the end, the split file menu validity should be:

  1. accept only a single file.
  2. accept files which file extension is not 001.

The validity element should look like this:

<validity maxfiles="1" maxfolders="0" fileextensions="001" inverse="fileextensions" />

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.