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-Location
con 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
Edite el
(Default)
valor, cambiándolo a:powershell.exe -NoExit -Command &{Set-Location -LiteralPath $Args[1]} --%% %V
Elimine el
Full Control
permiso que agregó para su usuario.Vuelva a cambiar el propietario
TrustedInstaller
especificandoNT Service\TrustedInstaller
el 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
.ps1
archivo en el directorio donde residirá. - Ejecute el script desde unPotencia Shellconsola sin argumentos. El código utiliza la ruta actual\nombre de archivo del
.ps1
archivo 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.ps1
respuesta 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.exe
yaplicar los siguientes pasos paraambosde las siguientes claves de registro: HKEY_CLASSES_ROOT\Directory\shell\Powershell\command
y
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.exe
directamente comoNT SERVICE\TrustedInstaller
usuario: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
command
subclave y seleccionePermissions...
Haga clic en
Advanced
y:- hacer del
Administrators
grupo eldueñode la llave - dar al
Administrators
grupo el control total de la clave
- hacer del
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 laTrustedInstaller
entidad de seguridad como propietaria de lacommand
clave; tenga en cuenta que debe especificarlo como
NT SERVICE\TrustedInstaller
.
Ahora reemplace el valor
command
de 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
start
antespowershell.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 invariablementecmd.exe
parpadea brevemente en la pantalla.La respuesta de Keith Miller.ofrece una alternativa a través de un
.ps1
guión de ayuda, que permite la invocación directa víapowershell.exe -File
y 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-Command
no se aplica.powershell.exe -NoExit -File "C:\Path\to\OpenHere.ps1" "%V"
Vocacióna través de
cmd /c
es elmás robustoyseguroopción:El valor de
%V
solo podría interrumpir sintácticamente elset
comando 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.exe
referencia 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
cd
como parte de lacmd.exe
llamada es quepowershell.exe
no funciona correctamente cuando se llama desde una carpeta cuyo nombre contiene[
o]
(por ejemplofoo[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.exe
es nuevo-WorkingDirectory
el 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.exe
directamenteesuna 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`bar
o$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.