Explorer context menu shell extensions

Get help with using AutoHotkey (v1.1 and older) and its commands and hotkeys
User avatar
jeeswg
Posts: 6902
Joined: 19 Dec 2016, 01:58
Location: UK

Explorer context menu shell extensions

22 May 2017, 20:43

I have wanted AutoHotkey to be able to make use of Explorer context menu shell extensions since I first started using it.

I've collected everything within my knowledge, that could be helpful towards this goal, in case anyone has the knowledge to take this further.

I intend to try and create a few simple applications in C++, and to learn more about C++ generally, and shell extensions, but it could be many months or longer, before I achieve that.

==================================================

Open single/multiple files as individual files:
- Pass the filename as a command-line parameter.

[add 'open with Notepad' to all files][if a shortcut, the target is opened]
HKEY_CLASSES_ROOT\*\shell\Open with Notepad\command
(Default) REG_SZ notepad.exe "%1"

[add 'open with WordPad' to all files][if a shortcut, the target is opened]
HKEY_CLASSES_ROOT\*\shell\Open with WordPad\command
(Default) REG_SZ "C:\Program Files\Windows NT\Accessories\wordpad.exe" "%1"

==================================================

Open single/multiple files as a group:
- Perhaps pass the Explorer window hWnd as a command-line parameter.
- Then retrieve the paths from the window (a folder window or Desktop).
- Otherwise get the list of files more directly by whatever means Explorer provides.
- We could look at 7-Zip to get some hints.

If I do '7-Zip, Add to archive...', and check Task Manager:

E.g. select some files in an Explorer window, for the folder 'New Folder':
"C:\Program Files\7-Zip\7zG.exe" a -i#7zMap20728:678:7zEvent24246 -ad -slp- -- "New Folder"
"C:\Program Files\7-Zip\7zG.exe" a -i#7zMap5190:572:7zEvent25545 -ad -slp- -- "New Folder"
"C:\Program Files\7-Zip\7zG.exe" a -i#7zMap730:678:7zEvent27379 -ad -slp- -- "New Folder"

E.g. select some files on Desktop:
"C:\Program Files\7-Zip\7zG.exe" a -i#7zMap2723:350:7zEvent8418 -ad -slp- -- "Desktop"

In the registry we see:
HKEY_CLASSES_ROOT\*\shellex\ContextMenuHandlers\7-Zip
(Default) REG_SZ {23170F69-40C1-278A-1000-000100020000}

==================================================

To get the paths from an Explorer Window:
for oWin in ComObjCreate("Shell.Application").Windows

To get the paths from Desktop:
get full paths of selected files on Desktop and Common File Dialogs - AutoHotkey Community
https://autohotkey.com/boards/viewtopic.php?f=5&t=31135

==================================================

Some comments on creating a GUID (globally unique identifier):

