【问题标题】:Adding PowerShell command to Windows Context menu (and escaping quotes properly)将 PowerShell 命令添加到 Windows 上下文菜单(并正确转义引号)
【发布时间】:2015-08-03 16:21:43
【问题描述】:

我创建了 Windows 上下文菜单项来执行 powershell 命令。但是,我不知道如何使用转义引号将 %1 传递给我的 Powershell 脚本。

当前注册表项:

[HKEY_CLASSES_ROOT\*\shell\Share file on FTP\Command]
@="cmd.exe /C nircmd elevate PowerShell -NoProfile -NoLogo -Command \"& {(dir \"%1\" | Copy-ToFTP -Destination Public.Screenshots).source | clip}\""

当我通过“在 FTP 上共享文件”上下文菜单项选择文件时产生以下错误:

dir : Cannot find path 'D:\Multimedia' because it does not exist.
At line:1 char:5
+ & {(dir D:\Multimedia Files\Pictures\HTPC\20150328_220120.jpg | Copy-ToOnedrive  ...
+     ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    + CategoryInfo          : ObjectNotFound: (D:\Multimedia:String) [Get-ChildItem], ItemNotFoundException
    + FullyQualifiedErrorId : PathNotFound,Microsoft.PowerShell.Commands.GetChildItemCommand

奖金 我目前正在使用第 3 方工具 Nircmd 来提升 Powershell 提示(因为我的 powershell 命令需要它)。如果可能的话,我想使用本机 Windows 来代替(如果可能的话,将我的命令代码保留在一行中)....不是之后,通过创建一个 Powershell PS1 脚本来提升自己。

编辑: 下面的代码行“应该”工作..但是,我没有得到一个短名称路径,而是得到一个意外的错误结果:

我正在复制和粘贴注册表项值以使其更易于阅读(而不是 .reg 文件内容)

cmd.exe /c for %%A in (%1) do @set I=%%~sA | PowerShell.exe -NoExit -NoProfile -NoExit -NoLogo -Command "& {(dir %I% | Copy-ToFTP -Destination Public.Screenshots).source | clip}"

最终在 Powershell 中生成此输出:

dir : Cannot find path 'D:\Multimedia Files\Pictures\HTPC\:433310880:4624'
because it does not exist.

【问题讨论】:

  • 我认为真正让我感到困惑的是 %~s1 在 Windows 8.1 命令解释器 cmd 下不起作用。我在 Win7 及更早版本下使用了这种缩短技术数十次。因此,即使是只有 echo %~s1 的最简单的批处理文件也会返回完整路径,而不会出现任何缩短或错误。
  • 我猜语法的复杂性会很困难;或者,我现在可能已经看到了有效的答案

标签: powershell cmd registry contextmenu


【解决方案1】:

我终于找到了问题所在。 Windows 本机命令解释器 CMD 将 %1 作为原始脚本块转储到 Powershell。我测试的 Powershell cmdlet 无法自动将 scriptblock 类型转换为字符串类型(当传递给它时。难以调试的是“%1”(带有引号)DID 保留了全名路径;看起来与具有全名目录路径的普通字符串相同,例如:

%1 = “D:\Multimedia Files\Pictures\HTPC\20150328_220120.jpg”

这可以使大多数人误以为这是一个字符串。它实际上被视为一个脚本块!

以下是我对我的问题的解决方案。此外,看起来我根本不需要提升 Powershell 才能使其正常工作。希望将来有人会发现这篇文章有帮助;为他们节省大量时间。

ShareImageOneDrive.reg

Windows Registry Editor Version 5.00

[HKEY_CLASSES_ROOT\*\shell\Share Image on OneDrive\Command]
@="cmd.exe /c PowerShell.exe -NoProfile -WindowStyle Hidden -NoLogo -Command \"& {param ($I = {%1}) ; (Copy-ToOnedrive -Path $I.ToString() -Destination Public).source | clip}\""

注册表键值(更易于阅读代码)

cmd.exe /c PowerShell.exe -NoProfile -WindowStyle Hidden -NoLogo -Command "& {param ($I = {%1}) ; (Copy-ToOnedrive -Path $I.ToString() -Destination Public).source | clip}"

【讨论】:

  • 您能否更清楚地了解建议中最重要的部分?使用您的建议,我所要做的就是将 %1 括在花括号中。无论如何,谢谢你的建议,它确实为我节省了很多时间和头痛!
【解决方案2】:

我如何测试这些是首先我创建一个工作批处理文件。确保在双击批处理文件时转义所有 powershell 以正常工作。然后,一旦我可以正确双击批处理文件,然后我最终通过 GUI 将其复制到注册表项中,以便 GUI 自动正确转义双引号,这在您导出 reg 设置时会发生。

意思是我不直接从注册表进行测试,因为这里有多层转义。

作为一个批处理文件,当我双击下面的命令时,它运行良好(假设我有一个文件夹路径保存到我的剪贴板)。它应该都在一条线上,但由于某种原因它被拆分了。

start /wait /b powershell -command "Clear-Host;$CLIPBOARD = PowerShell -NoProfile -STA -Command {[reflection.assembly]::loadwithpartialname('PresentationCore') | Out-Null;[Windows.Clipboard]::GetText()};C:\Windows\Explorer.exe $CLIPBOARD" 如何获得符合注册表的设置,我只需将 cmd /c 添加到工作批处理脚本的前面,然后直接粘贴到注册表项中,然后导出到 .reg 文件。原因是 regedit.exe 有一个内置函数来转义或加倍 // 一切正确,只要它在批处理文件中工作,你可以用 'cmd /c " 包装它,它会运行。我更喜欢开始 /等待命令,因此它对于我运行的命令类型保持足够长的时间,但可能并非在所有情况下都需要。这是导出到 .reg 文件后得到的结果。

(找到我的例子的来源)

https://superuser.com/a/705188/281412

Windows 注册表编辑器 5.00 版

[HKEY_CLASSES_ROOT\Directory\Background\shell\Open_in_Explorer] "MUIVerb"="Open_in_Explorer_By_KNUCKLE_DRAGGER" "icon"="Explorer.exe" “位置”=“顶部” "扩展"=""

[HKEY_CLASSES_ROOT\Directory\Background\shell\Open_in_Explorer\command] @="cmd /c start /wait /b powershell -command \"Clear-Host;$CLIPBOARD = PowerShell -NoProfile -STA -Command {[reflection.assembly]::loadwithpartialname('PresentationCore') | Out-Null;[Windows.Clipboard]::GetText()};C:\Windows\Explorer.exe $CLIPBOARD\""

对于较大的脚本,您需要使用 base64 编码命令,这将 100% 避免这些问题(base64 字符集不需要转义)并允许从单行运行多行脚本。

https://stackoverflow.com/a/24997890/3093031

这里有几个自我提升脚本的例子。

Determine if script is running hidden

由于某种原因,我的 gui 中没有按钮,无法添加代码标签。必须有人编辑它们。

你是否 100% 确定你不应该调用 nircmdc.exe,nircmd 的命令行版本???

【讨论】:

  • 我需要语法方面的帮助;或者至少是一个更接近我想要做的工作的例子。我所有的测试都是先在批处理文件中完成的...包括使用%~s1(前面提到过)/在Win8下不起作用。
  • 我在处理 "%1" 部分代码时特别需要帮助。
  • PS:另外,据我所知,Windows cmd 解释器没有原生 base64 字符编码。换句话说,在 Powershell 中对已经混乱的字符串/变量进行 base64 编码为时已晚。它必须在传递给 Powershell 之前完成。可能是我解释的不够清楚?
猜你喜欢
  • 2014-07-07
  • 1970-01-01
  • 2014-01-24
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2011-09-21
  • 2012-01-17
相关资源
最近更新 更多