2016-10-21 2 views
3

Я заметил странное поведение при использовании заданий в PowerShell 5.0. Запуск задания, который возвращает PSObject, также возвращает некоторую хэш-таблицу. Работы, возвращающие строки, целые числа и т. Д., Работают нормально.Невыделенные результаты в получающем задании

Запуск

Start-Job { New-Object PSObject -Property @{ A = 1 } } | 
    Receive-Job -Wait -AutoRemoveJob 

возвращает

A      : 1 
RunspaceId   : 6921e85f-301e-4e95-8e4b-c0882fc2085f 
PSSourceJobInstanceId : 2992ef77-5642-4eac-8617-f26449a87801

Запуск

Start-Job { New-Object PSObject } | Receive-Job -Wait -AutoRemoveJob 

возвращается

@{PSComputerName=localhost; RunspaceId=3e783d5f-254a-4951-bb4a-7ff6fa2812c5; PSShowComputerName=False; PSSourceJobInstanceId=1d951dec-0823-4cde-8219-4a6263550441}

Однако запуск

Start-Job { ,@(New-Object PSObject -Property @{ A = 1 }) } | 
    Receive-Job -Wait -AutoRemoveJob 

возвращается

A 
- 
1

Почему Receive-Job Командлет добавить, что хэш-таблицу только для PSObject с?

ОБНОВЛЕНИЕ: То же самое в PowerShell 4.0.

+0

FWIW, он ведет себя так же для PSCustomObject: 'Start-Job {[PSCustomObject] @ {A = 1}} | Receive-Job -Wait -AutoRemoveJob' –

+0

@PetSerAl, я не понимал, что он также добавляет свойства примечаний к целым числам и строкам. Не могли бы вы написать это как ответ? – user175908

+0

@PetSerAl: Великие указатели, спасибо. Я не думаю, что '.ToString()' вызывается, однако (по крайней мере, не непосредственно на объекте), и есть 3 набора из 3-5 связанных с удалением свойств, которые запускают это форматирование (если они являются единственными свойства). Я опубликовал свои результаты в качестве ответа - пожалуйста, дайте мне знать, если у меня что-то не так. – mklement0

ответ

3

PowerShell не является оболочкой WYSIWYG. Обычно «то, что вы получаете» - это не текст, а объекты со свойствами и методами. И «то, что вы видите» - это некоторое текстовое представление. Во многих случаях по умолчанию PowerShell не отображает все свойства объекта, а только наиболее распространенные, как определено в файлах формата. И некоторые объекты используют собственное форматирование, например, строки и целые числа отображают только их ценность, но не любые его свойства, а коллекции отображают их содержимое, но не сами коллекции.

Итак, на самом деле PowerShell добавляет дополнительные свойства ко всем объектам, полученным с работы. Но это свойство не всегда отображается. Вы можете видеть, что дополнительные свойства путем пропускания выхода работы в Get-Member командлет:

Start-Job { 1,'',@() } | Receive-Job -Wait -AutoRemoveJob | Get-Member 

или форматирования командлет с соответствующими параметрами, чтобы заставить форматирование примитивных типов и не перечислить коллекции:

Start-Job { 1,'',@() } | Receive-Job -Wait -AutoRemoveJob | Format-List -Force -Expand CoreOnly 
2

Для комплементPetSerAl's excellent answer с сосредоточиться на хеш-таблица, которая не была (хеш-таблица), на основе полезных комментариев от пользователя PetSerAl:

Выход из Start-Job { New-Object PSObject } | Receive-Job -Wait -AutoRemoveJob,

@{PSComputerName=localhost; RunspaceId=3e783d5f-254a-4951-bb4a-7ff6fa2812c5; PSShowComputerName=False; PSSourceJobInstanceId=1d951dec-0823-4cde-8219-4a6263550441} 

только выглядит подобно Хеш буквальным; на самом деле, он выводится по умолчанию форматирование «собственности менее» пользовательских объектов, что, на самом деле, делать имеют свойства, но только те добавляют сам PowerShell.

Это представление подозрительно подобной к Хеш буквальным, но кавычки вокруг значений, которые обычно должны были бы его не хватает - например, вокруг localhost.
Также обратите внимание, что вывод фактического хеш-таблицы приводит к значительно более хорошему двухколоночному ключевому значению.

Обратите внимание, что PS до сих пор считает пользовательский объект, который первоначально имел никаких свойств собственности менее даже после того, как сам PS добавил свойства к нему, например, путем Receive-Job здесь - не смотри ниже для деталей.

В исходном состоянии (пока еще нет свойств, добавленных PS) объект по умолчанию не имеет значения по умолчанию: пусто (пустая строка). (Попробуйте New-Object PSCustomObject непосредственно в командной строке.)

После Receive-Job добавила свои «мета» свойства пользовательского объекта, их существование вызывает выход форматирования hashtable- как.


PetSerAl предоставил ссылку на source code, что говорит о том, что форматирование «PropertyLessObject» срабатывает при следующих условиях:

  • Объект не имеет свойств на всех или только имеет свойства, автоматически добавленные PowerShell в контексте удалением (который, по-видимому, также включает в себя job-связанных командлетов), как сделано Receive-Object здесь.

  • По-разному: свойства, автоматически добавленные PS, не учитываются при решении вопроса о том, является ли объект без собственности.

Ссылка исходного кода покажет вам конкретные наборы 3-, 4- или 5-элементных ремоутинга свойства, которые могут быть добавлены во время удаленного доступа и вызвать форматирование, но вот минимальный (3-недвижимость) пример.
Опять же, обратите внимание, что Хеш-как форматирование срабатывает только потому, что только свойства, что объект имеет названы для удаленного взаимодействия, связанные, автоматически добавляются свойства:

> [PSCustomObject] @{PSComputerName='Hi, Mom'; RunspaceId=0; PSShowComputerName=$false} 
@{PSComputerName=Hi, Mom; RunspaceId=0; PSShowComputerName=False} 

Обратите внимание, что даже если Хеш литерал в команде, она используется только для . Создает пользовательский объект.

Вы можете заставить нормальный список или вид таблицы с Format-List -Force или Format-Table -Force, но учтите, что логическое свойство PSShowComputerNameникогда показывает и вместо того, чтобы косвенно контролирует, является ли связанныйPSComputerName собственности, включенные в список/таблицы ,


PetSerAl также указывает на то, что вы можете получить hashtable- как выходной формат по требованию для любого пользовательского объекта: просто вызовите .PSObject.ToString() (обратите внимание на важную .PSObject часть, без него , вы получаете пусто выход).

> ([pscustomobject] @{ one = 'Hi, Mom'; two = 2 }).PSObject.ToString() 
@{one=Hi, Mom; two=2} 

Или, проще говоря, с интерполяции строк (который, по-видимому, просто вызывает .PSObject.ToString() за кадром):

> "$([pscustomobject] @{ one = 'Hi, Mom'; two = 2 })" 
@{one=Hi, Mom; two=2} 

Обратите внимание, что это делает не работу для случаев любой другие виды (объекты не, полученные от [System.Management.Automation.PSObject]):

  • PowerShell отказывается от своего метода .ToString(), даже если вы вызываете .PSObject.ToString().

  • пр мого .NET на основе типа (например, как добавленный с Add-Type) по умолчанию просто возвращает его полное имя типа (оба из .ToString()/.PSObject.ToString() и в качестве выходного сигнала по умолчанию в PS); например .:

    > (Add-Type -PassThru 'namespace net.same2u { public class SomeType {} }')::New() 
    net.same2u.SomeType # the full type name 
    
Смежные вопросы