4

enter image description here

So the idea is to make an encryption software which will work only on .txt files and apply some encryption functions on it and generate a new file. To avoid the hassle of user having to drag-and-drop the file, I have decided to make an option similar to my anti-virus here.

I want to learn how to make these for various OS, irrespective of the architecture :)

  1. What are these menus called? I mean the proper name so next time I can refer to them in a more articulate way
  2. How to make these?

My initial understanding:

What I think it will do is: pass the file as an argument to the main() method and then leave the rest of the processing to me :)

An SO User
  • 24,612
  • 35
  • 133
  • 221
  • 1
    they are called shell extensions. maybe this is helpful to you: http://msdn.microsoft.com/en-us/library/windows/desktop/cc144067%28v=vs.85%29.aspx – Marco Forberg May 27 '13 at 10:22
  • @MarcoForberg are these `testing friendly` ? I mean will it screw up my PC if I try to make some adventurous changes ? – An SO User May 27 '13 at 10:25
  • can't tell since i didn't play around with them myself – Marco Forberg May 27 '13 at 10:25
  • If you are planning to support Windows 7 or newer, it's considerably simpler to create context menus. But I suppose XP must be on the list as well, right ? – gkalpak May 27 '13 at 10:28
  • @ExpertSystem Well, yeah but for starter's sake I will be on Win 7 :) – An SO User May 27 '13 at 10:29
  • @ExpertSystem http://stackoverflow.com/questions/370114/how-can-i-add-a-context-menu-to-the-windows-explorer-for-a-java-application?rq=1 was not so much of a help you know :) I would love to see an example for a JAVA program :) – An SO User May 27 '13 at 10:30
  • Do you need a simpel entry, or do you want a submenu with more entries ? – gkalpak May 27 '13 at 10:32
  • @ExpertSystem I will start with simple entry :) I will move to complex stuff later :) – An SO User May 27 '13 at 10:32
  • @ExpertSystem which is easier ? Single entry or the one with multiple sub-options ? – An SO User May 27 '13 at 10:58
  • 1
    Single entry is considerably simpler :) – gkalpak May 27 '13 at 11:05
  • @ExpertSystem can you answer this question by showing how that can be done ??? please :) – An SO User May 27 '13 at 11:06
  • I plan to, as soon as possible :) – gkalpak May 27 '13 at 11:10
  • @ExpertSystem sure .. eagerly waiting. Please remember , it is a `executable jar file .jar` that will work only with `.txt`,`.doc` and `.docx` (I decided to add 2 new) files :) :D THANKS IN ADVANCE – An SO User May 27 '13 at 11:13
  • @ExpertSystem I found this: http://www.howtogeek.com/107965/how-to-add-any-application-shortcut-to-windows-explorers-context-menu/ Its says that **1. It needs a .exe file** **2. It passes the file name to the program** Can you explain them in context of a `jar` file please ? – An SO User May 27 '13 at 19:23
  • I did not "abandon" you. I am preparing an answer. It seems like it is an even more complicated matter than I originally thought, but an answer will eventually come ;) – gkalpak May 27 '13 at 19:57
  • Some tips to keep you busy until then: 1. For a java app, `C:\Path\To\Program.exe "%1"` needs to be replaced with `"C:\Path\To\jre\bin\javaw.exe" -jar "C:\Path\To\JavaApp.jar" "%1"`. 2. You can read (the relevant part of) **[this answer](http://stackoverflow.com/questions/14737244/change-file-icon-in-windows-using-java/16394823#16394823)** regarding adding context-menu with submenu-entries for a java app (under windows 7 or newer). – gkalpak May 27 '13 at 20:04
  • @ExpertSystem dont worry, this time it will be less frustrating because I am going to accept your answer :D – An SO User May 27 '13 at 20:20
  • @ExpertSystem WHat is more important is getting the file names to the jar file. :) I can handle the rest :) – An SO User May 27 '13 at 20:32
  • I hope you do, because that's all you're gone get: a file-path as String argument :) Getting ii is the tricky part though... – gkalpak May 27 '13 at 20:36
  • @ExpertSystem will this work? http://www.howtogeek.com/howto/windows-vista/add-open-with-notepad-to-the-context-menu-for-all-files/ – An SO User May 27 '13 at 20:39
  • Probably. Adding context menus for all files (Class "*") seems to work easier (at least under Windows 7/8), than addig for e.g. .txt files only. In the link I posed above I have a working example which does just that (adds a cotext menu to all files). – gkalpak May 27 '13 at 20:42
  • @ExpertSystem The task can be made easier by using `launch4j` to make an `exe` out of `jar`. That way I wont have to worry about where Java is installed on client machine :) – An SO User May 28 '13 at 05:31
  • True :) I use Launch4J - it's very nice if you target Windows platforms. – gkalpak May 28 '13 at 06:26
  • @ExpertSystem For now, lets just stick to Windows. Other OS later :) – An SO User May 28 '13 at 06:27
  • So, finally: there you go ! I'll try to add some demo-code (hopefully before WE). If anything isn't clear, please, feel free to ask clarifications :D – gkalpak May 28 '13 at 08:57

