Atualização: um comando independente --- sem dependência de arquivo de script.

Atualização: um comando independente --- sem dependência de arquivo de script.

No Windows 10, clicar com o botão direito do mouse em uma pasta ou em segundo plano no File Explorer adiciona um comando “Abra a janela do PowerShell aqui” ao menu de contexto.

No entanto, o comando usado para abrir a janela do PowerShell está mal definido (pelo menos a partir do ID de versão 1709 do W10), pois assume incorretamente que os nomes das pastas nunca contêm 'caracteres incorporados:

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

Veja abaixo uma correção, mas observe que ela requer privilégios administrativos.

Responder1

Atualização: um comando independente --- sem dependência de arquivo de script.

Copie, cole e execute este código em umPowerShellconsole para uma demonstração instantânea de "prova de conceito":

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

Saída:

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:\>
  • (interessante que --%é funcional e capturado como argumento)

A “bala mágica” é aPare de analisar o token: --%. De acordo com a documentação:

O símbolo de parada de análise (--%), introduzido no PowerShell 3.0, orienta o PowerShell a abster-se de interpretar a entrada como comandos ou expressões do PowerShell.
...
Quando encontra um símbolo de parada de análise, o PowerShell trata os caracteres restantes na linha como literais.

Embora destinado ao uso com argumentos para executáveis, ele também funciona com argumentos para blocos de script, como demonstra o código acima.

Então, para executar Set-Locationcom um caminho sem aspas, a sintaxe é:

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

E assim nosso comando de registro se torna:

    powershell.exe -NoExit -Command &{Set-Location -LiteralPath $Args[1]} --%% %V  
  • Observe que o sinal de porcentagem duplicado ( %%) é necessário para produzir o %símbolo literal no comando resultante.

Para modificar o comando em toda a máquina, edite o registro diretamente. As chaves relevantes são:

  • HKLM\SOFTWARE\Classes\Directory\Background\Shell\PowerShell\Command
  • HKLM\SOFTWARE\Classes\Directory\Shell\PowerShell\Command
  1. Assuma a propriedade da chave e atribua a si mesmo o controle total.

  2. Edite o (Default)valor, alterando-o para:

     powershell.exe -NoExit -Command &{Set-Location -LiteralPath $Args[1]} --%% %V  
    
  3. Remova a Full Controlpermissão que você adicionou para seu usuário.

  4. Altere o proprietário TrustedInstallerespecificando NT Service\TrustedInstallero nome de usuário nas etapas que você seguiu para assumir a propriedade.

Para modificar o comando por usuário, basta criar e editar as chaves de registro:

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

  • HKCU\Software\Classes\Directory\Shell\PowerShell\Command
    Alterando o valor de (Default)para:

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

ou apenas copie, pasee e execute o seguinte:

'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
}


Resposta original

Para uma solução alternativa 5.1, não consigo pensar em uma maneira com apenas umPowerShelllinha de comando, mas chamar um script de uma linha parece funcionar:

