将PowerShell命令添加到Windows上下文菜单(并正确转义引号)



我创建了Windows上下文菜单项来执行powershell命令。然而,我不知道如何通过转义引号传递%1到我的Powershell脚本。

当前注册表项:

[HKEY_CLASSES_ROOT*shellShare file on FTPCommand]
@="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 FilesPicturesHTPC20150328_220120.jpg | Copy-ToOnedrive  ...
+     ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    + CategoryInfo          : ObjectNotFound: (D:Multimedia:String) [Get-ChildItem], ItemNotFoundException
    + FullyQualifiedErrorId : PathNotFound,Microsoft.PowerShell.Commands.GetChildItemCommand

我目前正在使用第三方工具Nircmd来提升Powershell提示符(因为我的Powershell命令需要它)。如果可能的话,我希望使用本机Windows来代替(如果可能的话,将我的命令代码保持在一行)....NOT在之后,通过创建一个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 FilesPicturesHTPC:433310880:4624'
because it does not exist.

我终于解决了这个问题。Windows原生命令解释器CMD将%1作为原始脚本块转储到Powershell。我测试的Powershell cmdlet不能自动将scriptblock类型转换为字符串类型(当传递给它时)。使调试变得困难的是"%1"(用引号括起来)保留了完整的名称路径;它看起来与具有完整名称目录路径的普通字符串相同,例如:

%1 = "D:Multimedia FilesPicturesHTPC20150328_220120.jpg"

这会让大多数人误以为这是一个字符串。它实际上被视为一个scriptblock!

下面是我对我的问题的解决方案。而且,看起来我不需要升级Powershell就可以工作了。希望将来有人会发现这篇文章有所帮助;为他们节省了很多时间。

ShareImageOneDrive.reg

Windows Registry Editor Version 5.00
[HKEY_CLASSES_ROOT*shellShare Image on OneDriveCommand]
@="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}"

我如何测试这些呢?首先我创建一个工作批处理文件。确保在双击批处理文件时逃离所有的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:WindowsExplorer.exe $CLIPBOARD" 如何获得注册表兼容设置,我只需将cmd/c添加到工作批处理脚本的前面,并直接粘贴到注册表项中,然后导出到.reg文件。原因是regedit.exe有一个内置的功能,可以正确地转义或双重//一切,只要它从批处理文件中工作,你可以用'cmd/c "包装它,它就会运行。我更喜欢start/wait命令,这样对于我运行的命令类型,它可以保持足够长的存活时间,但在所有情况下可能都不是必需的。这是我导出到。reg文件后得到的结果。

(找到我的例子的来源)

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

Windows注册表编辑器版本5.00

[HKEY_CLASSES_ROOT 目录 壳 Open_in_Explorer背景)"MUIVerb"="Open_in_Explorer_By_KNUCKLE_DRAGGER"图标"="资源管理器"位置"="顶级"扩展"= " "

[HKEY_CLASSES_ROOT 目录背景 shell命令 Open_in_Explorer ]$CLIPBOARD = powershell -NoProfile -STA -command {[reflection.assembly]::loadwithpartialname('PresentationCore') | Out-Null;[Windows. CLIPBOARD]::GetText()}; c:WindowsExplorer.exe $CLIPBOARD"

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

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

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

判断脚本是否正在运行隐藏

由于某些原因,我的gui中没有按钮,不能添加代码标签。得有人把它们编辑进去。

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

最新更新