Друк властивостей об'єкта в Powershell


120

Під час роботи в інтерактивній консолі, якщо я визначаю новий об'єкт і присвоюю йому деякі значення властивостей так:

$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?

Відповіді:


187

Спробуйте це:

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

або

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

4
Мені довелося передати -Forceпараметр, щоб він працював, наприкладWrite-Host ($obj | Format-List -Force | Out-String)
Барт Веркойейн

1
Тьфу! Він все ще відображається горизонтально на екрані .... якщо будь-який вихід виходить за межі вашого буфера, він просто ставить .... У мене ненависть до
POSH

Використання $objs = @();і $objs = $objs + $obj; я можу використовувати ConvertTo-Html: $ cols = $ objs | ConvertTo-Html -Fragment-Назва власності, DataType, Типовий, Ідентичність, InPrimaryKey, IsForeignKey, Опис;
Кікенет

33

Моє рішення цієї проблеми полягало у використанні блоку суб-вирази $ () .

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

16

Щоб роздрукувати властивості та значення об'єкта в Powershell. Нижче приклади добре працюють для мене.

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

$ пул | 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()
...

$ пул | 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
...

1
Останній варіант цього працював для мене найкраще - можна навіть скоротити його $x | select *, чудово підходить для інтерактивності.
Проігноровано

Я не думаю, що це спрацьовує, якщо хочете помістити його в сценарій. Якщо так, я думаю, що вам доведеться зробити щось додаткове, ніж те, що зазначено для того, щоб насправді надрукувати його на консоль (тобто: Write-Output <something-something>)
Фрактал

11

Порада №1

Ніколи не використовуйте Write-Host.

Порада №12

Правильний спосіб вивести інформацію з командлета PowerShell або функції - створити об’єкт, який містить ваші дані, а потім записати цей об’єкт у конвеєр, використовуючи Write-Output.

-Дон Джонс: майстер PowerShell

В ідеалі ваш сценарій створив би ваші об’єкти ( $obj = New-Object -TypeName psobject -Property @{'SomeProperty'='Test'}), тоді просто зробіть Write-Output $objects. Ви б передали вихід на Format-Table.

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

Вони дійсно повинні називати PowerShell PowerObjectandPipingShell.


4
Дякую Боб, я прийняв відповідь mjolinor, оскільки я вважаю, що це відповідає безпосередньо на питання, однак я багато чого дізнався із наданих вами посилань і погоджуюся, що в більшості випадків Write-Host не підходить. Дякую!
Джон

1
Ця ж техніка спрацює, і, ймовірно, буде більш підходящою для використання з Write-Verbose або Write-Debug.
mjolinor

4
Я знаю, я запізнююсь на багато років, але я не згоден з Never use Write-Host.твердженням. Ви не можете використовувати функцію Write-Output всередині функцій, які повертають дані, оскільки це "забруднить" цю функцію. Простий приклад. Здогадайтесь, яку функцію ReturnText виведе? Ось чому я завжди використовую функції запису-хоста всередині. функція ReturnText () {Write-Output "Деякі випадкові повідомлення" return "Що я хочу повернути"}
Денис Молодцов

3
@DenisMolodtsov Я повністю згоден. З метою реєстрації інформації реєстрації НІКОЛИ не слід використовувати, якщо функція не є тривіальною. Після того, як є кілька функціональних рівнів, і вам потрібно повернути вихід, ОБОВ'ЯЗКОВО використовувати щось інше, і Write-Host відповідає рахунку.
RobG

2
Хост Write також буде негайно скерований назад з віддаленого сеансу, що дозволяє вам бачити прогрес, і якщо віддалений сеанс видає помилку, інформація про виведення запису втрачається.
RobG

3

Деякі загальні примітки.


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

Останній покаже всі властивості, не створені компілятором. Колишній зовсім НЕ по всій видимості (завжди) показати всі типи об'єктів (в моїх тестах, він з'являється , щоб показати 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.Collection...
    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
...

Якщо ви хочете Get-Memberдля кожного TypeNameз колекції (NB для кожного TypeName, а не для кожного об'єкта - колекція з N об'єктів з усіма однаковими TypeNameбуде друкувати лише 1 таблицю для цього TypeName, а не N таблиць для кожного об'єкта) ...... просто дотримуйтесь її трубопроводу безпосередньо.


1

Нижче працювало дуже добре для мене. Я скріпив усі вищевказані відповіді, а також прочитав про відображення властивостей об'єкта за наступним посиланням і придумав нижче коротке прочитання про друк об'єктів

додати наступний текст у файл з назвою 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" будь-яким об'єктом, який ви хотіли надрукувати. Якщо об’єкт недійсний, нічого не буде роздруковано.


Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.