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
987   2  

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

    Ничего не найдено.