(Edição/melhoria de código de acordo com o comentário de @ 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"
###
  • Salve como "OpenHere.ps1" em um local apropriado
  • Você pode então modificar:
    • HKLM\SOFTWARE\Classes\Directory\Shell\PowerShell\Command
      se você tiver acesso de administrador e se sentir confortável em lidar com propriedade e permissões.
      Caso contrário, você pode criar entradas por usuário em:
    • HKCU\Software\Classes\Directory\Shell\PowerShell\Command

A sintaxe da linha de comando do registro é:

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

Aqui está uma versão de "instalação automática" do código acima que criará as entradas do menu de contexto em HKCU(mod por usuário).

  • Salve o seguinte como um .ps1arquivo no diretório onde ele residirá.
  • Execute o script a partir de umPowerShellconsole sem argumentos. O código usa o Path\FileName atual do .ps1arquivo na linha de comando que ele cria.
### 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

Responder2

Prefácio

  • Resposta útil de Keith Milleré uma solução pragmática e automatizada - a única coisa a notar é que ela só funciona nonível de usuário.

  • A resposta abaixo pode ser interessante para umtodos os usuáriossolução e para formação técnica; a OpenHere.ps1resposta de Keith pode igualmente ser usada em uma solução para todos os usuários (exceto para a parte de instalação automática).


Ponta do chapéu paraLesFerchpor todas as suas contribuições.

Observação:

  • Esta correçãorequer privilégios administrativos(correndocom elevação).

Aberto regedit.exeeaplique os seguintes passos paraambosdas seguintes chaves de registro: HKEY_CLASSES_ROOT\Directory\shell\Powershell\commande
HKEY_CLASSES_ROOT\Directory\Background\shell\Powershell\command:

  • Preparação:modificar as permissõespara que a modificação do valor (o comando do PowerShell) seja possível:

    • Alternativas para modificação manual de permissão:

      • @LesFerch menciona os seguintes utilitários de terceiros comoalternativasà modificação manual de permissão, permitindo que você execute regedit.exediretamente como NT SERVICE\TrustedInstallerusuário:

        Power Run(meu preferido),Execução Avançada. Esta é uma opção muito mais segura do que mexer nas permissões (que muitas vezes as pessoas erram e quebram as coisas).

      • Resposta útil de Keith Millermenciona definiçãonível de usuáriochaves como alternativa - o que não requer elevação, mas limita a solução aousuário atual.

    • Clique com o botão direito na commandsubchave e selecionePermissions...

    • Clique Advancede:

      • faça do Administratorsgrupo oproprietárioda chave
      • dê ao Administratorsgrupo controle total da chave
    • Observação: não tenho conhecimento de quaisquer efeitos adversos dessas modificações, mas informe-nos se souber de algum.
      No entanto, por segurança, você pode reverter essas modificações após modificar o comando conforme descrito abaixo, o que implica restaurar a TrustedInstallerentidade de segurança como proprietária da commandchave; observe que você deve especificá-lo como
      NT SERVICE\TrustedInstaller.

  • Agora substitua o valor commandda chave (Default)pelo seguinte (veja a nota sobre configurações/cores do console abaixo):

    cmd /c set "_dir=%V%" & powershell.exe -NoExit -Command Set-Location -LiteralPath $env:_dir
    
    • Observação:

      • Ao chamar via cmd, você obterá as configurações do console deste último em vez das do Windows PowerShell, que incluem principalmente um fundo azul.

        • Você pode evitar isso colocando startbefore powershell.exe, que abre umanova janelacom as configurações e cores usuais, mas a desvantagem é que a janela original e transitória que é invariavelmente criada cmd.exepisca brevemente na tela.

        • A resposta de Keith Milleroferece uma alternativa através de um.ps1script auxiliar, que permite a invocação direta powershell.exe -Filee, portanto, evita o problema de flashing; o-File CLIparâmetro trata seus argumentosliteralmente, portanto, o problema descrito abaixo ao usar -Commandnão se aplica.

          powershell.exe -NoExit -File "C:\Path\to\OpenHere.ps1" "%V"
          
      • Chamandoatravés dacmd /cé omais robustoeseguroopção:

        • O valor de %Vsó poderia quebrar sintaticamente o setcomando se contivesse "caracteres, o que é por definição impossível (nomes de arquivos e pastas não podem conter ").

        • No entanto, se o nome de uma pasta contiver algo parecido com uma cmd.exereferência de variável de ambienteliteralmente(por exemplo %OS%)ea variável referenciada existe, a referência é expandida, fazendo com que a mudança para essa pasta falhe ou - hipoteticamente - uma pasta diferente seja direcionada.

        • A razão pela qual o comando não pode ser usado apenas cdcomo parte da cmd.exechamada é que powershell.exefunciona mal quando chamado de uma pasta cujo nome contém [ou ](por exemplo foo[0], ). Este bug foi corrigido noPowerShell (núcleo) 7+CLI, pwsh.exe, então você poderia simplesmente usar:

          # PowerShell 7+
          cmd /c cd /d "%V" & pwsh.exe
          
          • Na verdade, pwsh.exeé novo-WorkingDirectoryparâmetro permitediretoinvocação (isso não é apenas mais eficiente, mas também evita o problema de configurações do console): [1]

            pwsh.exe -WorkingDirectory "%V\."
            
      • Ao ligar powershell.exediretamenteéuma opção, envolve invariavelmentecompensações:

        • Se os nomes das suas pastas podem conter 'caracteres literais, mas NUNCA contêm caracteres `ou literais $, você pode usar "..."(umexpansível(interpolando) string) em vez disso, mas isso vem com o seguinte EMBARGO:

          • Embora o comando simplesmentedefeituosocom nomes de pastas literais, como foo`barou $foo(ou - hipoteticamente - direcionar umdiferentediretório), isso pode resultar emexecução indesejada de comandos, por meio de nomes de pastas cuidadosamente elaborados com códigos maliciosos que contêm $(...)subexpressões.

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

Deve ser possível criar o script das etapas acima.


[1]\. está anexado para garantir queraizcaminhos como esses C:\também são tratados adequadamente; caso contrário, a CLI do PowerShell interpretaria (justificadamente) "C:\", por exemplo, comoC: seguido por umescapou "caráter, ou seja, com efeito comoliteralmente C:", qualrompe.

informação relacionada