1 Answers1

5

Probably not exactly the answer you were hoping for, but it seems that this is a rather complicated matter. Anyway, I'll share what I know about it and it will hopefully prove enough to (at least) get you started.

Unfortunately, the easiest way to create a context menu using Java is editing the Registry. I'll try to summarize the milestones of the overall requirements and steps to achieve our objective.

<UPDATE>
See at the end of the post for links to sample code and a working demo.
</UPDATE>

What needs to be done

  1. We need to edit the Registry adding an additional entry (for our java-app) in the context menus of the file-types we are interested in (e.g. .txt, .doc, .docx).

    1. We need to determine which entries in Registry to edit, because our targeted file-extensions might be associated with another 'Class' (I couldn't test it on XP, but on Windows 7/8 this seems to be the case). E.g. instead of editing ...\Classes\.txt we might need to edit ...\Classes\txtfile, which the .txt Class is associated with.

    2. We need to specify the path to the installed jre (unless we can be sure that the directory containing javaw.exe is in the PATH variable).

    3. We need to insert the proper keys, values and data under the proper Registry nodes.

  2. We need a java-app packaged as a .JAR file, with a main method expecting a String array containing one value that corresponds to the path of the file we need to process (well, that's the easy part - just stating the obvious).

All this is easier said than done (or is it the other way around ?), so let's see what it takes to get each one done.

First of all, there are some assumption we'll be making for the rest of this post (for the sake of simplicity/clarity/brevity and the like).

Assumptions

  1. We assume that the target file-category is .TXT files - the same steps could be applied for every file-category.
  2. If we want the changes (i.e. context-menus) to affect all users, we need to edit Registry keys under HKCR\ (e.g. HKCR\txtfile), which requires administrative priviledges. For the sake of simplicity, we assume that only current user's settings need to be changed, thus we will have to edit keys under HKCU\Software\Classes (e.g. HKCU\Software\Classes\txtfile), which does not require administrative priviledges. If one chooses to go for system-wide changes, the following modifications are necessary:
    1. In all REG ADD/DELETE commands, replace HKCU\Software\Classes\... with HKCR\... (do not replace it in REG QUERY commands).
    2. Have your application run with administrative priviledges. Two options here (that I am aware of):
      • Elevate your running instance's priviledges (can be more complicated with latest windows versions, due to UAC). There are plenty of resources online and here in SO; this one seems promising (but I haven't tested it myself).
      • Ask the user to explicitely run your app "As administrator" (using right-click -> "Run as administrator" etc).
  3. We assume that only simple context-menu entries are needed (as opposed to a context-submenu with more entries). After some (rather shallow) research, I have come to believe that adding a submenu in older versions of Windows (XP, Vista), would require more complex stuff (ContextMenuHandlers etc). Adding a submenu in Windows 7 or newer is considerably more easy. I described the process in the relevant part of this answer (working demo provided ;)).

That said, let's move on to...

