Skip to main content

How to Set a Custom Icon for a Shortcut in Batch Script

Shortcuts with default icons blend into the desktop and are easy to overlook. Setting a custom icon makes your shortcuts visually distinct, professional, and immediately recognizable. In this guide, we will learn how to programmatically assign custom icons to Windows shortcut (.lnk) files using Batch Script, whether the icon comes from a .ico file, an .exe, a .dll, or any other compatible source.

This technique is invaluable for deployment scripts, branding purposes, and creating polished user environments.

Where Windows Gets Shortcut Icons

When you create a shortcut in Windows, the icon is determined by the IconLocation property of the .lnk file. This property accepts a path and an optional index:

  • C:\path\to\file.ico: Uses a standalone icon file.
  • C:\path\to\app.exe, 0: Uses the first icon embedded in an executable.
  • C:\Windows\System32\shell32.dll, 3: Uses icon index 3 from the Windows shell icon library.
  • imageres.dll, 15: Uses an icon from the Windows image resources library.

The index number is zero-based and refers to the position of the icon within the resource file.

Creating a Shortcut with a Custom Icon

Since Batch cannot create .lnk files natively, we use the WScript.Shell COM object via a temporary VBScript file.

Basic Example with a .ico File

@echo off
setlocal

set "shortcut=%USERPROFILE%\Desktop\My Tool.lnk"
set "target=C:\Tools\mytool.exe"
set "icon=C:\Tools\icons\mytool.ico"

(
echo Set ws = CreateObject("WScript.Shell"^)
echo Set sc = ws.CreateShortcut("%shortcut%"^)
echo sc.TargetPath = "%target%"
echo sc.IconLocation = "%icon%"
echo sc.Save
) > "%temp%\seticon.vbs"

cscript /nologo "%temp%\seticon.vbs"
del "%temp%\seticon.vbs"

echo [OK] Shortcut created with custom icon.
pause

Using an Icon from shell32.dll

The shell32.dll library contains hundreds of built-in Windows icons. This is convenient when you don't have a custom .ico file available.

@echo off
setlocal

set "shortcut=%USERPROFILE%\Desktop\Command Prompt.lnk"
set "target=C:\Windows\System32\cmd.exe"
set "icon=C:\Windows\System32\shell32.dll, 49"

(
echo Set ws = CreateObject("WScript.Shell"^)
echo Set sc = ws.CreateShortcut("%shortcut%"^)
echo sc.TargetPath = "%target%"
echo sc.IconLocation = "%icon%"
echo sc.Save
) > "%temp%\seticon.vbs"

cscript /nologo "%temp%\seticon.vbs"
del "%temp%\seticon.vbs"

echo [OK] Shortcut created with shell32.dll icon.
pause
info

To browse all available icons in shell32.dll, you can use the Windows icon picker: right-click any shortcut, go to Properties, click "Change Icon", and type shell32.dll in the search field.

Common Icon Libraries in Windows

LibraryPathDescription
shell32.dllC:\Windows\System32\shell32.dllMain Windows shell icons
imageres.dllC:\Windows\System32\imageres.dllModern Windows icons
moricons.dllC:\Windows\System32\moricons.dllLegacy MS-DOS and Windows icons
pifmgr.dllC:\Windows\System32\pifmgr.dllProgram Information File icons
accessibilitycpl.dllC:\Windows\System32\accessibilitycpl.dllAccessibility icons

Common Mistakes

The Wrong Way: Missing the Index Number

:: WRONG - using a DLL without specifying the icon index
echo sc.IconLocation = "C:\Windows\System32\shell32.dll"

Output Concern: Without the index, Windows defaults to index 0, which is the generic document icon. This is rarely the icon you actually wanted.

The Correct Way: Always Specify the Index

:: CORRECT - specify the exact icon index
echo sc.IconLocation = "C:\Windows\System32\shell32.dll, 15"

Even when using .ico files (which typically contain a single icon), it is good practice to include , 0 for clarity.

The Wrong Way: Using a Non-Existent Icon Path

:: WRONG - path does not exist
echo sc.IconLocation = "C:\Icons\missing_icon.ico"

Output Concern: Windows will fall back to a generic white-page icon. The shortcut will work, but it will look broken and unprofessional.

The Correct Way: Verify Before Setting

@echo off
set "icon_path=C:\Icons\custom.ico"

if not exist "%icon_path%" (
echo [WARNING] Icon file not found. Using default.
set "icon_path=%SystemRoot%\System32\shell32.dll, 0"
)
tip

Always include a fallback icon in your scripts. This ensures shortcuts look clean even if the custom icon file is missing.

Changing the Icon of an Existing Shortcut

You can also modify the icon of a shortcut that already exists on the desktop.

@echo off
setlocal

