Export-Csvすると値ではなくクラス名が出力される

概要

PowerShellのExport-Csvでデータを出力する時、対象のオブジェクトの中にオブジェクトが含まれていると展開されずにクラス名が出力されます。

オプションではどうしようもないので、New-Objectでエクスポートする用のオブジェクトを作ってExport-Csvに渡すとなんとかなります。

背景

Azure VMに付与されているタグ一覧をとりたいとのお話があり、そのままExport-Csvしたところ意図していない出力になりました。

Get-AzVM | Export-Csv -Encoding UTF8
PowerShellの出力ではタグ情報が見える
出力されたcsvではタグがクラス名になっている

やりかた

子オブジェクトのプロパティを参照してエクスポート用オブジェクトに入れて、それをExport-Csvに渡します。

function New-ExObject($obj){
  $new_obj = New-Object PSObject | Select-Object Name,ChildObjectPropety1;
  $new_obj.Name = $obj.Name;
  $new_obj.ChildObjectProperty1 = $obj.ChildObject.Property1;
  return $new_obj;
}
New-ExObject -obj $obj | Export-Csv -Path test.csv;

おまけ

背景のVMのタグ一覧の出力はこのようにしました。

# タグは辞書型なので文字列に変換する
function Convert-Hash-to-String($hash, $delimiter = ",", $end = "`n"){
  $str = "";
  foreach($key in $hash.Keys){
    $str += $key + $delimiter + $hash[$key] + $end;
  }
  return $str;
}

function New-VmInfoObject($vm){
  $new_obj = New-Object PSObject | Select-Object Name,Tags;
  $new_obj.Name = $vm.Name;
  # デリミタをカンマにするとcsvの区切りと被るのでコロンにする
  # タグが複数ある場合はセミコロンで区切る
  $new_obj.Tags = Convert-Hash-to-String -hash $vm.Tags -delimiter ":" -end ";";
  return $new_obj;
}

foreach($vm in (Get-AzVM)){
  New-VmInfoObject -vm $vm | Export-Csv -Path vmlist.csv -Encoding UTF8 -Append -NoTypeInformation;
}

せいぜい数百台なので都度Export-Csvしていますが、一度配列に入れてからエクスポートしたほうがパフォーマンスがよいかもしれません。

コメント