Actualización: un comando independiente, sin dependencia del archivo de script.

Actualización: un comando independiente, sin dependencia del archivo de script.

En Windows 10, al hacer clic con el botón derecho en una carpeta o en segundo plano en el Explorador de archivos, se agrega el comando "Abrir ventana de PowerShell aquí" al menú contextual.

Sin embargo, el comando utilizado para abrir la ventana de PowerShell está mal definido (al menos a partir de la versión W10 ID 1709) en el sentido de que asume incorrectamente que los nombres de las carpetas nunca contienen 'caracteres incrustados:

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

Consulte a continuación una solución, pero tenga en cuenta que requiere privilegios administrativos.

Respuesta1

Actualización: un comando independiente, sin dependencia del archivo de script.

Copie, pegue y ejecute este código en unPotencia Shellconsola para una demostración instantánea de "prueba de concepto":

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

Producción:

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:\>
  • (interesante que --%sea funcional y capturado como argumento)

La "bala mágica" es laDejar de analizar el token: --%. Según la documentación:

El símbolo de parada de análisis (--%), introducido en PowerShell 3.0, indica a PowerShell que se abstenga de interpretar la entrada como comandos o expresiones de PowerShell.
...
Cuando encuentra un símbolo de parada de análisis, PowerShell trata los caracteres restantes de la línea como literales.

Aunque está diseñado para usarse con argumentos para ejecutables, también funciona con argumentos para bloques de secuencias de comandos, como lo demuestra el código anterior.

Entonces, para ejecutar Set-Locationcon una ruta sin comillas, la sintaxis es:

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

Y así nuestro comando de registro se convierte en:

    powershell.exe -NoExit -Command &{Set-Location -LiteralPath $Args[1]} --%% %V  
  • Tenga en cuenta que se necesita el signo de porcentaje duplicado ( %%) para producir el %símbolo literal en el comando resultante.

Para modificar el comando en toda la máquina, edite el registro directamente. Las claves relevantes son:

  • HKLM\SOFTWARE\Classes\Directory\Background\Shell\PowerShell\Command
  • HKLM\SOFTWARE\Classes\Directory\Shell\PowerShell\Command
  1. Toma posesión de la clave y asígnate el control total.

  2. Edite el (Default)valor, cambiándolo a:

     powershell.exe -NoExit -Command &{Set-Location -LiteralPath $Args[1]} --%% %V  
    
  3. Elimine el Full Controlpermiso que agregó para su usuario.

  4. Vuelva a cambiar el propietario TrustedInstallerespecificando NT Service\TrustedInstallerel nombre de usuario en los pasos que siguió para tomar posesión.

Para modificar el comando por usuario, simplemente cree y edite las claves de registro:

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

  • HKCU\Software\Classes\Directory\Shell\PowerShell\Command
    Cambiando el valor de (Default)a:

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

o simplemente copie, pasee y ejecute lo siguiente:

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


Respuesta original

Para una solución alternativa 5.1, no se me ocurre ninguna manera con solo unPotencia Shelllínea de comando, pero llamar a un script de una línea parece funcionar:

(Edición/mejora del código según el comentario 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"
###
  • Guárdelo como "OpenHere.ps1" en una ubicación adecuada
  • Luego puede modificar:
    • HKLM\SOFTWARE\Classes\Directory\Shell\PowerShell\Command
      si tiene acceso de administrador y se siente cómodo manejando la propiedad y los permisos.
      De lo contrario, puede crear entradas por usuario en:
    • HKCU\Software\Classes\Directory\Shell\PowerShell\Command

La sintaxis de la línea de comando del registro es:

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

Aquí hay una versión "autoinstalable" del código anterior que creará las entradas del menú contextual en HKCU(mod por usuario).

  • Guarde lo siguiente como un .ps1archivo en el directorio donde residirá.
  • Ejecute el script desde unPotencia Shellconsola sin argumentos. El código utiliza la ruta actual\nombre de archivo del .ps1archivo en la línea de comando que crea.
### 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

Respuesta2

Prefacio

  • La útil respuesta de Keith Milleres una solución pragmática y automatizada; lo único a tener en cuenta es que solo funciona en elnivel de usuario.

  • La respuesta a continuación puede ser de interés para untodos los usuariossolución y antecedentes técnicos; La OpenHere.ps1respuesta de Keith se puede utilizar igualmente en una solución para todos los usuarios (excepto en la parte de autoinstalación).


Punta del sombrero paralesferchpor todos sus aportes.

Nota:

  • Esta soluciónrequiere privilegios administrativos(corrercon elevación).

Abierto regedit.exeyaplicar los siguientes pasos paraambosde las siguientes claves de registro: HKEY_CLASSES_ROOT\Directory\shell\Powershell\commandy
HKEY_CLASSES_ROOT\Directory\Background\shell\Powershell\command:

  • Preparación:modificar los permisospara que sea posible modificar el valor (el comando de PowerShell):

    • Alternativas a la modificación manual de permisos:

      • @LesFerch menciona las siguientes utilidades de terceros comoalternativasa la modificación manual de permisos, permitiéndole ejecutar regedit.exedirectamente como NT SERVICE\TrustedInstallerusuario:

        Ejecución de energía(mi preferido),Ejecución avanzada. Esta es una opción mucho más segura que alterar los permisos (que la gente suele equivocarse y romper cosas).

      • La útil respuesta de Keith Millermenciona definirnivel de usuarioclaves como alternativa, que no requiere elevación, pero limita la solución alusuario actual.

    • Haga clic derecho en la commandsubclave y seleccionePermissions...

    • Haga clic en Advancedy:

      • hacer del Administratorsgrupo eldueñode la llave
      • dar al Administratorsgrupo el control total de la clave
    • Nota: No tengo conocimiento de ningún efecto adverso de estas modificaciones, pero infórmenos si conoce alguno.
      Sin embargo, para estar seguro, puede revertir estas modificaciones después de modificar el comando como se describe a continuación, lo que implica restaurar la TrustedInstallerentidad de seguridad como propietaria de la commandclave; tenga en cuenta que debe especificarlo como
      NT SERVICE\TrustedInstaller.

  • Ahora reemplace el valor commandde la clave (Default)con lo siguiente (consulte la nota sobre la configuración/colores de la consola a continuación):

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

      • Al llamar a través de cmd, obtendrás la configuración de la consola de este último en lugar de la de Windows PowerShell, que incluye en particular un fondo azul.

        • Puedes evitar esto colocando startantes powershell.exe, lo que abre unanueva ventanacon la configuración y los colores habituales, pero la desventaja es que la ventana transitoria original que se crea invariablemente cmd.exeparpadea brevemente en la pantalla.

        • La respuesta de Keith Miller.ofrece una alternativa a través de un.ps1guión de ayuda, que permite la invocación directa vía powershell.exe -Filey por tanto evita el problema del flasheo; el-File CLIEl parámetro trata sus argumentos.literalmente, por lo que el problema que se describe a continuación al usarlo -Commandno se aplica.

          powershell.exe -NoExit -File "C:\Path\to\OpenHere.ps1" "%V"
          
      • Vocacióna través decmd /ces elmás robustoyseguroopción:

        • El valor de %Vsolo podría interrumpir sintácticamente el setcomando si contuviera "caracteres, lo cual es imposible por definición (los nombres de archivos y carpetas no pueden contener ").

        • Sin embargo, si el nombre de una carpeta contiene algo que parece una cmd.exereferencia de variable de entornoliteral(p.ej %OS%)yla variable a la que se hace referencia existe, la referencia se expande, lo que provoca que el cambio a esa carpeta falle o, hipotéticamente, se seleccione una carpeta diferente.

        • La razón por la que el comando no puede usarse simplemente cdcomo parte de la cmd.exellamada es que powershell.exeno funciona correctamente cuando se llama desde una carpeta cuyo nombre contiene [o ](por ejemplo foo[0]). Este error ha sido corregido en elPowerShell (Núcleo) 7+CLI, pwsh.exe, por lo que simplemente podrías usar:

          # PowerShell 7+
          cmd /c cd /d "%V" & pwsh.exe
          
          • De hecho, pwsh.exees nuevo-WorkingDirectoryel parámetro habilitadirectoinvocación (esto no sólo es más eficiente, sino que también evita el problema de configuración de la consola): [1]

            pwsh.exe -WorkingDirectory "%V\."
            
      • Mientras llama powershell.exedirectamenteesuna opción, invariablemente implicacompensaciones:

        • Si los nombres de sus carpetas pueden contener 'caracteres literales, pero NUNCA contienen caracteres literales `, $puede usar "..."(unampliable(interpolación) cadena) en su lugar, pero esto viene con lo siguiente ADVERTENCIA:

          • Mientras que el comando simplementeFuncionamiento defectuosocon nombres de carpeta textuales como foo`baro $foo(o - hipotéticamente - apuntar a undiferentedirectorio), podría resultar enejecución no deseada de comandos, a través de nombres de carpetas cuidadosamente elaborados con fines malintencionados que contienen $(...)subexpresiones.

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

Debería ser posible programar los pasos anteriores.


[1] \.se adjunta para garantizar queraízcaminos como los que C:\también se manejan adecuadamente; de lo contrario, la CLI de PowerShell interpretaría (justificadamente) "C:\", por ejemplo, como C:seguido de unescapado "carácter, es decir, en efecto comoliteral C:", cualse rompe.

información relacionada