Change a folder's icon with a custom right click menu

I try to make a custom right click menu that allows me to set a folder's custom icon using whatever folder.ico I put in that folder.

My way so far:

Have a right click menu on folders that runs a batch file (done thanks to this topic):

Windows Registry Editor Version 5.00

[HKEY_CLASSES_ROOT\Directory\shell\set_folder_icon]
@="Set folder icon"

[HKEY_CLASSES_ROOT\Directory\shell\set_folder_icon\command]
@="\"C:\\path\\set_folder_icon.bat\" \"%1\""

For the bat file, I fail to make it work. I fear this is because I can't get it to pickup the folder I right click on.

I based my work from this topic:

rem @echo off
set O=desktop.old
set F=desktop.ini
FOR /R %%I IN (*.ico) DO @(
cd%%~pI 
if exist %%~dpnfolder.ico (
echo %%~dpnfolder.ico
attrib -h -s %F% 
copy /Y %F% %O%
echo [.ShellClassInfo] > %F%
echo IconResource=folder.ico,0 >> %F%
echo [ViewState] >> %F%
echo Mode= >> %F%
echo Vid= >> %F%
echo FolderType=Generic >> %F%
attrib +h +s %F% 
)
)
pause

I'd like to just check if folder.ico exists, edit desktop.ini or create it entirely if it doesn't exist (I don't know if the current bat can do that), and ideally (but not mandatory) not edit the other options that might be there already.


@echo off 

setlocal EnableExtensions
title <nul && title ..\\%~nx0
%__AppDir__%chcp.com 1252 >nul

set "_bat=%~dpnx0" & %__AppDir__%mode.com 40,02
set "_key=HKCR\Directory\shell\Set_Folder_Icon"

set "_reg_qry=%__AppDir__%reg.exe query "%_key%""
set "_ico_reg=%SystemRoot%\System32\shell32.dll,71"
set "_bat=%_bat:\=\\%" & set "_ico_reg=%_ico_reg:\=\\%"

>nul 2>&1 ( %__AppDir__%net.exe "session" && set "_adm=y" || set "_adm=n"
      %_reg_qry%|%__AppDir__%find.exe "_" && set "_reg=y" || set "_reg=n")

if /i "%_adm%|%_reg%" == "y|n" >nul 2>&1 (
    ( %__AppDir__%reg.exe add "%_key%" /ve /d "Set Folder Icon" /f
      %__AppDir__%reg.exe add "%_key%\command" /ve /d "\"%_bat%\" \"%%V\"" /f
      %__AppDir__%reg.exe add "%_key%" /v Icon /t reg_sz /d "\"%_ico_reg%\"" /f
    )&& goto %:^))else if /i "%_adm%|%_reg%" == "n|n" (set "_er=y" && goto %:^|
    )else if "%_adm%%_reg%" == "yy" (set "_er=n" && goto %:^|)else ;set "_er=n"
    
%:^)
2>nul cd/d "%~dpnx1\\." && %__AppDir__%Attrib.exe -r -a .\. || goto %:^|

if exist .\\Folder.ico (%__AppDir__%Attrib.exe -s -r -h +a .\\Folder.ico
    )else if exist .\\*.ico (for %%i in (.\\*.ico)do ren "%%~fi" Folder.ico & goto %:^/
    )else goto %:^| )

%:^/ 
if exist .\\Desktop.ini >.\\Desktop.old (
     %__AppDir__%Attrib.exe -s -r -h +a .\\Desktop.ini
     echo;[.ShellClassInfo] && echo;IconResource=Folder.ico,0
     %__AppDir__%Findstr.exe /bliv "\[\.Shell IconR IconF IconI" <.\\Desktop.ini
    )else >nul 2>&1 %__AppDir__%CertUtil.exe -decode -f "%~dpnx0" .\\Desktop.ini

if exist .\\Desktop.old >nul 2>&1 move/y .\\Desktop.old .\\Desktop.ini
        
%:^|
if "%_er%" == "y" (%__AppDir__%timeout.exe 5|echo\Admin rights required!
    )else if "%_er%" == "n" (%__AppDir__%Attrib.exe +s +r +h -a .\\Desktop.ini 
     <con: %__AppDir__%Attrib.exe -r +a .\. && %__AppDir__%Attrib.exe +r -a .\.
     <con: cd../ && %comSpec% /e:off/v:off/s/q/r "ren "%~dpnx1" "%~nx1" >nul 2>&1"
    )>nul 2>&1 else rem :: batch continue.
     
