在 Powershell 打印对象属性

在交互式控制台中工作时,如果我定义一个新对象并像下面这样给它赋一些属性值:

$obj = New-Object System.String
$obj | Add-Member NoteProperty SomeProperty "Test"

然后,当我在交互式窗口中键入变量的名称时,Powershell 会给我一个对象属性和值的摘要:

PS C:\demo> $obj
SomeProperty
------------
Test

我基本上只是想这样做,但从一个脚本中的函数。该函数创建一个对象并设置一些属性值,我希望它在返回之前将对象值的摘要打印到 Powershell 窗口。我尝试在函数中使用 Write-Host:

Write-Host $obj

但这只是输出对象的类型,而不是摘要:

System.Object

我如何让我的函数输出一个对象的属性值的摘要到 Powershell 窗口?

235609 次浏览

试试这个:

Write-Host ($obj | Format-Table | Out-String)

或者

Write-Host ($obj | Format-List | Out-String)

第一招

永远不要使用写主机。

第十二招

从 PowerShell cmdlet 或函数输出信息的正确方法是创建一个包含数据的对象,然后使用 Write-Output 将该对象写入管道。

- Don Jones: PowerShell Master

理想情况下,你的脚本会创建你的对象($obj = New-Object -TypeName psobject -Property @{'SomeProperty'='Test'}) ,然后只做一个 Write-Output $objects。你会管道输出到 Format-Table

PS C:\> Run-MyScript.ps1 | Format-Table

他们真的应该调用 PowerShell PowerObjectandPipingShell。

我对这个问题的解决方案是使用 $()子表达式块

Add-Type -Language CSharp @"
public class Thing{
public string Name;
}
"@;


$x = New-Object Thing


$x.Name = "Bill"


Write-Output "My name is $($x.Name)"
Write-Output "This won't work right: $x.Name"

给予:

My name is Bill
This won't work right: Thing.Name

打印出物体在 Powershell 的属性和价值。

$pool = Get-Item“ IIS: AppPools.NET v4.5”

$pool | Get-Member

   TypeName: Microsoft.IIs.PowerShell.Framework.ConfigurationElement#system.applicationHost/applicationPools#add


Name                        MemberType            Definition
----                        ----------            ----------
Recycle                     CodeMethod            void Recycle()
Start                       CodeMethod            void Start()
Stop                        CodeMethod            void Stop()
applicationPoolSid          CodeProperty          Microsoft.IIs.PowerShell.Framework.CodeProperty
state                       CodeProperty          Microsoft.IIs.PowerShell.Framework.CodeProperty
ClearLocalData              Method                void ClearLocalData()
Copy                        Method                void Copy(Microsoft.IIs.PowerShell.Framework.ConfigurationElement ...
Delete                      Method                void Delete()
...

$pool | Select-Object-Property * # 可以省略-Property

name                        : .NET v4.5
queueLength                 : 1000
autoStart                   : True
enable32BitAppOnWin64       : False
managedRuntimeVersion       : v4.0
managedRuntimeLoader        : webengine4.dll
enableConfigurationOverride : True
managedPipelineMode         : Integrated
CLRConfigFile               :
passAnonymousToken          : True
startMode                   : OnDemand
state                       : Started
applicationPoolSid          : S-1-5-82-271721585-897601226-2024613209-625570482-296978595
processModel                : Microsoft.IIs.PowerShell.Framework.ConfigurationElement
...
# Json to object
$obj = $obj | ConvertFrom-Json
Write-host $obj.PropertyName

下面的内容对我很有帮助。我把以上所有的答案拼凑在一起,加上在下面的链接中阅读关于显示对象属性的内容,得出了下面的结论 关于打印对象的简短阅读

将以下文本添加到名为 print _ object. ps1的文件中:

$date = New-Object System.DateTime
Write-Output $date | Get-Member
Write-Output $date | Select-Object -Property *

打开 powershell 命令提示符,转到该文件所在的目录并键入以下内容:

powershell -ExecutionPolicy ByPass -File is_port_in_use.ps1 -Elevated

只需将“ System.DateTime”替换为您想要打印的任何对象。如果该对象为 null,则不会打印出任何内容。

一些大概的注释。


$obj | Select-Object Something $obj | Select-Object -Property *

后者将显示 所有非内部的、非编译器生成的属性。前者似乎(总是)显示 所有属性类型(在我的测试中,它似乎始终如一地显示 CodeProperty MemberType——这里没有保证)。


记住需要注意的一些开关

  • Get-Member默认情况下 没有获得静态成员。你也可以 不能(直接)得到它们 还有的非静态成员。也就是说,使用开关只会返回静态成员:

    PS Y:\Power> $obj | Get-Member -Static
    
    
    TypeName: System.IsFire.TurnUpProtocol
    
    
    Name        MemberType Definition
    ----        ---------- ----------
    Equals      Method     static bool Equals(System.Object objA, System.Object objB)
    ...
    
  • Use the -Force.

    The Get-Member command uses the Force parameter to add the intrinsic members and compiler-generated members of the objects to the display. Get-Member gets these members, but it hides them by default.

    PS Y:\Power> $obj | Get-Member -Static
    
    
    TypeName: System.IsFire.TurnUpProtocol
    
    
    Name          MemberType     Definition
    ----          ----------     ----------
    ...
    pstypenames   CodeProperty   System.Collections.ObjectModel.Collection...
    psadapted     MemberSet      psadapted {AccessRightType, AccessRuleType,...
    ...
    

Use ConvertTo-Json for depth and readable "serialization"

I do not necessary recommend saving objects using JSON (use Export-Clixml instead). However, you can get a more or less readable output from ConvertTo-Json, which also allows you to specify depth.

Note that not specifying Depth implies -Depth 2

PS Y:\Power> ConvertTo-Json $obj -Depth 1
{
"AllowSystemOverload":  true,
"AllowLifeToGetInTheWay":  false,
"CantAnyMore": true,
"LastResortOnly": true,
...

如果你不打算读它,你可以 -Compress它(即带空格)

PS Y:\Power> ConvertTo-Json $obj -Depth 420 -Compress

如果可以(并且愿意) ,请使用 -InputObject

99.9% 的情况下使用 PowerShell: 要么性能不重要,要么不在乎性能。值得注意的是,在不需要管道的情况下避免使用管道可以节省一些开销,增加一些速度(一般来说,管道并不是超级有效的)。

也就是说,如果你只有一个便于打印的 $obj(并且不像我有时候那样懒得打出 -InputObject) :

# select is aliased (hardcoded) to Select-Object
PS Y:\Power> select -Property * -InputObject $obj
# gm is aliased (hardcoded) to Get-Member
PS Y:\Power> gm -Force -InputObject $obj

Get-Member -InputObject的警告: 如果 $obj 是 收藏品(例如 System.Object[]) ,那么您最终将获得有关集合对象本身的信息:

PS Y:\Power> gm -InputObject $obj,$obj2
TypeName: System.Object[]


Name        MemberType            Definition
----        ----------            ----------
Count       AliasProperty         Count = Length
...

如果你想为集合中的每个 TypeName打印 Get-Member(注意,为每个 TypeName打印 Get-Member,为每个对象打印 没有——具有所有相同 TypeName的 N 个对象的集合只会为该 TypeName打印1个表,而不是为每个对象打印 N 个表) ... ... 只要坚持直接通过管道输入就可以了。