ObjRegisterActive - AutoHotkey Community
https://autohotkey.com/boards/viewtopic.php?t=6148
; Register our object so that other scripts can get to it. The second
; parameter is a GUID which I generated. You should generate one unique
; to your script. You can use [CreateGUID](http://goo.gl/obfmDc).
ObjRegisterActive(ActiveObject, "{6B39CAA1-A320-4CB0-8DB4-352AA81E460E}")
==================================================

Some links on creating a shell extension:

Writing a shell extension in plain C++ - CodeProject
https://www.codeproject.com/Articles/58 ... -Cplusplus

C++ Windows Shell context menu handler (CppShellExtContextMenuHandler) sample in C++, Windows Shell Script for Visual Studio 2010
https://code.msdn.microsoft.com/windows ... l-410a709a

==================================================

So the question is if there is some template we can use or modify, in order to choose a string/some strings for the Explorer context menu item(s) text (possibly with a popup menu/popup menus), and then determine some command-line parameters for AutoHotkey.exe or a compiled script to receive, or some code for handling whatever communication means Explorer provides.

Thanks for reading.
homepage | tutorials | wish list | fun threads | donate
WARNING: copy your posts/messages before hitting Submit as you may lose them due to CAPTCHA
User avatar
jeeswg
Posts: 6902
Joined: 19 Dec 2016, 01:58
Location: UK

Re: Explorer context menu shell extensions

07 Jun 2017, 16:55

SEND TO

Using the 'Send to' menu is pretty much a solution, although I would like to be able to specify a menu item that is higher up, and/or that has a submenu. You put a lnk file in the 'Send to' folder, that specifies the AHK exe and an AHK script path, and that script, receives all the selected files via the command line, even for the longest possible filenames (259 chars) you can get around 120 files (see calculations at the bottom of this post).

What is the command line length limit? – The Old New Thing
https://blogs.msdn.microsoft.com/oldnew ... 0/?p=41553
The maximum command line length for the CreateProcess function is 32767 characters.
Based on my tests, that may be 32767, including the null character, so in effect a 32766 limit.

Queries:
- Is the 'Send to' technique available via ShellEx, as a class, like the drop handler below?
- Even if someone doesn't want to provide any code, could someone suggest in simple terms, how communication is done between a shell extension and a utility, is it done via command line, or are there other possibilities like running a program and communication via messages/COM. Do the classes have to have hardcoded paths inside them, how is that dealt with? If there is some C/C++ code, for a utility that does this that would be useful. Cheers.
- I don't think that realistically I'm going to make more progress with this for a long time, so I'd be grateful if this interests anyone.

Some code:

Code: Select all

q:: ;add a script to the SendTo folder (tested on Windows 7)
username := A_UserName
vDir = C:\Users\%username%\AppData\Roaming\Microsoft\Windows\SendTo
if !FileExist(vDir)
	vDir = C:\Documents and Settings\%username%\SendTo

if !FileExist(vDir)
{
	MsgBox, % "error: folder not found:`r`n" vDir
	return
}

vPath = %A_Desktop%\z send to.ahk
vOutput = ;continuation section
(Join`r`n % `
Loop, %0%
	vOutput .= %A_Index% "`r`n"
Clipboard := vOutput
MsgBox, % vOutput
)
if !FileExist(vPath)
	FileAppend, % vOutput "`r`n", % "*" vPath, UTF-8

vPathLnk = %vDir%\Send To AHK.lnk
if !FileExist(vPathLnk)
	FileCreateShortcut, % A_AhkPath, % vPathLnk,, % """" vPath """"
return

;create files for testing 'Send to'
vDir = %A_Desktop%\z nums
FileCreateDir, % vDir
Loop, 1000
	FileAppend,, % "*" vDir "\" A_Index ".txt"
return
==================================================

OPEN MULTIPLE INSTANCES

It is possible to open a separate AHK instance for each file, get all but one of the scripts to close themselves, and leave the last script to get the selected files from the Explorer window. E.g. check for AutoHotkey windows with the same title and class, and close all accept the one with the lowest hWnd/PID.

However, this is equivalent to opening multiple text files with Notepad at the same time, and in Windows 7 for example, you can only open 15 files at the same time.

==================================================

AHK FILE DROP HANDLER

AutoHotkey's drop handler, for when you drag-and-drop files onto an ahk file, is the same as that for batch files (and other filetypes).

list of every command/function/variable from across all versions - AutoHotkey Community
https://autohotkey.com/boards/viewtopic ... 65#p151665

[HKEY_CLASSES_ROOT\AutoHotkeyScript\ShellEx\DropHandler]
@="{86C86720-42A0-1069-A2E8-08002B30309D}"

[HKEY_CLASSES_ROOT\batfile\ShellEx\DropHandler]
@="{86C86720-42A0-1069-A2E8-08002B30309D}"

==================================================

HOW MANY PATHS CAN YOU FIT IN A COMMAND LINE

E.g. if path length 259: 125 files (or: exe, script, 123 files)
E.g. if path length 42: 728 files (or: exe, script, 726 files)
E.g. 'C:\Program Files\AutoHotkey\AutoHotkey.exe' has 42 characters.

Code: Select all

q:: ;how many file paths of length n can fit in a command line (take into account double quotes and spaces)
vLen := 0
vCount := 0
;259 maximum number of chars in a path (so 260, MAX_PATH if include a null character)
vLen2 := 259 ;125 files ;e.g. C:\Users\me\Desktop\abcdefghijklmnopqrstuvwxyabcdefghijklmnopqrstuvwxyabcdefghijklmnopqrstuvwxyabcdefghijklmnopqrstuvwxyabcdefghijklmnopqrstuvwxyabcdefghijklmnopqrstuvwxyabcdefghijklmnopqrstuvwxyabcdefghijklmnopqrstuvwxyabcdefghijklmnopqrstuvwxyabcdefghij.txt
vLen2 := 42 ;728 files, e.g. C:\Program Files\AutoHotkey\AutoHotkey.exe
Loop
{
	if (A_Index = 1)
		vLen += 1+vLen2+1  ;i.e. quote path quote, e.g. "C:\MyFile.txt"
	else
		vLen += 1+1+vLen2+1 ;i.e. space quote path quote
	if (vLen > 32766)
		break
	vCount++
}
MsgBox, % vCount ;125 files (exe, script, 123 files)

vPath := ""
Loop, 259
	vPath .= "a"
vCmdLn := ""
Loop, 125
	vCmdLn .= " """ vPath """"
vCmdLn := LTrim(vCmdLn)
Clipboard := vCmdLn
return
Simplified maths:

Code: Select all

MsgBox, % (32766+1)/(259+3) ;125.064885
MsgBox, % (32766+1)/(42+3) ;728.155556
==================================================

LINKS

7-Zip: conditional extract here/extract to subfolder based on count of items in root of archive - AutoHotkey Community
https://autohotkey.com/boards/viewtopic.php?f=6&t=39577
homepage | tutorials | wish list | fun threads | donate
WARNING: copy your posts/messages before hitting Submit as you may lose them due to CAPTCHA

Return to “Ask for Help (v1)”

Who is online

Users browsing this forum: mikeyww and 286 guests