Powershell: экспорт свойства с хэш-таблицей в CSV-файл
Я управляю Test-AdfsServerHealth (Ref.)
Проблема в том, что одно из выходных значений (имя значения
Output) - это массив, который отображается как System.Collection.Hashtable, и я пытаюсь найти способ получить его в аккуратном формате Excel.Например, это одно из фактических значений в CSV при экспорте:
Name Result Detail Output
TestServiceAccountProperties Pass "" System.Collections.Hashtable
Но PowerShell отображает:
Name : TestServiceAccountProperties
Result : Pass
Detail :
Output : {AdfsServiceAccount, AdfsServiceAccountDisabled, AdfsServiceAccountLockedOut,
AdfsServiceAccountPwdExpired...}
ExceptionMessage :
Фактическая команда, которую я выполняю:
$ServerResult = Test-AdfsServerHealth
2 ответов:
Tl; dr :
Вышеизложенное сериализует каждую запись хеш-таблицыTest-AdfsServerHealth | Select-Object Name, Result, Detail, @{ n='Output' e={ $_.prop2.GetEnumerator().ForEach({ '{0}={1}' -f $_.Key, $_.Value }) -join ' ' } } | ExportTo-Csv out.csv.Outputв однострочную строку, состоящую из разделенных пробелами пар<key>=<value>(синтаксис PSv4+), которые должны достаточно хорошо работать в выводе CSV.
Поскольку CSV является форматом text , PowerShell сериализует экспортируемые объекты, вызывая их метод
.ToString().Сложные объекты, такие как экземпляры
[hashtable], часто дают только полное имя типа (System.Collections.Hashtable) для.ToString(), который не полезен в CSV.Упрощенный пример (я использую
ConvertTo-Csv, но пример аналогично применяется кExport-Csv):# Create a custom object whose .col2 property is a hashtable with 2 # sample entries and convert it to CSV PS> [pscustomobject] @{ prop1 = 1; Output = @{ name='foo'; ID=666 } } | ConvertTo-Csv "prop1","Output" "1","System.Collections.Hashtable"Если бы все выходные объекты из
Test-AdfsServerHealthимели одинаковую структуру хэш-таблицы в своем свойстве.Output, вы могли бы попытаться сгладить хэш-таблицу, сделав ее столбцы записей в своем собственном праве, но похоже, что это не так.Поэтому вы должны вручную преобразовать хэш-таблицу в текст представление, которое помещается в один столбец CSV :
Вы можете сделать это с помощью
Select-Objectи вычисляемого свойства, которое выполняет преобразование для вас, но вам нужно решить, какое текстовое представление имеет смысл в контексте CSV-файла.В следующем примере создается однострочная строка, состоящая из пар
<key>=<value>, разделенных пробелами (синтаксис PSv4+).[pscustomobject] @{ prop1 = 1; Output = @{ name='foo'; ID=666 } } | Select-Object prop1, @{ n='Output' e={ $_.prop2.GetEnumerator().ForEach({ '{0}={1}' -f $_.Key, $_.Value }) -join ' ' } } | ConvertTo-Csvдля объяснения формата хэш-таблицы, который создает вычисляемый Свойство
prop2, смотрите этот мой ответ.Вышеприведенные результаты:
Однако обратите внимание, что если значения в ваших хэштабах снова являются сложными объектами, которые сериализуются только по имени типа, вам придется применить подход рекурсивно."prop1","prop2" "1","ID=666 name=foo"
Необязательное чтение: сглаживание свойства hashtable в отдельные столбцы
Если свойства объектов для экспорта в CSV-файл с хэш-таблицей имеют одинаковое значение структура , Вы можете выбрать сделать записи хэш-таблицы каждый свой собственный выходной столбец.
Возьмем следующий пример ввода: набор из 2 пользовательских объектов, значение которых
.prop2является хэш-таблицей с единым набором ключей (записей):$coll = [pscustomobject] @{ prop1 = 1; prop2 = @{ name='foo1'; ID=666 } }, [pscustomobject] @{ prop1 = 2; prop2 = @{ name='foo2'; ID=667 } }Если вы заранее знаете имена ключей (представляющих интерес), вы можете просто использовать явный список вычисляемых свойств для создания отдельных столбцов :
$coll | select prop1, @{ n='name'; e={ $_.prop2.name } }, @{ n='ID'; e={ $_.prop2.ID } } | ConvertTo-CsvВышеизложенное дает следующее, показывая что записи хэш-таблицы стали их собственными столбцами,
nameиID:"prop1","name","ID" "1","foo1","666" "2","foo2","667"Требуются более продвинутые методы , если вы Не знаете имена ключей заранее :
# Create the list of calculated properties dynamically, from the 1st input # object's .prop2 hashtable. $propList = foreach ($key in $coll[0].prop2.Keys) { # The script block for the calculated property must be created from a # *string* in this case, so we can "bake" the key name into it. @{ n=$key; e=[scriptblock]::Create("`$_.prop2.$key") } } $coll | Select-Object (, 'prop1' + $propList) | ConvertTo-CsvЭто дает тот же результат, что и предыдущая команда с фиксированным списком вычисляемых свойств.
Это не будет существенно сложно,просто будет раздражать. Причина, по которой вы получаете "систему.коллекции.hashtable " является потому, что не может отображать все в этом свойстве в одном формате, как это, есть способ много информации. Вам придется создать другой объект и поместить туда любую информацию, которую вы хотите.
Эта проблема не будет работать точно так, как вы хотите, но с некоторыми настройками она должна привести вас туда.
$ServerResult = Test-ADFSServerHealth $Object = New-PSObject -Property @{ 'Name' = $ServerResult.name 'Result' = $ServerResult.Result 'Detail' = $ServerResult.Detail 'Output' = ($ServerResult.Output | out-string -stream) 'ExceptionMessage' = $ServerResult.ExceptionMessage }Если вам интересно, вот ресурсы, которые я использовал, чтобы найти этот ответ.
преобразование хэш-таблицы в массив strings
https://devops-collective-inc.gitbooks.io/the-big-book-of-powershell-gotchas/content/manuscript/new-object_psobject_vs_pscustomobject.html
Comments