更新:独立命令---没有脚本文件依赖。

更新:独立命令---没有脚本文件依赖。

在 Windows 10 中,按住 Shift 键并右键单击文件夹或文件资源管理器中的背景会在上下文菜单中添加“在此处打开 PowerShell 窗口”命令。

但是,用于打开 PowerShell 窗口的命令定义不正确(至少从 W10 版本 ID 1709 开始),因为它错误地假定文件夹名称从不包含嵌入'字符:

# !! Breaks with folder names such as "a'b"
powershell.exe -noexit -command Set-Location -literalPath '%V' 

请参阅下文以找到解决方法,但请注意,它需要管理权限。

答案1

更新:独立命令---没有脚本文件依赖。

复制、粘贴并执行此代码电源外壳控制台进行即时“概念验证”演示:

$msg = @'
$Args[0] : {0}
$Args[1] : {1}
'@
&{echo ($msg -f $Args[0], $Args[1])} --% I'm an unquoted string with an apostrophe and spaces.

输出:

PS C:\> $msg = @'
>> $Args[0] : {0}
>> $Args[1] : {1}
>> '@
>> &{echo ($msg -f $Args[0], $Args[1])} --% I'm an unqoted string with an apostroohe and spaces.
$Args[0] : --%
$Args[1] : I'm an unqoted string with an apostroohe and spaces.
PS C:\>
  • (有趣的是,它既--%具有功能性,又可以作为参数捕获)

“魔法子弹”是停止解析 token--%。根据文档:

PowerShell 3.0 中引入的停止解析符号 (--%) 指示 PowerShell 不要将输入解释为 PowerShell 命令或表达式。...

遇到停止解析符号时,PowerShell 会将行中的剩余字符视为文字。

尽管旨在用于可执行文件的参数,但它也可以用于脚本块的参数,如上面的代码所示。

因此,要使用不带引号的路径执行Set-Location,语法是:

    &{Set-Location -LiteralPath $Args[1]} --% <unquoted path>  

因此我们的注册命令变成:

    powershell.exe -NoExit -Command &{Set-Location -LiteralPath $Args[1]} --%% %V  
  • 请注意,需要双百分号 ( %%) 才能%在结果命令中产生文字符号。

要修改整个计算机范围内的命令,请直接编辑注册表。相关键为:

  • HKLM\SOFTWARE\Classes\Directory\Background\Shell\PowerShell\Command
  • HKLM\SOFTWARE\Classes\Directory\Shell\PowerShell\Command
  1. 掌握密钥并完全控制

  2. 编辑(Default)值,将其更改为:

     powershell.exe -NoExit -Command &{Set-Location -LiteralPath $Args[1]} --%% %V  
    
  3. 删除Full Control您为用户添加的权限。

  4. 通过按照您采取的获取所有权的步骤TrustedInstaller指定用户名,将所有者更改回。NT Service\TrustedInstaller

要根据每个用户修改命令,只需创建并编辑注册表项:

  • HKCU\Softwar\Classes\Directory\Background\Shell\PowerShell\Command

  • HKCU\Software\Classes\Directory\Shell\PowerShell\Command
    将的值更改(Default)为:

     powershell.exe -NoExit -Command &{Set-Location -LiteralPath $Args[1]} --%% %V  
    

或者只需复制、粘贴并执行以下命令:

'Background\','' | ForEach{
    $splat = @{
        'Path'    = ('HKCU:\Software\Classes\Directory\{0}Shell\PowerShell\Command' -f $_)
        'Value'   = 'powershell.exe -NoExit -Command &{Set-Location -LiteralPath $Args[1]} --%% %V'
    }
    New-Item @splat -Force
}


原始回复

对于 5.1 的解决方案,我想不出只用电源外壳命令行,但调用单行脚本似乎可以解决问题:

(根据@mklement0 的评论进行代码编辑/改进)

### OpenHere.ps1
Set-Location -LiteralPath $Args[0]

### (HKCU|HKLM)\Software\Classes\Direcory[\Background]\Shell\PowerShell\Command
###
###powershell.exe -noexit -File "C:\Path\to\OpenHere.ps1" "%V"
###
  • 另存为“OpenHere.ps1”到适当位置
  • 然后您可以修改:
    • HKLM\SOFTWARE\Classes\Directory\Shell\PowerShell\Command
      如果您具有管理员权限,并且愿意处理所有权和权限。
      否则,您可以在以下位置创建每个用户的条目:
    • HKCU\Software\Classes\Directory\Shell\PowerShell\Command

注册表命令行的语法是:

  • powershell.exe -noexit -File "C:\Path\to\OpenHere.ps1" "%V"

这是上述代码的“自安装”版本,它将在HKCU(每个用户模式)下创建上下文菜单条目。

  • 将以下内容保存为其.ps1所在目录中的文件。
  • 从运行脚本电源外壳控制台,不带任何参数。代码.ps1在其创建的命令行中使用文件的当前 Path\FileName。
