如何在特定的PowerShell中链接命令4命令提示符?

问题描述:

通常,PowerShell命令可以用分号链接。下面打开2个记事本:如何在特定的PowerShell中链接命令4命令提示符?

PS> notepad; notepad 

你也可以连接一个更复杂的语句:

PS> Add-Type -AssemblyName System.IO.Compression; ` 
> $src = "C:\aFolder"; $zip="C:\my.zip"; ` 
> [io.compression.zipfile]::CreateFromDirectory($src, $zip) 

链式PowerShell命令也可以从一个CMD命令行称为:

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 

而且也从标准的命令提示符工作:

C:\> ps4 notepad; notepad 

This post描述办法做到Add-Type一个明确的路径(参考4.0需要来自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" 

这样的作品,即使在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在一个标准的命令提示符(误差完全在后的底部)启动失败
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" 

如果您更改执行策略,以RemoteSignedUnrestricted,改变默认的处理程序.ps1文件,你甚至可以运行这样的脚本:

zip.ps1 -Path "C:\x\xl" -Zipfile "C:\x\xl.zip" 
+0

真棒!你的解决方案有效:逃避双引号,或使用单打。虽然我想用一个适当的脚本,但我不明白我能做什么。我的用例是:我必须用VB的单个语句执行整个过程。我假设如果我在多个语句中调用PS4.cmd,它们将是独立的会话:在一次调用中添加程序集将无法连接到后续调用。此外,我必须将这些命令嵌入到VB代码中,因此使用';'链接它们似乎比在VB中嵌入脚本更方便,将脚本保存为批处理文件,然后执行该脚本 - 但我欢迎提供建议。谢谢! –

+0

我把你的答案链接到这里:http://stackoverflow.com/a/39800779/209942 –