Just as pinning programs to the taskbar is a common setup task, removing or unpinning them is equally important during system cleanup, user profile resets, or desktop standardization. In this guide, we will explore how to unpin programs from the Windows taskbar using Batch Script, covering multiple methods that work across different Windows versions.
Whether you are preparing a clean deployment image or removing unwanted default pins, understanding the unpinning mechanism gives you full control over the taskbar layout.
How Pinned Items Are Stored
Pinned taskbar items are stored as .lnk shortcut files in a specific directory:
%APPDATA%\Microsoft\Internet Explorer\Quick Launch\User Pinned\TaskBarEach pinned application has a corresponding .lnk file in this folder. While deleting the shortcut file is the simplest approach, it may not always fully unpin the item until Explorer refreshes.
Method 1: Deleting the Shortcut File
The most direct way to "unpin" a program is to remove its shortcut from the pinned folder.
Listing Current Pinned Items
Before removing anything, it helps to see what is currently pinned:
@echo off
echo Currently pinned taskbar items:
echo ================================
dir /b "%APPDATA%\Microsoft\Internet Explorer\Quick Launch\User Pinned\TaskBar\*.lnk"
echo.
pauseRemoving a Specific Pinned Item
@echo off
setlocal
set "pinned_folder=%APPDATA%\Microsoft\Internet Explorer\Quick Launch\User Pinned\TaskBar"
set "target=Notepad.lnk"
if exist "%pinned_folder%\%target%" (
del "%pinned_folder%\%target%"
echo [OK] "%target%" removed from taskbar.
) else (
echo [INFO] "%target%" was not found in the pinned folder.
)
pauseMethod 2: PowerShell from Batch
PowerShell provides a more modern way to interact with the Shell COM object.
@echo off
setlocal
set "target=C:\Windows\System32\notepad.exe"
:: Extract the parent folder and file name from the target
for %%F in ("%target%") do (
set "targetDir=%%~dpF"
set "targetName=%%~nxF"
)
powershell -command ^
"$shell = New-Object -ComObject Shell.Application;" ^
"$dir = $shell.Namespace('%targetDir%');" ^
"$item = $dir.ParseName('%targetName%');" ^
"$verbs = $item.Verbs();" ^
"foreach ($v in $verbs) {" ^
" if (($v.Name -replace '&','') -eq 'Unpin from taskbar') {" ^
" $v.DoIt();" ^
" Write-Host '[OK] Unpinned.';" ^
" break;" ^
" }" ^
"}"
pauseCommon Mistakes
The Wrong Way: Only Deleting the File Without Refreshing Explorer
:: WRONG - the taskbar may still show the pinned icon
del "%APPDATA%\...\TaskBar\Notepad.lnk"Output Concern: The shortcut is deleted, but the taskbar icon remains visible until Explorer is restarted or the user logs off. This can be confusing during automated deployments.
The Correct Way: Delete and Refresh
@echo off
set "pinned=%APPDATA%\Microsoft\Internet Explorer\Quick Launch\User Pinned\TaskBar"
del "%pinned%\Notepad.lnk" 2>nul
:: Refresh the taskbar by restarting Explorer
taskkill /f /im explorer.exe >nul 2>&1
timeout /t 2 /nobreak >nul
start explorer.exe
echo [OK] Unpinned and refreshed.Unpinning All Items
To create a completely clean taskbar (useful for kiosk setups or fresh deployments):
@echo off
set "pinned=%APPDATA%\Microsoft\Internet Explorer\Quick Launch\User Pinned\TaskBar"
echo Removing all pinned taskbar items...
del "%pinned%\*.lnk" 2>nul
:: Restart Explorer to apply changes
taskkill /f /im explorer.exe >nul 2>&1
timeout /t 2 /nobreak >nul
start explorer.exe
echo [OK] All taskbar items unpinned.
pauseComplete Unpin Manager Script
This interactive script lets you list, selectively remove, or clear all pinned items.
@echo off
title Taskbar Unpin Manager
setlocal enabledelayedexpansion
set "pinned=%APPDATA%\Microsoft\Internet Explorer\Quick Launch\User Pinned\TaskBar"
:menu
cls
color 0F
echo =============================================
echo TASKBAR UNPIN MANAGER
echo =============================================
echo.
echo [1] List all pinned items
echo [2] Unpin a specific item
echo [3] Unpin all items
echo [4] Unpin via Shell Verb (by .exe path^)
echo [5] Refresh Explorer
echo [0] Exit
echo.
set /p "opt=Select: "
if "%opt%"=="1" goto do_list
if "%opt%"=="2" goto do_unpin_specific
if "%opt%"=="3" goto do_unpin_all
if "%opt%"=="4" goto do_shell_verb
if "%opt%"=="5" goto do_refresh
if "%opt%"=="0" exit /b
goto menu
:: =========================
:do_list
echo.
echo --- Pinned Items ---
if not exist "%pinned%" (
echo [ERROR] Pinned folder not found:
echo %pinned%
pause
goto menu
)
set "count=0"
set "found=0"
for %%f in ("%pinned%\*.lnk") do (
if exist "%%f" (
set "found=1"
set /a count+=1
echo !count!. %%~nf
)
)
if "!found!"=="0" echo No pinned items found.
echo.
pause
goto menu
:: =========================
:do_unpin_specific
echo.
echo --- Pinned Items ---
:: Uses the correct multi-line syntax
powershell -NoProfile -Command ^
"$pinned = $env:APPDATA + '\Microsoft\Internet Explorer\Quick Launch\User Pinned\TaskBar'; " ^
"$i=0; $items=@(); " ^
"Get-ChildItem $pinned -Filter *.lnk -ErrorAction SilentlyContinue | ForEach-Object { " ^
" $i++; " ^
" $name = $_.BaseName; " ^
" $items += $_.FullName; " ^
" Write-Host ($i.ToString() + '. ' + $name) " ^
"}; " ^
"if ($i -eq 0) { Write-Host 'No pinned items found.' }"
echo.
set /p "sel=Enter number to remove: "
:: Uses Shell.Application like your working example for 100% reliability
powershell -NoProfile -Command ^
"$pinned = $env:APPDATA + '\Microsoft\Internet Explorer\Quick Launch\User Pinned\TaskBar'; " ^
"$items = Get-ChildItem $pinned -Filter *.lnk; " ^
"if (%sel% -le $items.Count -and %sel% -gt 0) { " ^
" $shell = New-Object -ComObject Shell.Application; " ^
" $dir = $shell.Namespace($pinned); " ^
" $item = $dir.ParseName($items[%sel%-1].Name); " ^
" $verbs = $item.Verbs(); " ^
" foreach ($v in $verbs) { " ^
" if (($v.Name -replace '&','') -eq 'Unpin from taskbar') { " ^
" $v.DoIt(); " ^
" Write-Host '[OK] Unpinned item.'; " ^
" break " ^
" } " ^
" } " ^
"} else { " ^
" Write-Host '[ERROR] Invalid selection.' " ^
"}"
pause
goto menu
:: =========================
:do_unpin_all
echo.
set /p "confirm=Remove ALL pinned items? (Y/N): "
if /i not "%confirm%"=="Y" goto menu
echo.
echo Removing all pinned items...
powershell -NoProfile -ExecutionPolicy Bypass -Command ^
"$pinned = $env:APPDATA + '\Microsoft\Internet Explorer\Quick Launch\User Pinned\TaskBar'; " ^
"Get-ChildItem $pinned -Filter *.lnk -ErrorAction SilentlyContinue | Remove-Item -Force; " ^
"Write-Host '[OK] All pinned items removed.'"
echo Restarting Explorer...
taskkill /f /im explorer.exe >nul 2>&1
timeout /t 2 /nobreak >nul
start explorer.exe
pause
goto menu
:: =========================
:do_shell_verb
echo.
set /p "exe_path=Enter full .exe path: "
if not exist "!exe_path!" (
echo [ERROR] File not found.
pause
goto menu
)
echo.
echo Unpinning using PowerShell...
:: FIXED: Correct syntax and fixed the Resolve-Path parenthesis typo
powershell -NoProfile -ExecutionPolicy Bypass -Command ^
"$pinned = $env:APPDATA + '\Microsoft\Internet Explorer\Quick Launch\User Pinned\TaskBar'; " ^
"$target = (Resolve-Path '%exe_path%').Path.ToLower(); " ^
"$found = $false; " ^
"Get-ChildItem $pinned -Filter *.lnk -ErrorAction SilentlyContinue | ForEach-Object { " ^
" try { " ^
" $s = (New-Object -ComObject WScript.Shell).CreateShortcut($_.FullName).TargetPath.ToLower(); " ^
" if ($s -eq $target) { " ^
" Remove-Item $_.FullName -Force; " ^
" Write-Host '[OK] Unpinned:' $_.Name; " ^
" $found = $true " ^
" } " ^
" } catch {} " ^
"}; " ^
"if (-not $found) { Write-Host '[INFO] No matching pinned item found.' }"
pause
goto menu
:: =========================
:do_refresh
echo Restarting Explorer...
taskkill /f /im explorer.exe >nul 2>&1
timeout /t 2 /nobreak >nul
start explorer.exe
goto menuWindows 11 Considerations
Windows 11 uses a different pinning mechanism internally. The taskbar layout is stored in the registry rather than as individual shortcut files:
HKCU\Software\Microsoft\Windows\CurrentVersion\Explorer\TaskbandThe Favorites binary value in this key contains the serialized list of pinned items. Editing this value directly is complex and not recommended unless you are using specialized deployment tools.
For Windows 11 enterprise deployments, consider using:
- Start Menu Layout policies via Group Policy
- Provisioning packages (PPKG) with Windows Configuration Designer
- Intune with custom taskbar layout XML
Best Practices
- List before deleting: Always check what is currently pinned before making changes.
- Use Shell Verbs when possible: They are more reliable than file deletion because they properly notify Explorer of the change.
- Restart Explorer only when necessary: Combine multiple unpin operations before a single restart.
- Test on target OS: Methods vary significantly between Windows 10 and Windows 11.
- Provide a confirmation prompt: Before clearing all pins, always ask for user confirmation.
Conclusion
Unpinning programs from the Windows taskbar in Batch Script can be achieved through file deletion, Shell Verb invocation, or PowerShell COM interaction. Each method has its trade-offs in terms of simplicity, reliability, and OS version compatibility. For most scenarios, the Shell Verb method provides the cleanest results, while direct shortcut deletion is the simplest fallback. Understanding both approaches ensures you can manage taskbar layouts effectively across any Windows environment.