[新手上路]批处理新手入门导读[视频教程]批处理基础视频教程[视频教程]VBS基础视频教程[批处理精品]批处理版照片整理器
[批处理精品]纯批处理备份&还原驱动[批处理精品]CMD命令50条不能说的秘密[在线下载]第三方命令行工具[在线帮助]VBScript / JScript 在线参考
返回列表 发帖

[问题求助] PowerShell怎样复制 快捷方式 链接的源文件到剪贴板?

复制 快捷方式 链接的源文件或目录到剪贴板,以便于可以在别的文件夹中粘贴。
格式:脚本.ps1 任意多个快捷方式...

test.ps1
  1. $shell = New-Object -ComObject 'WScript.Shell' ; $arr = @()
  2. $args | foreach { $arr += $shell.CreateShortcut($_).TargetPath }
  3. $s = $arr -join "`r`n" ; Write-Host $s
  4. Set-Clipboard -Value $s
复制代码
powershell test.ps1 "C:\Users\Public\Desktop\腾讯QQ.lnk"  "F:\Desktop\微信.lnk"

TOP

回复 2# went


    好像不行,粘贴按钮仍然是灰色的

TOP

  1. [void][System.Reflection.Assembly]::LoadWithPartialName('System.Windows.Forms')
  2. $shell = New-Object -ComObject 'WScript.Shell'
  3. $paths = New-Object 'System.Collections.Specialized.StringCollection'
  4. $args | foreach {
  5.     $file_str = $shell.CreateShortcut($_).TargetPath
  6.     Write-Host $file_str
  7.     [void]$paths.Add($file_str)
  8. }
  9. [System.Windows.Forms.Clipboard]::SetFileDropList($paths)
复制代码
1

评分人数

TOP

回复 4# went


    多谢,如果能把该脚本加入到 快捷方式 的右键菜单,就更方便使用了

TOP

test.bat 管理员运行
  1. @echo off & cd /d "%~dp0"
  2. set "ps1=F:\Desktop\test.ps1"
  3. reg add "HKCR\lnkfile\shell\复制源到剪贴板\command" /ve /d "powershell \"%ps1%\" %%1" /f
  4. pause&exit
复制代码
F:\Desktop\test.ps1
只支持单个文件右键

TOP

回复 6# went


    多文件选择,我使用 发送到 菜单 -> 脚本.ps1解决了
    但框择多个文件时会夹杂着非lnk文件,这时脚本会报错。
    能改成对于传递进来的非lnk文件正常复制吗?即:脚本.ps1 1.lnk 2.txt 3.lnk
    复制1和3的源文件和2.txt到剪贴板

TOP

回复 7# g495326
  1. [void][System.Reflection.Assembly]::LoadWithPartialName('System.Windows.Forms')
  2. $shell = New-Object -ComObject 'WScript.Shell'
  3. $paths = New-Object 'System.Collections.Specialized.StringCollection'
  4. $args | foreach {
  5.     if($_.EndsWith('.lnk')){
  6.         $file_str = $shell.CreateShortcut($_).TargetPath
  7.     } else {
  8.         $file_str = $_
  9.     }
  10.     Write-Host $file_str
  11.     [void]$paths.Add($file_str)
  12. }
  13. [System.Windows.Forms.Clipboard]::SetFileDropList($paths)
复制代码

TOP

回复 8# went


    多谢,但使用过程中,只要一个链接所指向的源文件不存在,复制会失败。因为粘贴时什么都不会发生。
    例如:1.lnk 链接 1.txt,2.lnk 链接 2.txt,3.lnk 链接 3.txt,此时我把1.txt删除。然后执行:脚本.ps1 1.lnk 2.lnk 3.lnk
    然后在另一文件夹中执行粘贴将会失败。此时正常的表现应该是跳过1.txt,仅复制2.txt和3.txt。

    另一个是当链接的源文件移动了位置,脚本获取链接的源文件位置仍是旧位置,也会造成复制的失败
    例如:1.lnk 链接 1.txt(假设为c:\1.txt),然后移动1.txt到新的位置(d:\1.txt)。
    然后执行:脚本.ps1 1.lnk,获取的源文件路径是c:\1.txt,而不是d:\1.txt

    还有一个是,能否在脚本运行时,检测到shift键按下且剪贴板中有文件内容,则把当前要复制的文件内容追加到剪贴板。(在右键菜单执行脚本)
    例如:2.lnk 链接 2.txt,此时先复制1.txt,按下shift键,然后执行:脚本.ps1 2.lnk,此时剪贴板应存在1.txt和2.txt

