Sign in to follow this  
Followers 0

_ShellFolder() - Create an entry in the shell contextmenu when selecting a folder, includes the program icon as well.

15 posts in this topic

Posted (edited)

I created this after I developed because I was interested in the entry displaying when a folder was right clicked on. The entry will pass the folder name to your program via a commandline argument, so you'll have to use $CmdLine/$CmdLineRaw to access the folder that was selected.

Any problems or suggestions then please post below. Thanks.

UDF:

#include-once

; #AutoIt3Wrapper_Au3Check_Parameters=-d -w 1 -w 2 -w 3 -w 4 -w 5 -w 6 -w 7
; #INDEX# =======================================================================================================================
; Title .........: _ShellFolder
; AutoIt Version : v3.2.12.1 or higher
; Language ......: English
; Description ...: Create an entry in the shell contextmenu when selecting a folder, includes the program icon as well.
; Note ..........:
; Author(s) .....: guinness
; Remarks .......: Special thanks to KaFu for EnumRegKeys2Array() which I used as inspiration for enumerating the Registry Keys.
; ===============================================================================================================================

; #INCLUDES# ====================================================================================================================
; None

; #GLOBAL VARIABLES# ============================================================================================================
; None

; #CURRENT# =====================================================================================================================
; _ShellFolder_Install: Creates an entry in the 'All Users/Current Users' registry for displaying a program entry in the shell contextmenu, but only displays when selecting a folder.
; _ShellFolder_Uninstall: Deletes an entry in the 'All Users/Current Users' registry for displaying a program entry in the shell contextmenu.
; ===============================================================================================================================

; #INTERNAL_USE_ONLY#============================================================================================================
; __ShellFolder_RegistryGet ......; Retrieve an array of registry entries for a specific key.
; ===============================================================================================================================

; #FUNCTION# ====================================================================================================================
; Name ..........: _ShellFolder_Install
; Description ...: Creates an entry in the 'All Users/Current Users' registry for displaying a program entry in the shell contextmenu, but only displays when selecting a file and folder.
; Syntax ........: _ShellFolder_Install($sText[, $sName = @ScriptName[, $sFilePath = @ScriptFullPath[, $sIconPath = @ScriptFullPath[,
;                  $iIcon = 0[, $fAllUsers = False[, $fExtended = False]]]]]])
; Parameters ....: $sText               - Text to be shown in the contextmenu.
;                  $sName               - [optional] Name of the program. Default is @ScriptName.
;                  $sFilePath           - [optional] Location of the program executable. Default is @ScriptFullPath.
;                  $sIconPath           - [optional] Location of the icon e.g. program executable or dll file. Default is @ScriptFullPath.
;                  $iIcon               - [optional] Index of icon to be used. Default is 0.
;                  $fAllUsers           - [optional] Add to Current Users (False) or All Users (True) Default is False.
;                  $fExtended           - [optional] Show in the Extended contextmenu using Shift + Right click. Default is False.
; Return values .: Success - Returns True
;                  Failure - Returns False and sets @error to non-zero.
; Author ........: guinness
; Example .......: Yes
; ===============================================================================================================================
Func _ShellFolder_Install($sText, $sName = @ScriptName, $sFilePath = @ScriptFullPath, $sIconPath = @ScriptFullPath, $iIcon = 0, $fAllUsers = False, $fExtended = False)
    Local $i64Bit = '', $sRegistryKey = ''

    If $iIcon = Default Then
        $iIcon = 0
    EndIf
    If $sFilePath = Default Then
        $sFilePath = @ScriptFullPath
    EndIf
    If $sIconPath = Default Then
        $sIconPath = @ScriptFullPath
    EndIf
    If $sName = Default Then
        $sName = @ScriptName
    EndIf
    If @OSArch = 'X64' Then
        $i64Bit = '64'
    EndIf
    If $fAllUsers Then
        $sRegistryKey = 'HKEY_LOCAL_MACHINE' & $i64Bit & 'SOFTWAREClassesFoldershell'
    Else
        $sRegistryKey = 'HKEY_CURRENT_USER' & $i64Bit & 'SOFTWAREClassesFoldershell'
    EndIf

    $sName = StringLower(StringRegExpReplace($sName, '.[^./]*$', ''))
    If StringStripWS($sName, 8) = '' Or FileExists($sFilePath) = 0 Then
        Return SetError(1, 0, False)
    EndIf

    _ShellFolder_Uninstall($sName, $fAllUsers)

    Local $iReturn = 0
    $iReturn += RegWrite($sRegistryKey & $sName, '', 'REG_SZ', $sText)
    $iReturn += RegWrite($sRegistryKey & $sName, 'Icon', 'REG_EXPAND_SZ', $sIconPath & ',' & $iIcon)
    $iReturn += RegWrite($sRegistryKey & $sName & 'command', '', 'REG_SZ', '"' & $sFilePath & '" "%1"')
    If $fExtended Then
        $iReturn += RegWrite($sRegistryKey & $sName, 'Extended', 'REG_SZ', '')
    EndIf
    Return $iReturn > 0
