This is probably more of a 'how does PowerShell handle variables and piping' rather than a specific programmatical question, but since it seems like strange behaviour (to me) I thought I'd post it here.
I just had some difficulties exporting a variable to a CSV using PowerShell and found this Stack question that helped me a lot. However, when fiddling around with the output I got two different results depending on how I called the Export-CSV
function.
I have a custom PS object that looks roughly like this:
Account Partner ProjectName ProjectPhase
1 A Test Start
2 B Test2 Start
3 A Test4 End
4 C Test3 Middle
....
When I use the following line it correctly outputs the CSV file:
$csvBody | Export-Csv -Path "$targetPath\$fileName" -Encoding Unicode -NoTypeInformation
However, when I use the following line it doesn't:
Export-Csv -InputObject $csvBody -Path "$targetPath\$fileName" -Encoding Unicode -NoTypeInformation
In this case, the output looks like this: Count,"Length","LongLength","Rank","SyncRoot","IsReadOnly","IsFixedSize","IsSynchronized" 263,"263","263","1","System.Object[]","False","True","False"
I understand from this other Stack post that the output becomes the property of the $csvBody, which is an array. My question is why does this happen when I'm not piping the object to Export-CSV, but it doesn't happen when I am using the pipe?
I think this is because Export-CSV
has been written with the intention that it should (and would) generally handle input via the pipeline.
I think the behavior you are seeing occurs because the -InputObject
parameter does not accept array input. You can see that from the help page:
Export-Csv [[-Path] <String>] [[-Delimiter] <Char>] [-Append] [-Confirm] [-Encoding <String> {Unicode | UTF7 |
UTF8 | ASCII | UTF32 | BigEndianUnicode | Default | OEM}] [-Force] -InputObject <PSObject> [-LiteralPath <String>]
[-NoClobber] [-NoTypeInformation] [-WhatIf] [<CommonParameters>]
It is <psobject>
rather than <psobject[]>
and as such it expects a single <psobject>
as it's input. It seemingly doesn't unroll that object when it's provided via the parameter line, instead it gives you a CSV that contains the default properties of that object itself (length etc.).
When you send the object via the pipeline, it uses the cmdlet PROCESS
functionality of accepting pipeline input to unroll the object and handle each item in the collection individually.
Someone can probably explain this better than I have above, or perhaps can explain why Export-CSV doesn't work the way you expect (other than --as I assume-- by design).
Here everything works as design and not badly written :
In the second way, the inputobject is a #TYPE System.Object[]
as you can see if you keep TypeInformation.
When you call Export-Csv using the pipe, each object of the collection is sent to the process part of the Cmdlet.
Take a collection of integers :
$a = 1..4
then try :
$a | Get-Member
It gives : System.Int32
Then try :
Get-Member -InputObject $a
It gives : System.Object[]
So in your case the object exported is the array wich can be useful too.
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