How to pin .lnk files to taskbar in PowerShell?
Solution 1:
Minimum system requirement
I don't know, I am using PowerShell 7.2 preview 2 x64 on Windows 10 20H2, I have tested the script and confirmed it is working, and found a minor bug and fixed it; But I have tested my code on PowerShell 5.1.19041.610
and confirmed my code won't work on it, so maybe you need at least PowerShell Core 6
? I don't really know, but it is advised to use the latest version of PowerShell.
I solved it via:
- Save as
pintotaskbar.ps1
:param( [parameter(mandatory=$true)] [validatenotnullorempty()]$execs ) if (!(test-path $home\pinnedshortcuts)) {new-item $home\pinnedshortcuts -type "directory" > $null} $execs = $execs -split "\|" foreach ($exec in $execs) { $path = ($exec -split "::")[0] $name = ($exec -split "::")[1] if ($path -notmatch "[C-Zc-z]:(\\[^(<>:`"\/\\|?*\x00-\x1f\x7f)]+)+") {$path=where.exe $path} $shortcutpath = "$home\desktop\$name.lnk" $wshshell = new-object -comobject wscript.shell $shortcut = $wshshell.createshortcut($shortcutpath) $shortcut.targetpath = $path $shortcut.save() $bytes = [system.io.file]::readallbytes($shortcutpath) $bytes[0x15] = $bytes[0x15] -bor 0x20 [system.io.file]::writeallbytes($shortcutpath,$bytes) copy-item -path $shortcutpath -destination $home\pinnedshortcuts } $template = get-content "$psscriptroot\template.xml" $pinnedshortcuts = (get-childitem -path $home\pinnedshortcuts -filter "*.lnk").fullname | %{"`t`t<taskbar:DesktopApp DesktopApplicationLinkPath=`"{0}`" />" -f $_} $template = $template | % {$_;if ($_ -match "<taskbar:taskbarpinlist>") {$pinnedshortcuts}} $template | out-file -path "$home\pinnedshortcuts\pinnedshortcuts.xml" import-startlayout -layoutpath $home\pinnedshortcuts\pinnedshortcuts.xml -mountpath c:\ get-process -name "explorer" | stop-process & explorer.exe
- Save
template.xml
in the same directory aspintotaskbar.ps1
:<?xml version="1.0" encoding="utf-8"?> <LayoutModificationTemplate xmlns="http://schemas.microsoft.com/Start/2014/LayoutModification" xmlns:defaultlayout="http://schemas.microsoft.com/Start/2014/FullDefaultLayout" xmlns:start="http://schemas.microsoft.com/Start/2014/StartLayout" xmlns:taskbar="http://schemas.microsoft.com/Start/2014/TaskbarLayout" Version="1"> <CustomTaskbarLayoutCollection> <defaultlayout:TaskbarLayout> <taskbar:TaskbarPinList> </taskbar:TaskbarPinList> </defaultlayout:TaskbarLayout> </CustomTaskbarLayoutCollection> </LayoutModificationTemplate>
-
# Accepts a string like: # cmd::Command Prompt|pwsh::PowerShell 7|python::Python .\pintotaskbar.ps1 "cmd::Command Prompt|pwsh::PowerShell 7|python::Python"
I have found a strange issue, using the above example will generate a working shortcut named "Command Prompt pwsh" that points to %comspec%
, I got rid of this by deleting [string]
type specifier of $execs and it magically went away, I still have no idea how it happened...
Solution 2:
There are scripts for Win10 for taskbar pinning to use as is, learn form, tweak as needed.
PinToTaskBar1903.ps1 script version 1
Example use - PIN/UNPIN are case sensitive:
powershell -noprofile -ExecutionPolicy Bypass -file D:\Scripts\PinToTaskBar1903.ps1 "C:\Windows\Notepad.exe" PIN
powershell -noprofile -ExecutionPolicy Bypass -file C:\Scripts\PinToTaskBar1903.ps1 "C:\Windows\Notepad.exe" UNPIN
Update as to your downvote comment.
"The script linked masquerades PEB, and I have not seen the verbs PIN and UNPIN "
Did you even read the script. This PIN/UNPIN is directly called out in the code of the script:
if (($args[0] -eq "/?") -Or ($args[0] -eq "-h") -Or ($args[0] -eq "--h") -Or ($args[0] -eq "-help") -Or ($args[0] -eq "--help")){
write-host "This script needs to be run with two arguments."`r`n
write-host "1 - Full path to the file you wish to pin (surround in quotes)."
write-host "2 - Either PIN or UNPIN (case insensitive)."
write-host "Example:-"
write-host 'powershell -noprofile -ExecutionPolicy Bypass -file PinToTaskBar1903.ps1 "C:\Windows\Notepad.exe" PIN'`r`n
Break
}