EndFunc   ;==>_ShellFolder_Install

; #FUNCTION# ====================================================================================================================
; Name ..........: _ShellFolder_Uninstall
; Description ...: Deletes an entry in the 'All Users/Current Users' registry for displaying a program entry in the shell contextmenu.
; Syntax ........: _ShellFolder_Uninstall([$sName = @ScriptName[, $fAllUsers = False]])
; Parameters ....: $sName               - [optional] Name of the Program. Default is @ScriptName.
;                  $fAllUsers           - [optional] Was it added to Current Users (False) or All Users (True) Default is False.
; Return values .: Success - Returns True
;                  Failure - Returns False and sets @error to non-zero.
; Author ........: guinness
; Example .......: Yes
; ===============================================================================================================================
Func _ShellFolder_Uninstall($sName = @ScriptName, $fAllUsers = False)
    Local $i64Bit = '', $sRegistryKey = ''

    If $sName = Default Then
        $sName = @ScriptName
    EndIf
    If @OSArch = 'X64' Then
        $i64Bit = '64'
    EndIf
    If $fAllUsers Then
        $sRegistryKey = 'HKEY_LOCAL_MACHINE' & $i64Bit & 'SOFTWAREClassesFoldershell'
    Else
        $sRegistryKey = 'HKEY_CURRENT_USER' & $i64Bit & 'SOFTWAREClassesFoldershell'
    EndIf

    $sName = StringLower(StringRegExpReplace($sName, '.[^./]*$', ''))
    If StringStripWS($sName, 8) = '' Then
        Return SetError(1, 0, 0)
    EndIf

    Local $aReturn = __ShellFolder_RegistryGet($sRegistryKey), $iReturn = 0, $sNameDeleted = ''
    If $aReturn[0][0] Then
        For $i = 1 To $aReturn[0][0]
            If $aReturn[$i][0] = $sName And $sNameDeleted <> $aReturn[$i][1] Then
                $sNameDeleted = $aReturn[$i][1]
                $iReturn += RegDelete($sNameDeleted)
            EndIf
        Next
    EndIf
    $aReturn = 0
    Return $iReturn > 0
EndFunc   ;==>_ShellFolder_Uninstall

; #INTERNAL_USE_ONLY#============================================================================================================
Func __ShellFolder_RegistryGet($sRegistryKey)
    Local $aArray[1][5] = [[0, 5]], $iCount_1 = 0, $iCount_2 = 0, $iDimension = 0, $iError = 0, $sRegistryKey_All = '', $sRegistryKey_Main = '', $sRegistryKey_Name = '', _
            $sRegistryKey_Value = ''

    While 1
        If $iError Then
            ExitLoop
        EndIf
        $sRegistryKey_Main = RegEnumKey($sRegistryKey, $iCount_1 + 1)
        If @error Then
            $sRegistryKey_All = $sRegistryKey
            $iError = 1
        Else
            $sRegistryKey_All = $sRegistryKey & $sRegistryKey_Main
        EndIf

        $iCount_2 = 0
        While 1
            $sRegistryKey_Name = RegEnumVal($sRegistryKey_All, $iCount_2 + 1)
            If @error Then
                ExitLoop
            EndIf

            If ($aArray[0][0] + 1) >= $iDimension Then
                $iDimension = Ceiling(($aArray[0][0] + 1) * 1.5)
                ReDim $aArray[$iDimension][$aArray[0][1]]
            EndIf

            $sRegistryKey_Value = RegRead($sRegistryKey_All, $sRegistryKey_Name)
            $aArray[$aArray[0][0] + 1][0] = $sRegistryKey_Main
            $aArray[$aArray[0][0] + 1][1] = $sRegistryKey_All
            $aArray[$aArray[0][0] + 1][2] = $sRegistryKey & $sRegistryKey_Main & '' & $sRegistryKey_Name
            $aArray[$aArray[0][0] + 1][3] = $sRegistryKey_Name
            $aArray[$aArray[0][0] + 1][4] = $sRegistryKey_Value
            $aArray[0][0] += 1
            $iCount_2 += 1
        WEnd
        $iCount_1 += 1
    WEnd
    ReDim $aArray[$aArray[0][0] + 1][$aArray[0][1]]
    Return $aArray
