如何在特殊的 PowerShell 4 命令提示符下链接命令?
How to Chain Commands at a Special PowerShell 4 Command Prompt?
通常情况下,PowerShell 命令可以用分号链接起来。下面打开2个记事本:
PS> notepad; notepad
您还可以链接更复杂的语句:
PS> Add-Type -AssemblyName System.IO.Compression; `
> $src = "C:\aFolder"; $zip="C:\my.zip"; `
> [io.compression.zipfile]::CreateFromDirectory($src, $zip)
也可以从 CMD 命令行调用链接的 PowerShell 命令:
C:\> powershell notepad; notepad
This post 描述了一种创建 .Net 4.0 PowerShell 提示符的方法,即使 .Net 2.0 是您 OS 上的活动框架。您创建一个 .cmd 脚本,然后 运行 那个。现在您处于 .Net 4.0 环境中。
链接也适用于 4.0 提示:
C:\> ps4.cmd
PS> notepad; notepad
也可以在标准 CMD 提示符下工作:
C:\> ps4 notepad; notepad
描述了一种对显式路径名执行 Add-Type
的方法(需要从 ps4 提示符引用 4.0 程序集):
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"
这有效,即使在 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)
问题:当 ps4 在标准命令提示符下启动时, 链接上述语句失败(post 底部的完整错误):
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)
然而,上述所有方法都有效。为什么?我怎样才能使这项工作?
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
当菊花链命令传递给 powershell.exe
时,字符串周围的双引号被删除。 Add-Type
不受此影响,因为路径不包含空格,因此不需要引号:
Add-Type -Path C:\x\System.IO.Compression.FileSystem.dll # <- this works
但是,在赋值操作中,PowerShell 要求字符串用引号引起来,否则它会将字符串解释为命令并尝试执行它:
$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
这就是导致您观察到的前两个错误的原因。第三个错误是后续错误,因为两个路径变量没有正确初始化。
您应该可以通过转义双引号来避免这种行为:
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)
或者用单引号替换它们(因为后者不被 CMD 识别为引号字符,因此按原样传递给 PowerShell,它确实将它们识别为引号字符):
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)
但是,我建议您创建并 运行 正确的 PowerShell 脚本,而不是解决这个问题,这样您就可以完全避免这个问题:
#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)
脚本会是这样的 运行:
powershell.exe -File zip.ps1 -Path "C:\x\xl" -Zipfile "C:\x\xl.zip"
如果您将执行策略更改为 RemoteSigned
或 Unrestricted
并更改 .ps1 文件的默认处理程序,您甚至可以 运行 脚本如下:
zip.ps1 -Path "C:\x\xl" -Zipfile "C:\x\xl.zip"
通常情况下,PowerShell 命令可以用分号链接起来。下面打开2个记事本:
PS> notepad; notepad
您还可以链接更复杂的语句:
PS> Add-Type -AssemblyName System.IO.Compression; `
> $src = "C:\aFolder"; $zip="C:\my.zip"; `
> [io.compression.zipfile]::CreateFromDirectory($src, $zip)
也可以从 CMD 命令行调用链接的 PowerShell 命令:
C:\> powershell notepad; notepad
This post 描述了一种创建 .Net 4.0 PowerShell 提示符的方法,即使 .Net 2.0 是您 OS 上的活动框架。您创建一个 .cmd 脚本,然后 运行 那个。现在您处于 .Net 4.0 环境中。
链接也适用于 4.0 提示:
C:\> ps4.cmd
PS> notepad; notepad
也可以在标准 CMD 提示符下工作:
C:\> ps4 notepad; notepad
Add-Type
的方法(需要从 ps4 提示符引用 4.0 程序集):
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"
这有效,即使在 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)
问题:当 ps4 在标准命令提示符下启动时, 链接上述语句失败(post 底部的完整错误):
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)
然而,上述所有方法都有效。为什么?我怎样才能使这项工作?
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
当菊花链命令传递给 powershell.exe
时,字符串周围的双引号被删除。 Add-Type
不受此影响,因为路径不包含空格,因此不需要引号:
Add-Type -Path C:\x\System.IO.Compression.FileSystem.dll # <- this works
但是,在赋值操作中,PowerShell 要求字符串用引号引起来,否则它会将字符串解释为命令并尝试执行它:
$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
这就是导致您观察到的前两个错误的原因。第三个错误是后续错误,因为两个路径变量没有正确初始化。
您应该可以通过转义双引号来避免这种行为:
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)
或者用单引号替换它们(因为后者不被 CMD 识别为引号字符,因此按原样传递给 PowerShell,它确实将它们识别为引号字符):
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)
但是,我建议您创建并 运行 正确的 PowerShell 脚本,而不是解决这个问题,这样您就可以完全避免这个问题:
#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)
脚本会是这样的 运行:
powershell.exe -File zip.ps1 -Path "C:\x\xl" -Zipfile "C:\x\xl.zip"
如果您将执行策略更改为 RemoteSigned
或 Unrestricted
并更改 .ps1 文件的默认处理程序,您甚至可以 运行 脚本如下:
zip.ps1 -Path "C:\x\xl" -Zipfile "C:\x\xl.zip"