我正在编写一个脚本,试图输出两个不同的自定义对象;一个接一个地遇到问题,所以为了简化,我把所有的代码都精简到了最低限度:
$beep = new-object -TypeName PSObject
$beep | Add-Member -MemberType NoteProperty -Name "Entry1" -Value "beep1"
$beep | Add-Member -MemberType NoteProperty -Name "Entry2" -Value "beep1"
$beep
$boop = new-object -TypeName PSObject
$boop | Add-Member -MemberType NoteProperty -Name "Entry1" -Value "boop1"
$boop | Add-Member -MemberType NoteProperty -Name "Entry2" -Value "boop1"
$boop
Run Code Online (Sandbox Code Playgroud)
当我运行它时,对象似乎组合在一起。当我做一个 get-member 时,它似乎只显示一个对象。为什么?
在我实际尝试完成的代码中,一个对象是上面的自定义对象,但另一个是 selected.system.int32。当我尝试一个接一个地输出时,只有第一个输出。如果我翻转订单;同样的事情,第一个对象得到输出。我做错了什么/不明白?
@JamesQ - 我想让我感到困惑的是当我这样做时:
$beep = new-object -TypeName PSObject
$beep | Add-Member -MemberType NoteProperty -Name "Entry1" -Value "beep1"
$beep | Add-Member -MemberType NoteProperty -Name "Entry2" -Value "beep1"
$beep | get-member
$boop = new-object -TypeName PSObject
$boop | Add-Member -MemberType NoteProperty -Name "Entry1" -Value "boop1"
$boop | Add-Member -MemberType NoteProperty -Name "Entry2" -Value "boop1"
$boop | get-member
Run Code Online (Sandbox Code Playgroud)
我得到:
TypeName: System.Management.Automation.PSCustomObject
Name MemberType Definition
---- ---------- ----------
Equals Method bool Equals(System.Object obj)
GetHashCode Method int GetHashCode()
GetType Method type GetType()
ToString Method string ToString()
Entry1 NoteProperty System.String Entry1=beep1
Entry2 NoteProperty System.String Entry2=beep1
Equals Method bool Equals(System.Object obj)
GetHashCode Method int GetHashCode()
GetType Method type GetType()
ToString Method string ToString()
Entry1 NoteProperty System.String Entry1=boop1
Entry2 NoteProperty System.String Entry2=boop1
Run Code Online (Sandbox Code Playgroud)
我试图让问题保持简单,但我认为我把它说得太含糊了,所以......
我正在尝试重用一些代码:
function Get-NetworkConfig($computerName) {
Get-WmiObject Win32_NetworkAdapter -Filter 'NetConnectionStatus=2' |
ForEach-Object {
$result = 1 | Select-Object Name, IP, MAC
$result.Name = $_.Name
$result.MAC = $_.MacAddress
$config = $_.GetRelated('Win32_NetworkAdapterConfiguration')
$result.IP = $config | Select-Object -expand IPAddress
$result
}
}
Run Code Online (Sandbox Code Playgroud)
然后在同一个脚本中类似:
function Get-ComputerInfo($computerName) {
$operatingSystem = Get-WMIObject -computername $computerName win32_operatingsystem
$computerInfo = new-object -TypeName PSObject
$computerInfo | Add-Member -MemberType NoteProperty -Name "Computer Name" -Value ("$computerName")
$computerInfo | Add-Member -MemberType NoteProperty -Name "Operating System" -Value ("$operatingSystem.Caption")
$computerInfo
}
$computerNames = $args
foreach ($computerName in $computerNames) {
Get-ComputerInfo($computerName)
Get-NetworkConfig($computerName)
}
Run Code Online (Sandbox Code Playgroud)
只显示 get-computerinfo 的输出,然后是一堆空行,其中 get-networkconfig 将有输出。
如果我颠倒顺序;只有第一个函数给出输出,第二个函数只输出空行。
为什么我不能像这样按顺序调用两个函数?
当我执行 a 时
Get-Member
,它似乎只显示一个对象。
Get-Member
显示有关输入集合中不同类型的信息,这意味着报告每种类型的第一次出现,并跳过后续出现。
在您的情况下,两个输入对象都是 type [System.Management.Automation.PSCustomObject]
,因此Get-Member
将仅报告一种共享类型。
例如,1, 2 | Get-Member
报告有关System.Int32
once 的信息。
一个对象是上面的自定义对象,但另一个是 selected.system.int32。当我尝试一个接一个地输出时,只有第一个输出。
PowerShell 的默认输出格式默认为隐式使用,Format-Table
用于最多具有 4 个属性的自定义对象。
如果您输出具有不同类型的多个对象,并且第一个对象默认为隐式Format-Table
输出,则第一个对象的类型将单独确定要在结果表中显示的属性(列)。
Get-FormatData
),后续对象会打印,尽管总是通过隐式Format-List
格式设置。如果后续对象没有第一个对象具有的任何相同属性,则它们只需打印一个空行;如果它们具有某些相同的属性,则仅打印它们;任何附加属性都将被忽略。
需要注意的是,这只是一个显示问题,但是:输出的所有对象仍然存在;如果您将输出发送到另一个命令进行进一步处理而不是直接发送到控制台,它们都会在那里。
一个简单的例子:
PS> [pscustomobject] @{ one = 1; two = 2 }, [pscustomobject] @{ three = 3 }
one two
--- ---
1 2
Run Code Online (Sandbox Code Playgroud)
请注意第二个自定义对象是如何产生一个空行的,因为它既没有属性.one
也没有.two
.
您可以通过使用应用于每个对象的显式格式化命令来解决这个问题:
PS> [pscustomobject] @{ one = 1; two = 2 }, [pscustomobject] @{ three = 3 } |
ForEach-Object { Format-Table -InputObject $_ }
one two
--- ---
1 2
three
-----
3
Run Code Online (Sandbox Code Playgroud)
与单个输出命令相同的方法:
[pscustomobject] @{ one = 1; two = 2 } | Format-Table
[pscustomobject] @{ three = 3 } | Format-Table
Run Code Online (Sandbox Code Playgroud)
正如Mark Wragg 的博客文章所解释的那样,给定脚本生成的所有输出——即使是跨单独的命令——都被发送到同一个管道。
(您可以将交互式提交的命令行视为隐式脚本。)
有关如何根据显示格式处理单个管道中的混合类型的更详细讨论,请参阅此答案。
为什么使用显式格式化命令有帮助:
通过显式管道到Format-*
cmdlet(例如,[pscustomobject] @{ one = 1; two = 2 } | Format-Table
),您实际上是将格式化对象([Microsoft.PowerShell.Commands.Internal.Format.*]
各种类型)发送到管道,然后 PowerShell 有效地传递它们以进行显示。
另一种方法是使用通用的解决方法:如果您改为使用管道Out-Host
(例如,[pscustomobject] @{ one = 1; two = 2 } | Out-Host
),在这种情况下:
需要注意的是,这些变通方法仅适用于显示目的,因为原始对象在此过程中丢失了:
当您Format-*
显式地通过管道传输到cmdlet 时,您将使用包含格式说明的对象替换原始对象,这些对象对于进一步处理毫无用处。
当您通过管道传输到 时Out-Host
,您不会向脚本的管道发送任何内容。
归档时间: |
|
查看次数: |
1125 次 |
最近记录: |