EndFunc   ;==>__ShellFolder_RegistryGet

Example 1:

#include "_ShellFolder.au3"

Example()

Func Example()
    _ShellFolder_Install('Start ShellFolder') ; Add the running EXE to the Shell ContextMenu. This will only display when selecting a drive and folder.
    Sleep(10000)
    _ShellFolder_Uninstall() ; Remove the running EXE from the Shell ContextMenu.
EndFunc   ;==>Example

All of the above has been included in a ZIP file. ShellFolder.zip

Edited by guinness
yahaosoft likes this

Share this post


Link to post
Share on other sites



Posted (edited)

For compatibility's sake, these keys work on Win2000-Win7:

HKEY_CURRENT_USER\SOFTWARE\Classes\Folder\shell

or

HKEY_LOCAL_MACHINE\SOFTWARE\Classes\Folder\shell

(the latter requires admin rights of course)

HKEY_CURRENT_USER keys override keys with the same name in HKEY_LOCAL_MACHINE

The only shortcoming is I don't know of a way to put an icon in the menu, but I don't mind. All you need to do is add these subkeys. For example, to add 'CommandPromptHere', this is a .reg file that would add this:

Windows Registry Editor Version 5.00

[HKEY_CURRENT_USER\SOFTWARE\Classes\Folder\shell]

[HKEY_CURRENT_USER\SOFTWARE\Classes\Folder\shell\CommandPromptHere]
@="Command Prompt Here"
"Icon"=hex(2):25,00,63,00,6f,00,6d,00,73,00,70,00,65,00,63,00,25,00,2c,00,30,\
  00,00,00

[HKEY_CURRENT_USER\SOFTWARE\Classes\Folder\shell\CommandPromptHere\command]
@=hex(2):25,00,63,00,6f,00,6d,00,73,00,70,00,65,00,63,00,25,00,20,00,2f,00,6b,\
  00,20,00,20,00,70,00,75,00,73,00,68,00,64,00,20,00,22,00,25,00,31,00,22,00,\
  20,00,26,00,20,00,74,00,69,00,74,00,6c,00,65,00,20,00,43,00,6f,00,6d,00,6d,\
  00,61,00,6e,00,64,00,20,00,50,00,72,00,6f,00,6d,00,70,00,74,00,00,00

Hmm, forgot about the hex conversion. The Icon and Command lines appear as:

"Icon"=%comspec%,0
%comspec% /k  pushd "%1" & title Command Prompt

The list of common context menu locations follows (HKCU can be used in place of HKLM):

HKLM\Software\Classes\Folder\shell\yourappname
HKLM\Software\Classes\Folder\shell\yourappname\command
 HKLM\Software\Classes\Directory\shell\yourappname
 HKLM\Software\Classes\Directory\shell\yourappname\command
 HKLM\Software\Classes\Drive\shell\yourappname
 HKLM\Software\Classes\Drive\shell\yourappname\command

Note: On Vista+, the command prompt here registry addition is unneeded and should just be seen as a placeholder for whatever program you like.

(Shift-Right-Click a folder on Vista+ to open a command prompt)

*edit: oops, I guess its pretty easy to add an Icon after all.

Edited by Ascend4nt

Share this post


Link to post
Share on other sites

Posted

Oh Cheers Ascend4nt! I will update tomorrow or Sunday. By the way perhaps I misunderstood but should I stray away from using HKEY_CLASSES_ROOT altogether?

The only shortcoming is I don't know of a way to put an icon in the menu, but I don't mind.

From what I've read this is only available in Windows 7.