TOP

  1. using namespace 'Microsoft.PowerShell.Commands.AddType.AutoGeneratedTypes';cls
  2. [void][System.Reflection.Assembly]::LoadWithPartialName('System.Windows.Forms')
  3. Add-Type -Name 'WinApi' -MemberDefinition '[DllImport("user32.dll")]public static extern short GetKeyState(uint VK);'
  4. $shell = New-Object -ComObject 'WScript.Shell'
  5. $paths = New-Object 'System.Collections.Specialized.StringCollection'
  6. if([WinApi]::GetKeyState(16) -band 0x8000){ $paths = [System.Windows.Forms.Clipboard]::GetFileDropList() }
  7. $args | foreach { [void]$paths.Add($shell.CreateShortcut($_).TargetPath) }
  8. $paths = $paths | Select-Object -Unique | Where-Object {[System.IO.File]::Exists($_)}
  9. [System.Windows.Forms.Clipboard]::SetFileDropList($paths)
  10. $paths
复制代码
回复 9# g495326

TOP

本帖最后由 g495326 于 2022-10-16 22:34 编辑

回复 10# went


    多谢。但还有些问题
    链接的源文件位置变化,运行报错
    链接的源文件是目录时,运行报错
    对于非lnk文件,运行报错

TOP

本帖最后由 went 于 2022-10-19 16:04 编辑
  1. using namespace 'Microsoft.PowerShell.Commands.AddType.AutoGeneratedTypes'
  2. using namespace 'System.Windows.Forms'
  3. using namespace 'System.Collections.Specialized';cls
  4. [void][System.Reflection.Assembly]::LoadWithPartialName('System.Windows.Forms')
  5. Add-Type -Name 'WinApi' -MemberDefinition '[DllImport("user32.dll")]public static extern short GetKeyState(uint VK);'
  6. $shell = New-Object -ComObject 'WScript.Shell'
  7. $paths = New-Object 'StringCollection'
  8. $arr_err = New-Object 'System.Collections.ArrayList'
  9. if([WinApi]::GetKeyState(16) -band 0x8000){ write-host 'shift';$paths = [Clipboard]::GetFileDropList() }
  10. $args | foreach { [void]$paths.Add($_) }
  11. $paths = &{
  12. $paths | Select-Object -Unique | foreach {
  13. #目录
  14. if([System.IO.Directory]::Exists($_)){ return $_ }
  15. #文件
  16. if([System.IO.File]::Exists($_)){
  17. #lnk文件
  18. if($_.EndsWith('.lnk')){
  19. $p = $shell.CreateShortcut($_).TargetPath
  20. if([System.IO.File]::Exists($p)){ return $p }
  21. if([System.IO.Directory]::Exists($p)){ return $p }
  22.                 [void]$arr_err.Add(('{0} -> {1}' -f $_,$p))
  23. return $null
  24. }
  25. #其它文件
  26. return $_
  27. }
  28. } | Select-Object -Unique
  29. }
  30. if($paths.Count -gt 0){
  31. [Clipboard]::SetFileDropList($paths)
  32. 'ok'
  33. $paths
  34. '-----------'
  35. }
  36. if($arr_err.Count -gt 0){
  37. 'fail'
  38. $arr_err
  39. '-----------'
  40. pause
  41. }
复制代码

TOP

本帖最后由 g495326 于 2022-10-17 22:19 编辑

回复 12# went


    多谢,但还是有之前的问题1,2
    1、快捷方式 链接的 源文件被删除了,运行报错。这种情况应该跳过这些文件。最后打印出这些快捷方式的路径,并阻塞等待任意键之后结束(之所以阻塞,是因为右键菜单中执行,脚本执行完成后会自动关闭PS窗口)
    2、快捷方式 链接的 源文件 位置被改变,运行也会报错。比如 1.lnk 链接 1.txt,1.txt被移动到另一位置。脚本将无法获取1.txt的新位置
    3、shift的检测有时会检测不到,最后发现是脚本检测shift状态时,shift已被释放。能否脚本一运行就首先检测shift状态

TOP

源文件报错第28行改为
  1. if($paths.Count -gt 0){ [Clipboard]::SetFileDropList($paths) }
复制代码
检测shift要加载dll耗时,只有多按一点时间 5-8行都是

TOP

回复 14# went


    我的意思是,打印出链接失效的快捷方式的本身的路径,比如执行:脚本.ps1 1.lnk,1.lnk的源文件找不到,则打印1.lnk本身的路径并提示按任意键继续
    还有1.lnk 链接的源文件位置变化后,执行:脚本.ps1 1.lnk后,仍能找到新的源文件,而不是以找不到源文件处理。(记事本程序可以在处理这种情况,我想脚本也会有办法吧)
    论坛回复不及时,方便说下微信吗(可短消息回我)

TOP

返回列表