Getting things done

  1. You can achieve editing the Registry by issuing commands of the form REG Operation [Parameter List], with operations involving ADD, DELETE, QUERY (more on that later). In order to execute the necessary commands, we can use a ProcessBuilder instance. E.g.

    String[] cmd = {"REG", "QUERY", "HKCR\\.txt", "/ve"};
    new ProcessBuilder(cmd).start();
    // Executes: REG QUERY HKCR\.txt /ve

    Of course, we will probably want to capture and further process the command's return value, which can be done via the respective Process' getInputStream() method. But that falls into scope "implementation details"...

    1. "Normally" we would have to edit the .txt file-class, unless it is associated with another file-class. We can test this, using the following command:

      // This checks the "Default" value of key 'HKCR\.txt'
      REG QUERY HKCR\.txt /ve

      // Possible output:
      (Default) REG_SZ txtfile

      All we need, is parse the above output and find out, if the default value is empty or contains a class name. In this example we can see the associated class is txtfile, so we need to edit node HKCU\Software\Classes\txtfile.

    2. Specifying the jre path (more precisely the path to javaw.exe) falls outside the scope of this answer, but there should be plenty of ways to do it (I don't know of one I would 100% trust though).
      I'll just list a few off the top of my head:

      • Looking for environment-variable 'JAVA_HOME' (System.getenv("java.home");).
      • Looking in the Registry for a value like HKLM\Software\JavaSoft\Java Runtime Environment\<CurrentVersion>\JavaHome.
      • Looking in predifined locations (e.g. C:\Program Files[ (x86)]\Java\).
      • Prompting the user to point it out in a JFileChooser (not very good for the non-experienced user).
      • Using a program like Launch4J to wrap your .JAR into a .EXE (which eliminates the need of determining the path to 'javaw.exe' yourself).

Latest versions of Java (1.7+ ?) put a copy of javaw.exe (and other utilities) on the path, so it might be worth checking that as well.

3. So, after collecting all necessary data, comes the main part: Inserting the required values into Registry. After compliting this step, our HKCU\Software\Classes\txtfile-node should look like this:

HKCU
|_____Software
      |_____Classes
            |_____txtfile
                  |_____Shell
                        |_____MyCoolContextMenu: [Default] -> [Display name for my menu-entry]
                              |_____Command: [Default] -> [<MY_COMMAND>]*

*: in this context, a '%1' denotes the file that was right-clicked.

Based on how you addressed step (1.2), the command could look like this:
"C:\Path\To\javaw.exe" -jar "C:\Path\To\YourApp.jar" "%1"
Note that javaw.exe is usually in ...\jre\bin\ (but not always only there - recently I've been finding it in C:\Windows\System32\ as well).

Still being in step (1.3), the commands we need to execute, in order to achieve the above structure, look as follows:

REG ADD HKCU\Software\Classes\txtfile\Shell\MyCoolContextMenu /ve /t REG_SZ /d "Click for pure coolness" /f
REG ADD HKCU\Software\Classes\txtfile\Shell\MyCoolContextMenu\Command /ve /t REG_SZ /d "\"C:\Path\To\javaw.exe\" -jar \"C:\Path\To\Demo.jar\" \"%%1\" /f"

        // Short explanation:
        REG ADD  <Path\To\Key>  /ve  /t REG_SZ  /d "<MY_COMMAND>"  /f
        \_____/  \___________/  \_/  \_______/  \_______________/  \_/
 __________|_______   |          |       |___           |           |
|Edit the Registry |  |   _______|________   |   _______|_______    |
|adding a key/value|  |  |Create a no-name|  |  |Set the data   |   |
--------------------  |  |(default) value |  |  |for this value.|   |
                      |  ------------------  |  |Here: a command|   |
       _______________|______________        |  |to be executed.|   |
      |Edit this key                 |       |  -----------------   |
      |(creates the key plus         |   ____|_________    _________|_____
      | any missing parent key-nodes)|  |of type REG_SZ|  |No confirmation|
      --------------------------------  |(string)      |  -----------------
                                        ----------------

Implementation Considerations:

  • It is probably a good idea to check if our target class (e.g. txtfile), does already have a context-menu entry named "MyCoolContextMenu", or else we might be overriding an existing entry (which will not make our user very happy).
  • Since the data part of the value (the part that comes after /d and before /f) needs to be enclosed in "", keep in mind that you can escape " inside the string as \". You also need to escape the %1 so that it is stored in the Registry value as-is (escape it like: %%1).
  • It is a good idea to provide your user with an option to "un-register" your context-menu entry. The un-registering can be achieved by means of the command:
    REG DELETE HKCU\Software\Classes\txtfile\Shell\MyCoolContextMenu /f
  • Omitting the /f at the end of the commands may prompt the "user" (in this case your app) for confirmation, in which case you need to use the Process' getOutputStream() method to output "Yes" in order for the operation to be completed. We can avoid that unnecessary interaction, using the force flag (/f).

Almost, there !

Finding ourselves at step (2), we should by now have the following:

  1. A context-menu entry registered for our files in category txtfile (note that it is not restricted to .TXT files, but applies to all files pertained by the system as "txtfiles").
  2. Upon clicking that entry, our java-app should be run and its main() method passed a String array containing the path to the right-clicked .TXT file.

From there, our app can take over and do its magic :)

That's (almost) all, folks !

Sorry, for the long post. I hope it turns out to be of use to someone.
I'll try to add some demo-code soon (no promises though ;)).

UPDATE

The demo is ready !

Community
  • 1
  • 1
gkalpak
  • 47,844
  • 8
  • 105
  • 118
  • you can make it easy by using `launch4j` to make an exe right ? no need to worry about the location of `Java` and stuff because launch4j takes care of it ? – An SO User May 28 '13 at 09:47
  • I guess you didn't read it very carefully :P Section `Getting thinks done` `1.2`: "Using a program like Launch4J to wrap your .JAR into a .EXE (which eliminates the need of determining the path to 'javaw.exe' yourself)." – gkalpak May 28 '13 at 09:50
  • @Little Child: Answer updated with links to short demo. Take a look and let me know if you need any help (it's not very well documented [yet]). – gkalpak May 30 '13 at 13:29
  • sir, I havea lot of things to talk which I can not on SO. WIll you please send me an email ? It is related to this registry things :) and I insist – An SO User Jun 02 '13 at 13:19
  • Basically, I am interested in working with you on the registry demo that you made. :) Will help me in my academics – An SO User Jun 02 '13 at 13:42
  • @Little Child: My e-mail is on my profile. Feel free to send me anything :) – gkalpak Jun 02 '13 at 15:19
  • I can not see it. Neither in the info nor in the detailed description on the right. – An SO User Jun 02 '13 at 15:21
  • Emailed. Check your inbox. – An SO User Jun 02 '13 at 16:04
  • @ExpertSystem hi thanks for this great answer, it has helped me alot but unfortunately I could use it to add context menu for .txt files but not audio files such as .mp3 files which is what I need, Ive posted this question http://stackoverflow.com/questions/21684149/why-can-i-add-context-menus-for-some-extensions-but-no-others-using-reg-and-java any ideas – Paul Taylor Feb 10 '14 at 17:39