### OpenHere.ps1
If ($Args) {   ### Launched from context menu
    Set-Location -LiteralPath $Args[0]
} Else     {   ### Create HKCU registry entries
    'Background\','' | ForEach {
        $splat = @{
            'Path'   = ('HKCU:\Software\Classes\Directory\{0}Shell\PowerShell\Command' -f $_)
            'Value'  = ('powershell.exe -NoExit -File "{0}" "%V"' -f $PSCommandPath)
            'Type'   = 'ExpandString'
        }
        New-Item @splat -Force
    }
}

###   The "(Default)" value is created as a REG_EXPAND_SZ to allow for subsequent
###   editing that can include environmental variables

答案2

前言

  • Keith Miller 的有用答案是一个实用的自动化解决方案——唯一要注意的是,它只在用户级别

  • 以下答案可能会引起全部用户解决方案和技术背景;OpenHere.ps1Keith 的答案同样可以用于全用户解决方案(自安装部分除外)。


莱斯费奇感谢他的所有贡献。

笔记:

  • 此修复需要管理权限(跑步有海拔)。

开放regedit.exe应用以下步骤两个都以下注册表项HKEY_CLASSES_ROOT\Directory\shell\Powershell\command
HKEY_CLASSES_ROOT\Directory\Background\shell\Powershell\command

  • 准备:修改权限这样就可以修改值(PowerShell 命令):

    • 手动修改权限的替代方案

      • @LesFerch 提到以下第三方实用程序备择方案手动修改权限,允许您regedit.exe直接以NT SERVICE\TrustedInstaller用户身份运行:

        动力运行(我的首选),进阶跑。这是比弄乱权限(人们经常会弄错并破坏东西)更安全的选择。

      • Keith Miller 的有用答案提到定义用户级钥匙作为替代方案 - 不需要提升,但将解决方案限制在当前用户

    • 右键单击command子项并选择Permissions...

    • 点击Advanced并:

      • 使该Administrators团体成为所有者关键的
      • 让该Administrators团体完全控制密钥
    • 注意:我不知道这些修改会产生什么不良影响,但如果您知道任何不良影响,请告诉我们。
      但是,为了安全起见,您可以在修改命令后恢复这些修改,如下所示,这需要将TrustedInstaller安全主体恢复为密钥的所有者command;请注意,您必须将其指定为
      NT SERVICE\TrustedInstaller

  • 现在用以下内容替换command键的(Default)值(请参阅下面有关控制台设置/颜色的注释):

    cmd /c set "_dir=%V%" & powershell.exe -NoExit -Command Set-Location -LiteralPath $env:_dir
    
    • 笔记:

      • 通过调用cmd,您将获得后者的控制台设置而不是 Windows PowerShell 的设置,后者特别包含蓝色背景。

        • 您可以通过start在之前放置来避免这种情况powershell.exe放置来避免这种情况,这将打开新窗户使用通常的设置和颜色,但缺点是,原始的、瞬态的窗口总是会cmd.exe在屏幕上短暂闪烁。

        • Keith Miller 的回答提供替代方案帮手.ps1脚本,允许直接通过 调用powershell.exe -File,从而避免闪烁问题;-File 命令行界面参数将其参数视为字面上地,因此下面使用时描述的问题-Command不适用。

          powershell.exe -NoExit -File "C:\Path\to\OpenHere.ps1" "%V"
          
      • 呼唤通过cmd /c是个最坚固安全的选项:

        • 如果 的值包含字符,则的值%V只会在语法上破坏命令,而这在定义上是不可能的(文件和文件夹名称不能包含)。set""

        • 但是,如果文件夹名称包含类似cmd.exe环境变量引用的内容逐字(例如%OS%引用的变量存在,引用被扩展,导致对该文件夹的更改失败,或者 - 假设 - 以其他文件夹为目标。

        • 命令不能直接用作调用cd的一部分,原因cmd.exepowershell.exe当从名称恰好包含[](例如foo[0])的文件夹调用时,会出现故障。此错误已在PowerShell(核心)7+CLI,pwsh.exe因此您可以简单地使用:

          # PowerShell 7+
          cmd /c cd /d "%V" & pwsh.exe
          
          • 事实上,pwsh.exe新的-WorkingDirectory参数使能直接的调用(这不仅更有效率,而且还避免了控制台设置问题):[1]

            pwsh.exe -WorkingDirectory "%V\."
            
      • powershell.exe直接调用时一个选择,它总是涉及权衡

        • 如果你的文件夹名称可能包含文字'字符,但绝不包含文字`$字符,则可以使用"..."可扩展(插值)字符串),但这伴随着以下 警告

          • 虽然命令只会故障使用逐字文件夹名称,例如foo`bar$foo(或 - 假设 - 针对不同的目录),这可能会导致不需要的命令执行,通过精心恶意制作的包含$(...)子表达式的文件夹名称。

            powershell.exe -NoExit -Command "Set-Location -LiteralPath \"%V\""
            

应该可以编写上述步骤的脚本。


[1] 的\.附加是为了确保路径如C:\也得到了正确处理;否则,PowerShell CLI 会(合理地)解释为"C:\",例如,C:后面跟着一个逃脱 "字符,即实际上逐字 C:", 哪个休息

相关内容