.net - txt - ¿Cómo utilizar los comandos de cadena en un indicador de comandos de PowerShell 4 especial?
script en powershell (1)
Las comillas dobles alrededor de las cadenas se eliminan cuando los comandos en cadena se pasan a powershell.exe
. Add-Type
no se ve afectado por esto, ya que la ruta no contiene espacios, por lo que no requiere comillas:
Add-Type -Path C:/x/System.IO.Compression.FileSystem.dll # <- this works
Sin embargo, en una operación de asignación, PowerShell requiere que las cadenas estén entre comillas, de lo contrario, interpretará la cadena como un comando e intentará ejecutarla:
$src = C:/x/xl # <- this would try to run a (non-existent) command ''C:/x/xl''
# and assign its output to the variable instead of assigning
# the string "C:/x/xl" to the variable
Eso es lo que causa los primeros dos errores que observó. El tercer error es un error posterior, porque las dos variables de ruta no se inicializaron correctamente.
Debería poder evitar este comportamiento escapando las comillas dobles:
ps4 Add-Type -Path /"C:/x/System.IO.Compression.FileSystem.dll/"; $src = /"C:/x/xl/"; $zip=/"C:/x/xl.zip/"; [io.compression.zipfile]::CreateFromDirectory($src, $zip)
o reemplazándolos por comillas simples (porque CMD no reconoce estos últimos como caracteres que se citan y, por lo tanto, se pasan como están a PowerShell, que los reconoce como caracteres que se citan):
ps4 Add-Type -Path ''C:/x/System.IO.Compression.FileSystem.dll''; $src = ''C:/x/xl''; $zip=''C:/x/xl.zip''; [io.compression.zipfile]::CreateFromDirectory($src, $zip)
Sin embargo, en lugar de evitar este problema, recomendaría crear y ejecutar scripts de PowerShell adecuados, para que pueda evitar este problema por completo:
#requires -version 4
[CmdletBinding()]
Param(
[Parameter(Mandatory=$true)]
[string]$Path,
[Parameter(Mandatory=$true)]
[string]$Zipfile,
)
Add-Type -Assembly ''System.IO.Compression.FileSystem'' | Out-Null
[IO.Compression.ZipFile]::CreateFromDirectory($Path, $Zipfile)
El script se ejecutará así:
powershell.exe -File zip.ps1 -Path "C:/x/xl" -Zipfile "C:/x/xl.zip"
Si cambia la política de ejecución a RemoteSigned
o Unrestricted
y también cambia el controlador predeterminado para los archivos .ps1, incluso podría ejecutar el script de esta manera:
zip.ps1 -Path "C:/x/xl" -Zipfile "C:/x/xl.zip"
Normalmente, los comandos de PowerShell se pueden encadenar con punto y coma. Lo siguiente abre 2 blocs de notas:
PS> notepad; notepad
También puede encadenar una declaración más compleja:
PS> Add-Type -AssemblyName System.IO.Compression; `
> $src = "C:/aFolder"; $zip="C:/my.zip"; `
> [io.compression.zipfile]::CreateFromDirectory($src, $zip)
Los comandos de PowerShell encadenados también se pueden llamar desde una línea de comandos de CMD:
C:/> powershell notepad; notepad
Esta publicación describe un método para crear un indicador de .Net 4.0 PowerShell, incluso si .Net 2.0 es el marco activo en su sistema operativo. Usted crea un script .cmd y ejecuta eso. Ahora estás en un entorno .Net 4.0.
El encadenamiento también funciona en ese indicador 4.0:
C:/> ps4.cmd
PS> notepad; notepad
Y también funciona desde el prompt CMD estándar:
C:/> ps4 notepad; notepad
Esta publicación describe una forma de Add-Type
a un nombre de ruta explícito (necesario para hacer referencia a los ensamblados 4.0 desde el indicador ps4):
Add-Type -Path "C:/Windows/Microsoft.NET/assembly/GAC_MSIL/System.IO.Compression.FileSystem/v4.0_4.0.0.0__b77a5c561934e089/System.IO.Compression.FileSystem.dll"
Eso funciona, incluso cuando está encadenado en el indicador de ps4:
C:/> ps4
PS> Add-Type -Path "C:/x/System.IO.Compression.FileSystem.dll"; `
> $src = "C:/x/xl"; $zip="C:/x/xl.zip"; `
> [io.compression.zipfile]::CreateFromDirectory($src, $zip)
Problema: el encadenamiento de la instrucción anterior falla cuando se lanza ps4 en un símbolo del sistema estándar (error completo en la parte inferior de la publicación):
C:/> ps4 Add-Type -Path "C:/x/System.IO.Compression.FileSystem.dll"; $src = "C:/x/xl"; $zip="C:/x/xl.zip"; [io.compression.zipfile]::CreateFromDirectory($src, $zip)
Sin embargo, todos los métodos anteriores funcionan. ¿Por qué? ¿Cómo puedo hacer que esto funcione?
The term ''C:/x/xl'' is not recognized as the name of a cmdlet, function, script file, or operable program. Check the spelling of the name, or if a path was included, verify that the path is correct and try again. At line:1 char:73 + Add-Type -Path C:/x/System.IO.Compression.FileSystem.dll; $src = C:/x/xl <<<< ; $zip=C:/x/xl.zip; [io.compression.zipfile]::CreateFromDirectory($src, $zip) + CategoryInfo : ObjectNotFound: (C:/x/xl:String) [], CommandNotFoundException + FullyQualifiedErrorId : CommandNotFoundException The term ''C:/x/xl.zip'' is not recognized as the name of a cmdlet, function, script file, or operable program. Check the spelling of the name, or if a path was included, verify that the path is correct and try again. At line:1 char:91 + Add-Type -Path C:/x/System.IO.Compression.FileSystem.dll; $src = C:/x/xl; $zip=C:/x/xl.zip <<<< ; [io.compression.zipfile]::CreateFromDirectory($src, $zip) + CategoryInfo : ObjectNotFound: (C:/x/xl.zip:String) [], CommandNotFoundException + FullyQualifiedErrorId : CommandNotFoundException Exception calling "CreateFromDirectory" with "2" argument(s): "The path is not of a legal form." At line:1 char:138 + Add-Type -Path C:/x/System.IO.Compression.FileSystem.dll; $src = C:/x/xl; $zip=C:/x/xl.zip; [io.compression.zipfile]::CreateFromDirectory <<<< ($src, $zip) + CategoryInfo : NotSpecified: (:) [], MethodInvocationException + FullyQualifiedErrorId : DotNetMethodException