Powershell echo与写入主机和不同的输出

Powershell echo与写入主机和不同的输出,powershell,Powershell,我正在尝试编写我的第一个脚本,但是powershell出现了一些问题 我正在使用以下代码: $Disk = Get-Disk | Where-Object {$_.Path -match "USBSTOR" -and $_.Size -gt 20Gb -and $_.Size -lt 200Gb -and -not $_.IsBoot } 我不明白为什么 PS C:\> echo $disk Number Friendly Name

我正在尝试编写我的第一个脚本,但是powershell出现了一些问题

我正在使用以下代码:

$Disk = Get-Disk | Where-Object {$_.Path -match "USBSTOR" -and $_.Size -gt 20Gb -and $_.Size -lt 200Gb -and -not $_.IsBoot }
我不明白为什么

PS C:\> echo $disk
Number Friendly Name                            OperationalStatus                    Total Size Partition Style
 ------ -------------                            -----------------                    ---------- ---------------
1      Imation IronKey Wkspace USB Device       Online                                 59.63 GB MBR

下面的powershell脚本更为复杂:

$Disk = Get-Disk | Where-Object {$_.Path -match "USBSTOR" -and $_.Size -gt 20Gb -and $_.Size -lt 200Gb -and -not $_.IsBoot }
$WIM = Get-PSDrive -PSProvider FileSystem | Where { Test-Path (join-path $_.Root "\sources\install.wim") }
echo $Disk
echo $WIM
Write-Host $WIM
Write-Host $Disk
然后改变回音和写入的顺序,我得到不同的输出


有人能解释一下发生了什么吗?

在PowerShell中,
echo
映射到主机,而不是写入主机。如果要输出某个操作产生的对象,则应该输出它们,而不是尝试
写入主机
。通过
Write Host
写入的内容不会进入输出流,因此(例如)您不能在后续调用或管道中使用它

您会看到
Write Host
的输出乱七八糟,因为它试图写出整个对象,并且不明白您可能更喜欢一个具有清晰列出的属性的好表。您应该保留
Write Host
,当您需要向用户传达一些简单的信息时,您不介意被使用,即使这样,也可能有更好的选择,如或

更多信息

通过使用
帮助
获取帮助
调用cmdlet,始终可以检查这样的映射:

PS C:\> help echo

NAME
    Write-Output

Write Host
cmdlet将输出到主机(即powershell或ISE窗口)。它接受一个对象作为输入,只调用对象的
.ToString()
方法(或者如果它是一个数组,则调用
.ToString()
或数组的每个元素)

Write Output
或其别名
echo
只需将输入对象写入当前管道。到达管道末端的任何对象都会从当前函数、cmdlet或脚本(如果有)返回(然后它们可以继续沿着其他管道)。最终,对象可能会到达不在函数、cmdlet或脚本内的管道的末端,看起来它们是输出到主机的。实际发生的情况是,在最外层管道的末端,所有对象都会发送到一个额外隐藏的cmdlet:
Out Default

Out Default
将对象发送到默认格式化程序,然后发送到默认输出cmdlet。默认格式化程序将磁盘对象转换为一组
FormatStartData
GroupStartData
FormatEntryData
GroupEndData
FormatEndData
对象(将类似
Format Table
的输出导入
Get Member
以查看这些对象)。最后,格式对象被发送到主机以生成格式化输出

如果您想玩得开心,请尝试重新定义
出默认值
,以便查看其调用位置:

PS C:\scripts> function Out-Default {
>>   Write-Verbose "Called Out-Default" -Verbose
>>   $input | Format-Table | Out-Host
>> }
>>
PS C:\scripts> cd mod2
VERBOSE: Called Out-Default
PS C:\scripts\mod2> ls
VERBOSE: Called Out-Default


    Directory: C:\scripts\mod2


Mode                LastWriteTime     Length Name
----                -------------     ------ ----
-a---        29/12/2013     11:00        308 1Var.ps1
-a---        29/12/2013     11:00        326 2Quotes.ps1
-a---        29/12/2013     11:00        416 3ObjectMembers.ps1
-a---        29/12/2013     11:00        665 4Parenthesis.ps1
-a---        29/12/2013     11:00        392 5If.ps1
-a---        29/12/2013     11:00        325 6Switch.ps1
-a---        29/12/2013     11:00        226 7Do_While.ps1
-a---        29/12/2013     11:00        272 8For_Foreach.ps1
-a---        29/12/2013     11:00        150 _Startup.ps1

这有助于解释问题。但您能解释为什么更改回声的顺序很重要吗?如果我在命令行上执行最终脚本,它会按预期工作(两个回声都是表)。如果我将其放入powershell脚本中,第一个回声是表,最后一个回声是完整对象。如果我切换它们,输出结果是相同的(表,对象)。
PS C:\scripts> function Out-Default {
>>   Write-Verbose "Called Out-Default" -Verbose
>>   $input | Format-Table | Out-Host
>> }
>>
PS C:\scripts> cd mod2
VERBOSE: Called Out-Default
PS C:\scripts\mod2> ls
VERBOSE: Called Out-Default


    Directory: C:\scripts\mod2


Mode                LastWriteTime     Length Name
----                -------------     ------ ----
-a---        29/12/2013     11:00        308 1Var.ps1
-a---        29/12/2013     11:00        326 2Quotes.ps1
-a---        29/12/2013     11:00        416 3ObjectMembers.ps1
-a---        29/12/2013     11:00        665 4Parenthesis.ps1
-a---        29/12/2013     11:00        392 5If.ps1
-a---        29/12/2013     11:00        325 6Switch.ps1
-a---        29/12/2013     11:00        226 7Do_While.ps1
-a---        29/12/2013     11:00        272 8For_Foreach.ps1
-a---        29/12/2013     11:00        150 _Startup.ps1