2>nul del/q /f /a "%~f1\Desktop.old" & endlocal & <con: move nul 2>&0 ||goto :eOf
::-----BEGIN -----Wy5TaGVsbENsYXNzSW5mb10gDQpJY29uUmVzb3VyY2U9LlxGb2xkZXIuaWNvLDA
NCltWaWV3U3RhdGVdDQpNb2RlPQ0KVmlkPQ0KRm9sZGVyVHlwZT1HZW5lcmljDQo=-----END -----::

enter image description here


This code considers:

  • That you are going to put the bat in the folder where it should be, where it will always be called.

  • Will run a first time (as an administrator) so that the necessary entries in the Windows registry are added, (by the bat itself) and pointed to the location of to your File.bat.

  • The following executions will be right click menu, in the target folder

  • If a Folder.ico file is in the target folder, it will be used, in the absence, another icon file will be used, and renamed to Folder.ico

  • When a Desktop.ini file exists in the target folder, the necessary edits will be made to replace the .ico file, if not, a new one will be created.


1. Run a first time as admin, and it will add all the entries to the Windows registry.

2. Execute (click/prompt), without informing a valid folder as parameter, and it will abort.

3. Informing a valid folder, and it will check if a Folder.ico icon is present and will use it, if it does not exist, it will use another one that is in the same folder.

4. If the informed folder does not contain an icon, it will abort without warnings.

5. If the folder has a \Desktop.ini, it will use all the settings, except those related to icon options.

6. If the folder does not contain >\Desktop.ini, it will create one using decoding a standard file saved in itself in base64 strings.

  • The .\Desktop.ini defaults to folders that do not contain configuration.
[.ShellClassInfo] 
IconResource=.\Folder.ico,0
[ViewState]
Mode=
Vid=
FolderType=Generic
  • Base64 encoded .\Desktop.ini:
-----BEGIN CERTIFICATE-----
Wy5TaGVsbENsYXNzSW5mb10gDQpJY29uUmVzb3VyY2U9LlxGb2xkZXIuaWNvLDAN
CltWaWV3U3RhdGVdDQpNb2RlPQ0KVmlkPQ0KRm9sZGVyVHlwZT1HZW5lcmljDQo=
-----END CERTIFICATE-----
  • Base64 encoded .\Desktop.ini strings in the bat/code:
::-----BEGIN -----Wy5TaGVsbENsYXNzSW5mb10gDQpJY29uUmVzb3VyY2U9LlxGb2xkZXIuaWNvLDA
NCltWaWV3U3RhdGVdDQpNb2RlPQ0KVmlkPQ0KRm9sZGVyVHlwZT1HZW5lcmljDQo=-----END -----::

Note: Assign the icon to the folder, some displays immediately, others after a few seconds, the same seems to happen also when we change the wallpaper via the Windows registry/command line...

Obs.: CertUtil.exe already comes with Windows


A short answer, where the presence of registry entries are ignored, would be...

@echo off 

setlocal EnableExtensions
%__AppDir__%mode.com 40,02 
%__AppDir__%chcp.com 1252 >nul

2>nul cd/d "%~f1\\." || goto %:^|
if not exist ".\\Folder.ico" goto %:^|
<con: %__AppDir__%Attrib.exe -r -a .\.

if exist .\\Desktop.ini >.\\Desktop.old (
     %__AppDir__%Attrib.exe -s -r -h +a .\\Desktop.ini
     echo;[.ShellClassInfo] && echo;IconResource=.\Folder.ico,0
     %__AppDir__%Findstr.exe /bliv "\[\.Shell IconR IconF IconI" <.\\Desktop.ini
    ) else >nul 2>&1 %__AppDir__%CertUtil.exe -decode -f "%~dpnx0" .\\Desktop.ini

if exist .\\Desktop.old >.\\Desktop.ini %__AppDir__%findstr.exe . <.\\Desktop.old

if exist .\\Folder.ico if exist .\\Desktop.ini (
     %__AppDir__%Attrib.exe -r +a .\. 
     %__AppDir__%Attrib.exe +r -a .\. 
     %__AppDir__%Attrib.exe +r -a .\\Folder.ico
     %__AppDir__%Attrib.exe +s +r +h -a .\\Desktop.ini
     >con: cd..\ && %comSpec% /e:off/v:off/q/r "ren "%%~dpnx1" "%%~nx1". 2>nul")