set "shortcut=%USERPROFILE%\Desktop\Existing App.lnk"
set "new_icon=C:\Icons\new_icon.ico, 0"

if not exist "%shortcut%" (
echo [ERROR] Shortcut not found.
pause
exit /b 1
)

(
echo Set ws = CreateObject("WScript.Shell"^)
echo Set sc = ws.CreateShortcut("%shortcut%"^)
echo sc.IconLocation = "%new_icon%"
echo sc.Save
) > "%temp%\changeicon.vbs"

cscript /nologo "%temp%\changeicon.vbs"
del "%temp%\changeicon.vbs"

echo [OK] Icon updated.
pause

This opens the existing .lnk file, changes only the IconLocation property, and saves it. All other properties (target, arguments, working directory) remain unchanged.

Using PowerShell as an Alternative

@echo off
setlocal

set "shortcut=%USERPROFILE%\Desktop\MyApp.lnk"
set "target=C:\Apps\myapp.exe"
set "icon=C:\Apps\icons\myapp.ico, 0"

powershell -command ^
"$ws = New-Object -ComObject WScript.Shell;" ^
"$sc = $ws.CreateShortcut('%shortcut%');" ^
"$sc.TargetPath = '%target%';" ^
"$sc.IconLocation = '%icon%';" ^
"$sc.Save()"

echo [OK] Shortcut with icon created via PowerShell.
pause

Complete Icon Manager Script

This interactive tool lets you create shortcuts with custom icons or change icons on existing shortcuts.

@echo off
title Shortcut Icon Manager
setlocal enabledelayedexpansion

:menu
cls
color 0F
echo =============================================
echo SHORTCUT ICON MANAGER
echo =============================================
echo.
echo [1] Create new shortcut with custom icon
echo [2] Change icon of existing shortcut
echo [3] Browse shell32.dll icons
echo [4] Browse imageres.dll icons
echo [0] Exit
echo.
set /p "opt=Select: "

if "%opt%"=="1" goto do_create
if "%opt%"=="2" goto do_change
if "%opt%"=="3" goto do_browse_shell32
if "%opt%"=="4" goto do_browse_imageres
if "%opt%"=="0" exit /b
goto menu

:do_create
echo.
set /p "sc_name=Shortcut Name: "
set /p "sc_target=Target .exe Path: "
set /p "sc_icon=Icon Path (e.g., C:\icon.ico or shell32.dll, 15): "

if not exist "!sc_target!" (
echo [ERROR] Target file not found: !sc_target!
pause
goto menu
)

(
echo Set ws = CreateObject("WScript.Shell"^)
echo Set sc = ws.CreateShortcut("%USERPROFILE%\Desktop\!sc_name!.lnk"^)
echo sc.TargetPath = "!sc_target!"
echo sc.IconLocation = "!sc_icon!"
echo sc.Save
) > "%temp%\mk_icon.vbs"
cscript /nologo "%temp%\mk_icon.vbs"
del "%temp%\mk_icon.vbs"
echo [OK] Shortcut created.
pause
goto menu

:do_change
echo.
set /p "sc_path=Full path to .lnk file: "
if not exist "!sc_path!" (
echo [ERROR] File not found.
pause
goto menu
)
set /p "new_icon=New icon path: "

(
echo Set ws = CreateObject("WScript.Shell"^)
echo Set sc = ws.CreateShortcut("!sc_path!"^)
echo sc.IconLocation = "!new_icon!"
echo sc.Save
) > "%temp%\chg_icon.vbs"
cscript /nologo "%temp%\chg_icon.vbs"
del "%temp%\chg_icon.vbs"
echo [OK] Icon changed.
pause
goto menu

:do_browse_shell32
echo.
echo Opening shell32.dll icon browser...
rundll32 shell32.dll,PickIconDlg
pause
goto menu

:do_browse_imageres
echo.
echo Opening imageres.dll icon browser...
rundll32 shell32.dll,PickIconDlg C:\Windows\System32\imageres.dll 0
pause
goto menu

Best Practices

  1. Always specify the icon index, even for .ico files (use , 0).
  2. Prefer shell32.dll or imageres.dll for built-in icons to avoid dependency on external files.
  3. Include a fallback icon in case the custom icon path does not exist.
  4. When modifying existing shortcuts, only change the properties you need and leave everything else intact.
  5. Use .ico files with multiple resolutions (16x16, 32x32, 48x48, 256x256) for the best appearance across different display contexts.

Conclusion

Setting a custom icon for a shortcut in Batch Script transforms generic shortcuts into professional, branded, and user-friendly launch points. By using VBScript or PowerShell as helper mechanisms, you gain full control over the IconLocation property. Whether you are pulling icons from system DLLs, embedding them from executables, or using standalone .ico files, this technique ensures your desktop environment looks exactly the way you want it.