当多个命令在脚本

时间:2015-07-15 21:03:49

标签: powershell select output

我遇到了PowerShell脚本的问题我失去了"输出到控制台或被重定向的输出。经过大量的工作后,我将其简化为一个容易记录的问题示例。

将以下单行放在脚本(test1.ps1)中,并从基本的PowerShell命令窗口调用它:

Get-WmiObject win32_share  | select name, path

您可能会得到两列类似于以下内容的输出:

PS C:\Users\me\temp> ./test1.ps1

name                                    path
----                                    ----
ADMIN$                                  C:\Windows
C$                                      C:\
IPC$
Users                                   C:\Users

但是现在,像这样创建一个两行脚本(test2.ps1),并以相同的方式运行它:

Get-WmiObject win32_share | select name
Get-WmiObject win32_share | select name, path

并观察输出是否被破坏:

PS C:\Users\me\temp> ./test2.ps1

name
----
ADMIN$
C$
IPC$
Users
ADMIN$
C$
IPC$
Users

这两个命令实际上是在运行,但是第二个调用得到了"压缩"进入第一个输出。它失去了第二列,它的标题和间距。

这似乎是"第一个"输出不正确"关闭",因为如果第二行输入另一个选择语句,它似乎并不重要。

顺便说一下,我的原始线条看起来更像是这样:

Get-WmiObject win32_share | select name, path | Write-Output
Get-WmiObject win32_share | select name | Write-Output

因此,在powershell提示符下,我可以使用重定向将输出定向到我想要的地方

PS C:\Users\me\temp\> ./test2.ps1 > ./outfile.txt

如上所述,实际情况比这更完整,但在这一点上,我只是想了解正在发生的事情。

错误?或者我不理解?

3 个答案:

答案 0 :(得分:1)

Get-WmiObject win32_share | select name | ft
Get-WmiObject win32_share | select name, path | ft


Get-WmiObject win32_share | ft name
Get-WmiObject win32_share | ft name, path

答案 1 :(得分:1)

link from mjolinor更详细地解释了它,但PowerShell正在尝试将输出组合在一起。来自帖子的重要一行说明:

  

如果第一个Object有2个属性,即使流中的所有其他对象都有10个属性,您也会获得2列表。

在以下示例中

Get-WmiObject win32_share | select name
Get-WmiObject win32_share | select name, path

当seconds命令运行时,前一个输出没有该属性,因此PowerShell,更具体地说Out-Default将其丢弃在输出中,以使所有输出同步。

我会更好奇你真正的代码是什么造成了这个问题。与expirat001类似,您可以将输出转换为字符串,这不会发生,因为它们不再是对象。小心这样做,因为你可以这样丢失原始对象。无论哪种方式,数据都不会丢失。只是没有按照你期望的方式展示。

回顾前面的例子,我们可以假装第一行没有路径属性。无论如何从select调用它只会创建空列但允许显示其他输出。

# In this next command "path" is not a valid property but PowerShell will create the column anyway
Get-WmiObject win32_share | select name, path 
Get-WmiObject win32_share | select name, path

这是作弊但您可以将其中一个命令发送到不同的输出流。

Get-WmiObject win32_share | select name
Get-WmiObject win32_share | select name, path | Out-Host

答案 2 :(得分:1)

link from mjolinor确实解释了很多,这里的主要问题是您通过& ./test2.ps1启动脚本,命令的输出通过管道输入{{1 }}。反过来,Out-Default会看到由Out-Default cmdlet生成的一组PSObject,并检查第一个对象(这是Select-Object返回的第一个对象)它看到它只有一个属性“name”,然后从结果对象中格式化一个表,只收集所有属性中的Get-WmiObject win32_share | select name属性。

要规避,请使用nameft cmdlet将每行的输出转换为Format-Table s而不是String s的序列,这样当脚本的时候输出将通过管道输入PSObject,它将通过未处理的字符串传递字符串。