%:^|
2>nul del/q /f /a "%~f1\Desktop.old" & endlocal & <con: move nul 2>&0 ||goto :eOf
::-----BEGIN -----Wy5TaGVsbENsYXNzSW5mb10gDQpJY29uUmVzb3VyY2U9LlxGb2xkZXIuaWNvLDA
NCltWaWV3U3RhdGVdDQpNb2RlPQ0KVmlkPQ0KRm9sZGVyVHlwZT1HZW5lcmljDQo=-----END -----::

enter image description here

This code considers:

  • That the entries in the registry have been made, and the path of the bat file is set in the registry correctly.

  • A Folder.ico file already exists in the destination folder.

  • If Desktop.ini is not in the target folder, a new one will be created, if it exists, the relevant edits to the Folder.ico file will be made in the existing Desktop.ini.


  • The Set_Folder_Icon.reg file looks like:
Windows Registry Editor Version 5.00

[HKEY_CLASSES_ROOT\Directory\shell\Set_Folder_Icon]
@="Set Folder Icon"
"Icon"="\"C:\\\\WINDOWS\\\\System32\\\\shell32.dll,71\""

[HKEY_CLASSES_ROOT\Directory\shell\Set_Folder_Icon\command]
@="\"F:\\\\2020-SU\\\\Q1635169\\\\Q1635169.cmd\" \"%V\""

; Just replace drive and folder\file name...

  • The Remove_Set_Folder_Icon.reg file looks like:
Windows Registry Editor Version 5.00

[-HKEY_CLASSES_ROOT\Directory\shell\Set_Folder_Icon]

  • To add register entries in command line, run as admin:
%__AppDir__%reg.exe add "HKCR\Directory\shell\Set_Folder_Icon" /ve /d "Set Folder Icon" /f
%__AppDir__%reg.exe add "HKCR\Directory\shell\Set_Folder_Icon\command" /ve /d "\"F:\\2020-SU\\Q1635169\\Q1635169.cmd\" \"%V\"" /f
%__AppDir__%reg.exe add "HKCR\Directory\shell\Set_Folder_Icon" /v Icon /t reg_sz /d "\"C:\\WINDOWS\\System32\\shell32.dll,71\"" /f

rem ::  Just replace F:\\2020-SU\\Q1635169\\Q1635169.cmd\" 
rem ::  To the pertinent Drive:\\Folder\\Path\\To\\File\\Name.cmd
  • To delete the register entries in command line, run as admin:
reg delete HKEY_CLASSES_ROOT\Directory\shell\Set_Folder_Icon /f

  • You also can use a .cmd instead .reg file to add all entries in the Windows Register
  • Save the contents below as File.cmd, and run as an administrator to add the registry entries.
Windows Registry Editor Version 5.00 2>nul

;The following line/commands run and add the current file by "itself"
;@(cls & %__APPDIR__%reg.exe import "%~f0" >nul 2>&1 & goto=:EOF )

[HKEY_CLASSES_ROOT\Directory\shell\Set_Folder_Icon]
@="Set Folder Icon"
"Icon"="\"C:\\\\WINDOWS\\\\System32\\\\shell32.dll,71\""

[HKEY_CLASSES_ROOT\Directory\shell\Set_Folder_Icon\command]
@="\"F:\\\\2020-SU\\\\Q1635169\\\\Q1635169.cmd\" \"%V\""

; Just replace drive and folder\file name...
  • To do the same for remove all entries in the Windows Register
Windows Registry Editor Version 5.00 2<nul

;The following line remove HKCR\...\Set_Folder_Icon
;@(cls & %__APPDIR__%reg.exe import "%~f0" >nul 2>&1 & goto=:EOF )

[-HKEY_CLASSES_ROOT\Directory\shell\Set_Folder_Icon]

  • Some further reading:

    • If /?

    • Set /?

    • For /?

    • For /F /?

    • Attrib /?F

    • Findstr /?

    • Goto | Call :Label

    • Redirection |, <, > 2>, ...

    • DOS - String Manipulation

    • Conditional Execution || && ...

    • CertUtil /dostips.com

    • Unicode, UTF, ASCII, ANSI format differences

    • Base64 Encode or Decode (MacOS/Windows/Linux)

How does the Windows Command Interpreter cmd.exe Parse Scripts

How-to: Escape Characters, Delimiters and Quotes at the Windows command line