如何在 PowerShell 中将 .lnk 文件固定到任务栏?

如何在 PowerShell 中将 .lnk 文件固定到任务栏?

我在 stackoverflow.com 上看到过很多类似的问题,但这个问题不同,在您好奇之前,我为什么不在 stackoverflow.com 上发布这个问题?因为我目前被禁止在那里提问,而且我目前没有足够的时间来编辑所有这些问题。

我想做的事情的简要描述:我想以编程方式将提升的 cmd、powershell、pwsh、python 等固定到任务栏,当然我知道如何使用 explorer.exe 创建快捷方式并固定它们,但我认为 GUI 方法很累人且繁琐,必须单击多次才能完成简单的工作,而我想固定许多程序...

我发现了这一点:

如何使用 Powershell 创建以管理员身份运行的快捷方式

一个例子:

$WshShell = New-Object -comObject WScript.Shell
$Shortcut = $WshShell.CreateShortcut("$Home\Desktop\PowerShell.lnk")
$Shortcut.TargetPath = "C:\Windows\System32\WindowsPowerShell\v1.0\PowerShell.exe"
$Shortcut.Save()
$bytes = [System.IO.File]::ReadAllBytes("$Home\Desktop\PowerShell.lnk")
$bytes[0x15] = $bytes[0x15] -bor 0x20
[System.IO.File]::WriteAllBytes("$Home\Desktop\PowerShell.lnk", $bytes)

该示例将在桌面上以管理员权限创建一个名为“PowerShell”的默认 PowerShell 的快捷方式。

现在,将其包装到一个函数中:

function admin-shortcut {
  PARAM (
    [Parameter(ValueFromPipeline=$true, Mandatory=$true, Position=0)] [system.string] $path,
    [Parameter(ValueFromPipeline=$true, Mandatory=$true, Position=1)] [system.string] $name
    )
    $WshShell = New-Object -comObject WScript.Shell
    $Shortcut = $WshShell.CreateShortcut("$Home\Desktop\$name.lnk")
    $Shortcut.TargetPath = $path
    $Shortcut.Save()
    $bytes = [System.IO.File]::ReadAllBytes("$Home\Desktop\$name.lnk")
    $bytes[0x15] = $bytes[0x15] -bor 0x20
    [System.IO.File]::WriteAllBytes("$Home\Desktop\$name.lnk", $bytes)
}

我在 stackoverflow.com 上看到过很多关于将程序直接固定到任务栏的方法的帖子,但是都没有解决我的问题,因为我想赋予固定的快捷方式管理员权限,但我见过的方法都无法做到这一点。

因此我在 Google 上搜索了如何使用 PowerShell 创建管理员快捷方式,并找到了上面提到的方法,现在我只需要弄清楚如何将 .lnk 文件固定到任务栏,不幸的是,所有“如何将快捷方式固定到任务栏”的 Google 搜索结果都谈到直接固定程序,没有一个涉及 .lnk 文件,而且我已经解释了为什么它们在这种情况下不起作用。

那么你有什么想法吗?任何帮助都将不胜感激。


在 Windows 10 上不再有效的过时方法:

方法#1

$shell = new-object -com "Shell.Application"  
$folder = $shell.Namespace((Join-Path $env:SystemRoot System32\WindowsPowerShell\v1.0))
$item = $folder.Parsename('powershell_ise.exe')
$item.invokeverb('taskbarpin');

方法 #2

$shell = new-object -com "Shell.Application"  
$folder = $shell.Namespace('C:\Windows')    
$item = $folder.Parsename('notepad.exe')
$verb = $item.Verbs() | ? {$_.Name -eq 'Pin to Tas&kbar'}
if ($verb) {$verb.DoIt()}

方法 #3

$sa = new-object -c shell.application
$pn = $sa.namespace($env:windir).parsename('notepad.exe')
$pn.invokeverb('taskbarpin')

我将所有这些代码粘贴到 PowerShell 中,没有出现任何错误消息,但这些命令实际上什么也没做,我甚至重新启动了 explorer.exe,仍然没有观察到任何变化......


但是不,等等!一切还没有丢失,我可以将生成的快捷方式拖到任务栏以将其固定到任务栏,也可以右键单击并固定到开始,但想象一下拖动 20 多个快捷方式...如果我能弄清楚这些操作到底是做什么的,我就可以用命令复制它们...


我已经打开了%Appdata%\Microsoft\Internet Explorer\Quick Launch\User Pinned\TaskBar

文件夹并发现我固定的一些(非 UWP)应用程序图标确实在那里,

我在这里找到了一些已添加到开始菜单的应用程序图标:

%AppData%\Microsoft\Internet Explorer\Quick Launch\User Pinned\StartMenu

然而,我已经确认,简单地复制那里的快捷方式是行不通的。

发现了这个:https://docs.microsoft.com/en-us/windows/configuration/configure-windows-10-taskbar, 它是有益的。


我已经找到了一种方法来做到这一点,因为我想要的只是向 xml 文件中添加行,我可以使用这个:

[string[]]$xmlconfig=get-content $template | % {
    $_
    if ($_ -match $pattern) {$line}
}

我知道这很愚蠢,这就是为什么我没有将其作为答案发布,但它确实完成了工作,不要嘲笑我,因为我还在学习,我目前正在研究如何正确操作.xml 文件......

我试过:

[xml]$template=Get-Content $templatefile
$template.SelectNodes("//DesktopApp")

但是它不起作用,它也不适用于从 .admx 文件转换的 xml 对象,但是 .ChildNodes 起作用,并且它没有被 Get-Member 显示...我认为现在将它像纯文本文件一样处理是最好的方法,否则我必须使用这样的东西:

$template.LayoutModificationTemplate.CustomTaskbarLayoutCollection.TaskbarLayout.TaskbarPinList.DesktopApp.DesktopApplicationLinkPath

我已经解决了,现在我将把它作为答案发布,我没有追踪注册表项,而且我不再想将程序固定到开始菜单,因为我通常不使用它......

答案1

最低系统要求

我不知道,我在 Windows 10 20H2 上使用 PowerShell 7.2 预览版 2 x64,我已经测试了脚本并确认它可以运行,并且发现了一个小错误并修复了它;但是我已经测试了我的代码PowerShell 5.1.19041.610并确认我的代码无法在其上运行,所以也许你至少需要PowerShell Core 6?我真的不知道,但建议使用最新版本的 PowerShell。


我通过以下方式解决了它:

  1. 另存为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
    

  2. 保存template.xml在同一目录中pintotaskbar.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>
    

  3. # Accepts a string like:
      # cmd::Command Prompt|pwsh::PowerShell 7|python::Python
    
    .\pintotaskbar.ps1 "cmd::Command Prompt|pwsh::PowerShell 7|python::Python"
    

我发现了一个奇怪的问题,使用上面的例子将生成一个名为“命令提示符 pwsh”的指向的快捷方式%comspec%,我通过删除 $execs 的类型说明符摆脱了这个问题[string],它神奇地消失了,我仍然不知道它是怎么发生的......

答案2

有适用于 Win10 的任务栏固定脚本可供按原样使用、学习形式并根据需要进行调整。

PinToTaskBar1903.ps1 脚本版本 1

使用示例 - PIN/UNPIN 区分大小写:

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

更新您的反对评论。

“链接的脚本伪装了 PEB,我没有看到动词 PIN 和 UNPIN”

你读过这个脚本吗?这个 PIN/UNPIN 直接在脚本代码中调用:

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
}

相关内容