Вот функция, которая будет выполнять следующие действия:
- Используйте полный путь для создания временного ярлыка.
- Добавьте аргументы / Значок / Горячую клавишу и описание, если таковые имеются
- Вызвать глагол на временном ярлыке, чтобы создать закрепленный элемент.
Закрепленный элемент будет ссылаться на ваше приложение, а не на временный ярлык (который к тому времени был удален)
Чтобы использовать, просто заполните параметры (только путь обязателен)
Пример использования всех параметров и сплаттинга
$PinParams = @{
Path = 'C:\Program Files (x86)\Google\Chrome\Application\chrome.exe'
Arguments = '-incognito'
Name = 'Chrome Incognito'
Description = 'Launch Chrome (Incognito)'
Hotkey = 'ALT+CTRL+K'
IconLocation = 'C:\Windows\system32\shell32.dll,22'
RunAsAdmin = $true
}
New-PinnedItem @PinParams
Простой пример
New-PinnedItem -Arguments '-incognito' -Path 'C:\Program Files (x86)\Google\Chrome\Application\chrome.exe'
Поддержка имени только для всех элементов в $env:Path
/ установленном приложении
New-PinnedItem -Path 'notepad.exe' # Works because c:\windows\system32 is in $env:path
New-PinnedItem -Path 'chrome.exe' # Works because install path in installed appliation
New-PinnedItem -Path 'chrome' # Automatically assume *.exe if no extension provided
Поддержка запуска команд Powershell
# Internet options CPL
$inetcpl = @{
Command = { Start-Process inetcpl.cpl }
Name = 'inetcpl'
IconLocation = 'C:\Windows\system32\shell32.dll,99'
}
# Win + R
New-PinnedItem @inetcpl
$runcmd = @{
Command = { $obj = New-Object -ComObject Shell.Application; $obj.FileRun() }
Name = 'Run'
IconLocation = 'C:\Windows\system32\shell32.dll,25'
}
New-PinnedItem @runcmd
#Multiline will automatically be converted to single line behind the scene.
New-PinnedItem -name 'test' -Command {
Write-Host 'test'
pause
} -WindowStyle Normal
-
Определение функции
Function New-PinnedItem {
[CmdletBinding()]
param (
[ValidateScript( { $_.IndexOfAny([System.IO.Path]::GetInvalidFileNameChars()) -eq -1 })]
[Parameter(ParameterSetName = 'Path')]
[Parameter(Mandatory, ParameterSetName = 'Command')]
[String]$Name,
[Parameter(Mandatory, ParameterSetName = 'Path')]
[ValidateNotNullOrEmpty()]
[String]$Path,
[Parameter(Mandatory, ParameterSetName = 'Command')]
[scriptblock]$Command,
[ValidateSet('Normal', 'Minimized', 'Maximized')]
[String]$WindowStyle = 'Normal',
[String]$Arguments,
[String]$Description,
[String]$Hotkey,
[String]$IconLocation,
[Switch]$RunAsAdmin,
[String]$WorkingDirectory,
[String]$RelativePath
)
$NoExtension = [System.IO.Path]::GetExtension($path) -eq ""
$pinHandler = Get-ItemPropertyValue -Path "HKLM:\SOFTWARE\Microsoft\Windows\CurrentVersion\Explorer\CommandStore\shell\Windows.taskbarpin" -Name "ExplorerCommandHandler"
New-Item -Path "HKCU:Software\Classes\*\shell\pin" -Force | Out-Null
Set-ItemProperty -LiteralPath "HKCU:Software\Classes\*\shell\pin" -Name "ExplorerCommandHandler" -Type String -Value $pinHandler
if ($PSCmdlet.ParameterSetName -eq 'Command') {
#$Path = "C:\Windows\System32\WindowsPowerShell\v1.0\powershell.exe"
$Path = "powershell.exe"
$Arguments = ('-NoProfile -Command "&{{{0}}}"' -f ($Command.ToString().Trim("`r`n") -replace "`r`n", ';'))
if (!$PsBoundParameters.ContainsKey('WindowStyle')) {
$WindowStyle = 'Minimized'
}
}
if (!(Test-Path -Path $Path)) {
if ($NoExtension) {
$Path = "$Path.exe"
}
$Found = $False
$ShortName = [System.IO.Path]::GetFileNameWithoutExtension($path)
# testing against installed programs (Registry)
$loc = Get-ChildItem HKLM:\Software\Wow6432Node\Microsoft\Windows\CurrentVersion\Uninstall
$names = ($loc | foreach-object { Get-ItemProperty $_.PsPath }).Where( { ![String]::IsNullOrWhiteSpace($_.InstallLocation) })
$InstallLocations1, $InstallLocations2 = $names.Where( { $_.DisplayName -Like "*$ShortName*" }, 'split')
$InstallLocations1 = $InstallLocations1 | Select -ExpandProperty InstallLocation
$InstallLocations2 = $InstallLocations2 | Select -ExpandProperty InstallLocation
Foreach ($InsLoc in $InstallLocations1) {
if (Test-Path -Path "$Insloc\$path") {
$Path = "$Insloc\$path"
$Found = $true
break
}
}
if (! $found) {
$Result = $env:Path.split(';').where( { Test-Path -Path "$_\$Path" }, 'first')
if ($Result.count -eq 1) { $Found = $true }
}
# Processing remaining install location (less probable outcome)
if (! $found) {
Foreach ($InsLoc in $InstallLocations2) {
if (Test-Path -Path "$Insloc\$path") {
$Path = "$Insloc\$path"
$Found = $true
exit for
}
}
}
if (!$found) {
Write-Error -Message "The path $Path does not exist"
return
}
}
if ($PSBoundParameters.ContainsKey('Name') -eq $false) {
$Name = [System.IO.Path]::GetFileNameWithoutExtension($Path)
}
$TempFolderName = "tmp$((48..57 + 97..122| get-random -Count 4 |% {[char][byte]$_}) -join '')"
$TempFolderPath = "$env:temp\$TempFolderName"
$ShortcutPath = "$TempFolderPath\$Name.lnk"
[Void](New-Item -ItemType Directory -Path $TempfolderPath)
if ($Path.EndsWith(".lnk")) {
Copy-Item -Path $Path -Destination $ShortcutPath
$obj = New-Object -ComObject WScript.Shell
$link = $obj.CreateShortcut($ShortcutPath)
}
else {
$obj = New-Object -ComObject WScript.Shell
$link = $obj.CreateShortcut($ShortcutPath)
$link.TargetPath = $Path
}
switch ($WindowStyle) {
'Minimized' { $WindowstyleID = 7 }
'Maximized' { $WindowstyleID = 3 }
'Normal' { $WindowstyleID = 1 }
}
$link.Arguments = $Arguments
$Link.Description = $Description
if ($PSBoundParameters.ContainsKey('IconLocation')) { $link.IconLocation = $IconLocation }
$link.Hotkey = "$Hotkey"
$link.WindowStyle = $WindowstyleID
if ($PSBoundParameters.ContainsKey('WorkingDirectory')) { $link.WorkingDirectory = $WorkingDirectory }
if ($PSBoundParameters.ContainsKey('RelativePath')) { $link.RelativePath = $RelativePath }
$link.Save()
if ($RunAsAdmin) {
$bytes = [System.IO.File]::ReadAllBytes($ShortcutPath)
$bytes[0x15] = $bytes[0x15] -bor 0x20 #set byte 21 (0x15) bit 6 (0x20) ON
[System.IO.File]::WriteAllBytes($ShortcutPath, $bytes)
}
$Shell = New-Object -ComObject "Shell.Application"
$Folder = $Shell.Namespace((Get-Item $ShortcutPath).DirectoryName)
$Item = $Folder.ParseName((Get-Item $ShortcutPath).Name)
$Item.InvokeVerb("pin")
Remove-Item -LiteralPath "HKCU:Software\Classes\*\shell\pin\" -Recurse
Remove-item -path $ShortcutPath
Remove-Item -Path $TempFolderPath
[void][System.Runtime.InteropServices.Marshal]::ReleaseComObject([System.__ComObject]$shell)
[void][System.Runtime.InteropServices.Marshal]::ReleaseComObject([System.__ComObject]$obj)
}
В заключение, для ваших нужд вы должны назвать это так:
New-PinnedItem -Path 'C:\Program Files (x86)\Google\Chrome\Application\chrome.exe' -Arguments '--proxy-server=192.168.1.2:8080'
Дополнительные соображения
Похоже, что при закреплении чего-то важны две вещи:
- Полный путь к приложению
- Переданные аргументы
Другие параметры не имеют значения для действия с ПИН-кодом. Любое действие PIN, вызванное с тем же набором полного пути и аргументов, будет сравниваться с другими контактами и либо с контактом (если не найден), либо с не закрепленным (если найден) без учета Name / IconLocation / Hotkey / et c ...
Обратите внимание, что если вы используете функцию для закрепления уже открытого элемента (например, Chrome), действие закрепления / открепления будет выполнено для текущего экземпляра, если путь / аргументы совпадают, то есть выглядят так, как будто они не работают, но если вы посмотрите на состояние закрепления открытого приложения (или закроете его), вы увидите, что поведение изменилось с неподкрепленного на закрепленное или закрепленного на неподкрепленное (если оно уже закреплено)
Дополнительные примечания
Контактные данные хранятся в 2 местах
HKCU:\Software\Microsoft\Windows\CurrentVersion\Explorer\Taskband
$env:APPDATA\Microsoft\Internet Explorer\Quick Launch\User Pinned\TaskBar
Вы можете легко поменять 2 или более наборов панелей задач, используя их.
Вот фрагмент кода для просмотра избранных данных в виде шестнадцатеричного / строкового
$Bytes = Get-ItemPropertyValue -LiteralPath "HKCU:\Software\Microsoft\Windows\CurrentVersion\Explorer\Taskband\" -name 'Favorites'
# Data as Hex
[System.BitConverter]::ToString($bytes)
# A look at the data
[System.Text.Encoding]::UTF8.GetString($Bytes)
Ссылки
[MS-SHLLINK] : Бинарный формат файла Shell Link (.LNK)
Создание ярлыка «Запуск от имени администратора»