Passing Objects between functions and Export-CSV

Ask your PowerShell-related questions, including questions on cmdlet development!
Forum rules
Do not post any licensing information in this forum.

Any code longer than three lines should be added as code using the 'Select Code' dropdown menu or attached as a file.
Locked
azeiler
Posts: 12
Meble kuchenne na zamówienie - na wymiar - Wrocław
Joined: Fri Nov 09, 2018 1:20 pm

Passing Objects between functions and Export-CSV

Post by azeiler »

I have been getting into the object oriented nature of Powershell recently, and ran into an issue.

I have created a custom class and wrote a script that instantiates that class and populates its properties. It will then do that a number of times based on elements in an array. Lastly, I used Export-CVS to get the properties of all those objects into a CSV. It worked great.

But then I thought it would be more efficient to have another function creates a new object of the right class, populates all the values, and then returns that object to the main script. It seems to work OK from within that function, but when I return the object and try to Export-CSV, all I get is a single column with the "length" property. Is there something about passing an object between functions that causes this problem?

I can attach relevant bits of code if requested, I just figured I would start by conceptually explaining my issue.

Thanks

jvierra
Posts: 14444
Joined: Tue May 22, 2007 9:57 am
Contact:

Re: Passing Objects between functions and Export-CSV

Post by jvierra »

Without an example the question cannot be answered. Attach a simple example of your issue and we will look at it. It is likely you are not returning the correct object type or that enumeration is converting the object to a string.

A common cause of this behavior is an unintended result in a function is outputting a string as the first object returned. The Csv converter creates the Csv structure based on the type of the first object in the collection.

azeiler
Posts: 12
Joined: Fri Nov 09, 2018 1:20 pm

Re: Passing Objects between functions and Export-CSV

Post by azeiler »