Share this post


Link to post
Share on other sites

Posted

Hmm, I don't know.. the Microsoft docs on HKEY_CLASSES_ROOT says it will be written to HKEY_LOCAL_MACHINE\SOFTWARE\Classes, so I guess your program would need Admin rights? Reading from the key is a different story..

I haven't experimented with your code, but I've been told 'Folder' was the more reliable option, at least in the past? But how that's different from 'Directory' I don't know. That list was pulled off Stack Overflow here: "Windows Shell Context Menu option".

Share this post


Link to post
Share on other sites

Posted (edited)

Thats what I read on MSDN too. Well I'll have a play around with it tomorrow and see which is the more efficient option. But in all seriousness cheers for Helping out Ascend4nt :huh2:

Edit: Just saw your update about icons working! Good to know.

Edited by guinness

Share this post


Link to post
Share on other sites

Posted (edited)

Updated OP.

Changelog:

UPDATED: Registry Keys, so now it can add either to the Current User or All Users. (Thanks to Ascend4nt)

Edit: Function Header was Wrong! Now fixed. :huh2:

Edited by guinness

Share this post


Link to post
Share on other sites

Posted

Changelog:

UPDATED: x64 bit support and structure of code.

Share this post


Link to post
Share on other sites

Posted

I haven't experimented with your code, but I've been told 'Folder' was the more reliable option, at least in the past? But how that's different from 'Directory' I don't know.

Off the top of my head I can't remember which, but I recall that either 'Directory' or 'Folder' includes zip files (one does, one doesn't) ... which you don't want in many circumstances (i.e. many programs just can't cope with a zip as a folder).

Share this post


Link to post
Share on other sites

Posted

Thanks TheSaint. As I understood it Folder is the same as adding to the Directory & Drive ID's, so basically it will work when you right click on a drive too.

Share this post


Link to post
Share on other sites

Posted

I've updated the UDF syntax and suppressed certain bugs within the UDF.

Share this post


Link to post
Share on other sites

Posted (edited)

Hi all, anyone know how to make Shortcut Menu to work in DragDrop mod

because if you select multiple files, the program starts several times (for each file, so $CmdLine[0] = always 1 hmmmmmmmm), and not as the classic link in SendTo ($CmdLine[0] = the number of selected files)

http://msdn.microsoft.com/en-us/library/cc144101%28VS.85%29.aspx

other command line variables

// %* - replace with all parameters

// %~ - replace with all parmaters starting with and following the second parameter

// %0 or %1 the first file parameter. For example “C:UsersEricDestopNew Text document.txt”. Generally this should be in quotes and the applications command line parsing should accept quotes to disambiguate files with spaces in the name and different command line parameters (this is a security best practice and I believe mentioned in MSDN).

// %<n> (where N is 2 - 9), replace with the nth parameter

// %s – show command

// %h – hotkey value

// %i – IDList stored in a shared memory handle is passed here.

// %l – long file name form of the first parameter. Note win32 applications will be passed the long file name, win16 applications get the short file name. Specifying %L is preferred as it avoids the need to probe for the application type.

// %d – desktop absolute parsing name of the first parameter (for items that don’t have file system paths)

// %v – for verbs that are none implies all, if there is no parameter passed this is the working directory

// %w – the working directory

will certainly be some flags, perhaps like (Using Item Attributes) http://msdn.microsoft.com/en-us/library/cc144171%28v=vs.85%29.aspx#attributes_items & http://msdn.microsoft.com/en-us/library/windows/desktop/hh127465%28v=vs.85%29.aspx AttributeMask & AttributeValue http://msdn.microsoft.com/en-us/library/bb762589%28v=vs.85%29.aspx Edited by DXRW4E

Share this post


Link to post
Share on other sites

Posted

Look at _ShellFile, I have a workaround towards the end of the thread.

Share this post


Link to post
Share on other sites

Posted

Look at

Share this post


Link to post
Share on other sites

Posted (edited)

Thanks, (sorry wrong topic) I see it now

Ciao.

Edited by DXRW4E

Share this post


Link to post
Share on other sites

Posted

No problem at all.

Share this post


Link to post
Share on other sites

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!


Register a new account

Sign in

Already have an account? Sign in here.


Sign In Now
Sign in to follow this  
Followers 0