I have a Powershell script that reads a text file with single line descriptions of shares and their properties.
It then, for each share, adds an object to an array, with properties.
I end up with an array of shares, many with common properties but also some that only appear on a few shares.
When I pipe the finished array to Export-CSV
, the resulting CSV only has columns matching the properties of the first object in the array.
Any ideas/help gratefully received.
Here is the code:
$shares_only = gc \\server\share\SHARES.txt | where {$_ -match '^*TYPE = DISK'}
$share_index = @()
$shares_only |foreach {
$sharename = ($_.Split(" ")[1])
$_ -match '\([\w\s.,"=<>()\/\*\+\-]*\);'|out-null
$shareparams = $matches[0]
$paramlist = ($shareparams.Substring(1,($shareparams.Length -3))).Split(",")
$obj = $null
$obj = New-Object System.Object
$obj | Add-Member -type NoteProperty -Name NAME -Value $sharename
$paramlist | foreach {
$obj `
| Add-Member -type NoteProperty -Name ($_.Split("=")[0]) -Value ($_.Split("=")[1])
}
$share_index += $obj
}
$share_index | Select * | Export-CSV -notype \\server\share\Shares.csv
Here is the first two objects in the array as an example (using $share_index[0..2]
to output to console):
NAME : _ACCTEST_
TYPE : DISK
PREFIX : (<USERCODE>)
AREABYTES : 184320
ACCESS : ALL
FAMILY : ACCTESTPACK
DOWNSIZEAREA : TRUE
NAME : _HOME_
TYPE : DISK
PREFIX : (<USERCODE>)
COMMENT : Private user files
AREABYTES : 184320
ACCESS : ALL -EXTRACT
FAMILY : <FAMILY>
DOWNSIZEAREA : TRUE
ALLOWGUESTACCESS : TRUE
And here are the first 3 rows of the CSV:
"NAME","TYPE ","PREFIX ","AREABYTES ","ACCESS ","FAMILY ","DOWNSIZEAREA "
"_ACCTEST_"," DISK "," (<USERCODE>) "," 184320 "," ALL "," ACCTESTPACK "," TRUE "
"_HOME_"," DISK "," (<USERCODE>) "," 184320 "," ALL -EXTRACT "," <FAMILY> "," TRUE "
You can see that COMMENT
and ALLOWGUESTACCESS
properties are missing even although they are in the array for the _HOME_
share.
EDIT: Accepted slightly modified version of @JPBlancs answer, so last 2 lines of my code is now:
$fixed_index = $share_index | Sort-Object -Property @{expression={(($_.psobject.Properties)|Measure-Object).count}} -Descending | ConvertTo-CSV -notype
$fixed_index | ConvertFrom-CSV | Sort -Property Name | Export-CSV -notype \\server\share\Shares.csv
So, done as suggested, then converted to CSV in a new object. Then, convert that object back from CSV, retaining the new properties, sort again on Name to get the alphabetical list I need, then Export to CSV again.
Gives me, for example:
"NAME","TYPE","PREFIX","PUBLIC","COMMENT","AREABYTES","ACCESS","FAMILY","DOWNSIZEAREA","ALLOWGUESTACCESS"
"_ACCTEST_"," DISK "," (<USERCODE>) ","",""," 184320 "," ALL "," ACCTESTPACK "," TRUE ",
"_HOME_"," DISK "," (<USERCODE>) ",""," Private user files "," 184320 "," ALL -EXTRACT "," <FAMILY> "," TRUE "," TRUE "
I did something like this
$a = "" | select "P1","P2"
$b = "" | select "P1","P2","P3"
$c = "" | select "P1","P2","P3","P4"
$array = $a,$b,$c
$array | Export-Csv c:\temp\t.csv
gives as you remark:
#TYPE Selected.System.String
"P1","P2"
,
,
,
So the idea is to sort the objects by the properties count :
$array | Sort-Object -Property @{expression={$_.psobject.properties.count}} -Descending| Export-Csv c:\temp\t.csv
It gives :
#TYPE Selected.System.String
"P1","P2","P3","P4"
,,,
,,,
,,,
In the case of the question (object created adding members to a System.Object) you can use :
Sort-Object -Property @{expression={(($_.psobject.Properties)|Measure-Object).count}} -Descending
Export-Csv
and ConvertTo-Csv
appear to only take the union of properties between objects sent to them. I think you will have to parse the text file and compile a list of all properties and when you create your objects set any missing property values to null.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With