Here is the function, amended for propriety sake. It takes an array which is basically each line of a block of text, extracts information from the text, and sets that information to the properties of a new object of type ZClass. When I use this same basic code in my script without making it a separate function, and set several of the objects it creates to an array to Export-CSV, it works fine. But when I make it a function as posted here, Export-CSV just gives me a list of length values.
  1. function Get-XClassData()
  2.  
  3. {
  4.  
  5.     [CmdletBinding()]
  6.  
  7.     param (
  8.  
  9.         [Parameter(Mandatory = $True, ValueFromPipeline = $True)]
  10.  
  11.         [object[]]$XObjectText
  12.  
  13.     )
  14.  
  15.    
  16.  
  17.     BEGIN
  18.  
  19.     {
  20.  
  21.         $ANames = @(...)
  22.  
  23.         $ANames = @(...)
  24.  
  25.         $CNames = @(...)
  26.  
  27.         $DNames = @(...)
  28.  
  29.         $ENames = @(...)
  30.  
  31.         $FNames = @(...)
  32.  
  33.         $GCNames = @(...)
  34.  
  35.     }
  36.  
  37.     PROCESS
  38.  
  39.     {
  40.  
  41.         $LineContent = $XObjectText[0] -split '"'
  42.  
  43.         $XClass = New-Object ZClass
  44.  
  45.         $XClass.ClassName = $LineContent[1]
  46.  
  47.        
  48.  
  49.         $XObjectText | %{
  50.  
  51.             If ($_.SubString(0, [math]::min(14, $_.length)) -eq '...')
  52.  
  53.             {
  54.  
  55.                 $LineContent = $_ -split '"'
  56.  
  57.                 $XClass.ClassDescription = $LineContent[1]
  58.  
  59.             }
  60.  
  61.             If ($_ -like "*...*")
  62.  
  63.             {
  64.  
  65.                 $LineContent = $_ -split '"'
  66.  
  67.                 switch ($LineContent[1])
  68.  
  69.                 {
  70.  
  71.                     { $ANames -contains $LineContent[1] }
  72.  
  73.                     { $XClass.ABlocks++ }
  74.  
  75.                     { $BNames -contains $LineContent[1] }
  76.  
  77.                     { $XClass.BBlocks++ }
  78.  
  79.                     { $CNames -contains $LineContent[1] }
  80.  
  81.                     { $XClass.CBlocks++ }
  82.  
  83.                     { $DNames -contains $LineContent[1] }
  84.  
  85.                     { $XClass.DBlocks++ }
  86.  
  87.                     { $ENames -contains $LineContent[1] }
  88.  
  89.                     { $XClass.EBlocks++ }
  90.  
  91.                     { $FNames -contains $LineContent[1] }
  92.  
  93.                     { $XClass.FBlocks++ }
  94.  
  95.                     { $GCNames -contains $LineContent[1] }
  96.  
  97.                     { $XClass.GBlocks++ }
  98.  
  99.                 }
  100.  
  101.             }
  102.  
  103.         }
  104.  
  105.        
  106.  
  107.         $XClass.GetClassType()
  108.  
  109.        
  110.  
  111.         Write-Output $XClass
  112.  
  113.     }
  114.  
  115.     END { }
  116.  
  117.  
  118.  
  119. ForEach(...)
  120.  
  121. {
  122.  
  123. $XClass = Get-XClassData $XObjectText
  124.  
  125. $Classes += $XClass
  126.  
  127. }
  128.  
  129.  
  130.  
  131. $Classes | Export-Csv "c:\test_output.csv" -NoTypeInformation

jvierra
Posts: 14444
Joined: Tue May 22, 2007 9:57 am
Contact:

Re: Passing Objects between functions and Export-CSV

Post by jvierra »

We need real code and not pseudo code. It should be attached here as a PS1 file that runs and demonstrates th issue you are having. As posted the code is not useable. The code is full of syntax errors.

azeiler
Posts: 12
Joined: Fri Nov 09, 2018 1:20 pm

Re: Passing Objects between functions and Export-CSV

Post by azeiler »

jvierra wrote:
Fri May 03, 2019 9:13 am
We need real code and not pseudo code. It should be attached here as a PS1 file that runs and demonstrates th issue you are having. As posted the code is not useable. The code is full of syntax errors.
It's full of syntax errors because I removed code that I am not allowed to post on the internet. When I tried to create a similar (working) function to post here, everything worked fine. Can you please try to help me without the specific code?

I have attached two screenshots. The first is the properties of my class based objects while still inside the function. The second is the parameters after I write-output to a parameter outside the function. You can see that just this write-output causes it to lose its type and all its specific values.

https://ibb.co/3TcGwPV
https://ibb.co/GTRszn5

jvierra
Posts: 14444
Joined: Tue May 22, 2007 9:57 am
Contact:

Re: Passing Objects between functions and Export-CSV

Post by jvierra »

Please create a copy of your PS1 file that demonstrates your issue. We cannot help you with broken code or pictures of code.

It is also possible that you will see your own error when creating a simple version of your code. YOu need a basic class and the method you are calling the function. You have most of it just make it work. There is no need for proprietary data. Just change all data to be dummy data.

Also check all of the issues I listed in my first response.

jvierra
Posts: 14444
Joined: Tue May 22, 2007 9:57 am
Contact:

Re: Passing Objects between functions and Export-CSV

Post by jvierra »

/Two things I can tell you immediately:
1. The following line will output a string into your collection and that string will always be the first item in the collection.

Code: Select all

      $XClass.GetClassType()
2. When returning results from a function there is no need to use Write-Output.

Code: Select all

     Write-Output $XClass

Just output the object like this:
$XClass

azeiler
Posts: 12
Joined: Fri Nov 09, 2018 1:20 pm

Re: Passing Objects between functions and Export-CSV

Post by azeiler »

I was able to fix this issue, though I'm not entirely sure I understand. Your suggestions seem to be related.

XClass contains a method which sets one of it's parameters. I originally had the method returning that parameter as well, thinking there might be cases where I want to save the parameter and/or use it once its been set. When I modified the method to not return anything, my issue was resolved.

When I called the method within my function, I think the value that method was returning was ultimately being written to the pipeline. Then I think Powershell was converting those items I was intending to write to the pipeline to a String, and Export-CSV was exporting the length of those "strings" to my file.

So my lesson learned: do not (even accidentally) write anything to the pipeline from a function, or the powershell will make all output from that function match the type of the initial output.

Thanks for your help Jvierra!

Locked