ChatGPT解决这个技术问题 Extra ChatGPT

在 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 窗口?


m
mjolinor

尝试这个:

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

或者

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

我必须传递 -Force 参数才能使其工作,例如 Write-Host ($obj | Format-List -Force | Out-String)
啊!它仍然在屏幕上水平显示....如果任何输出超出您的缓冲区,它只会放置 ...。我对 POSH 爱恨交加
使用 $objs = @();$objs = $objs + $obj; 我可以使用 ConvertTo-Html$cols = $objs | ConvertTo-Html -Fragment -Property Name, DataType, Default, Identity, InPrimaryKey, IsForeignKey, Description;
这也非常适合调试目的,使用 Write-Debug ($obj | Format-Table | Out-String) :)
D
David Peters

我对这个问题的解决方案是使用 $() sub-expression block

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

c
cateyes

在 Powershell 中打印出对象的属性和值。低于 examples 对我来说效果很好。

$pool = Get-Item "IIS:\AppPools.NET v4.5"

$池 |获取会员

   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()
...

$池 | 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
...

最后一个变体最适合我 - 甚至可以将其缩短为 $x | select *,非常适合交互。
如果想将其放入脚本中,我认为这不起作用。如果是这样,我认为您必须做一些额外的事情才能将其实际打印到控制台(即:Write-Output
E
E.V.I.L.

Tip #1

永远不要使用写主机。

Tip #12

从 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。


谢谢鲍勃,我已经接受了 mjolinor 的回答,因为我觉得它更直接地回答了这个问题,但是我从您提供的链接中学到了很多,并同意在大多数情况下 Write-Host 不适合。谢谢!
相同的技术将起作用,并且可能更适合与 Write-Verbose 或 Write-Debug 一起使用。
我知道,我迟到了很多年,但我不同意 Never use Write-Host. 的说法。你不能在返回数据的函数中使用 Write-Output,因为它会“污染”这个函数。简单的例子。猜猜 ReturnText 函数会输出什么?这就是为什么我总是在函数内部使用 Write-host。 function ReturnText(){ Write-Output "Some random message" return "What I want to return" }
@DenisMolodtsov 我完全同意。出于记录信息的目的,除非函数是微不足道的,否则永远不应使用 Write-Output。一旦有多个功能级别并且您需要返回输出,您必须使用其他东西,并且 Write-Host 符合要求。
Write-Host 也将立即从远程会话返回,允许您查看进度,并且如果远程会话抛出错误,Write-Output 信息将丢失。
Y
YenForYang

一些一般性说明。

$obj |选择对象⊆ $obj |选择对象-属性 *

后者将显示 all 非内在、非编译器生成的属性。前者确实 not 似乎(总是)显示 all 属性类型(在我的测试中,它似乎确实始终显示 CodeProperty MemberType - 不能保证这里)。

Get-Member 需要注意的一些开关

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) ...

使用 -Force。 Get-Member 命令使用 Force 参数将对象的内在成员和编译器生成的成员添加到显示中。 Get-Member 获取这些成员,但默认情况下会隐藏它们。 PS Y:\Power> $obj | Get-Member -Static TypeName: System.IsFire.TurnUpProtocol Name MemberType Definition ---- ---------- ---------- ... pstypenames CodeProperty System.Collections.ObjectModel。集合... psadapted MemberSet psadapted {AccessRightType, AccessRuleType,... ...

使用 ConvertTo-Json 进行深度和可读的“序列化”

我确实推荐使用 JSON 保存对象(改用 Export-Clixml)。但是,您可以从 ConvertTo-Json 获得或多或少可读的输出,它还允许您指定深度。

请注意,不指定 Depth 意味着 -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(NB 为每个 TypeNamenot 为每个对象 - N 个对象的集合,所有相同的 TypeName 只会为该 TypeName 打印 1 个表,而不是每个对象的 N 个表)......只需坚持直接用管道输入。


F
Fractal

下面的工作对我来说真的很好。我将上述所有答案拼凑在一起,并在以下链接中阅读了有关显示对象属性的内容,并提出了以下short read about printing objects

将以下文本添加到名为 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”替换为您想要打印的任何对象。如果对象为空,则不会打印任何内容。


R
Ramanujam Allam
# Json to object
$obj = $obj | ConvertFrom-Json
Write-host $obj.PropertyName