What rules govern how objects are formatted to the console?

Welcome Forums General PowerShell Q&A What rules govern how objects are formatted to the console?

Viewing 2 reply threads
  • Author
    Posts
    • #231670
      Participant
      Topics: 6
      Replies: 15
      Points: 141
      Rank: Participant

      Edit: I think I figured out the answer. I will update this when I can better explain.

      <span class="&quot;&quot;">[PSCustomObject]@{</span><span class="&quot;&quot;">keyA1</span><span class="&quot;&quot;">=</span><span class="&quot;&quot;">&quot;value&quot;</span><span class="&quot;&quot;">} ; [PSCustomObject]@{</span><span class="&quot;&quot;">keyB1</span><span class="&quot;&quot;">=</span><span class="&quot;&quot;">&quot;value&quot;</span><span class="&quot;&quot;"> ; </span><span class="&quot;&quot;">keyB2</span><span class="&quot;&quot;">=</span><span class="&quot;&quot;">&quot;value&quot;</span><span class="&quot;&quot;">}</span>

      Output:
      keyA1
      —-
      value

      Suppresses properties from second object.
      <span class="&quot;&quot;">[PSCustomObject]@{</span><span class="&quot;&quot;">keyA1</span><span class="&quot;&quot;">=</span><span class="&quot;&quot;">&quot;value&quot;</span><span class="&quot;&quot;">} ; [PSCustomObject]@{</span><span class="&quot;&quot;">keyA1</span><span class="&quot;&quot;">=</span><span class="&quot;&quot;">&quot;value&quot;</span><span class="&quot;&quot;"> ; </span><span class="&quot;&quot;">keyB2</span><span class="&quot;&quot;">=</span><span class="&quot;&quot;">&quot;value&quot;</span><span class="&quot;&quot;">}</span>

      Output: 
      keyA1
      —–
      value
      value

      Combines like property names, even though they are different objects. Suppresses keyB2 property.
      <span class="&quot;&quot;">(</span><span class="&quot;&quot;">1</span><span class="&quot;&quot;">).</span><span class="&quot;&quot;">foreach</span><span class="&quot;&quot;">{[PSCustomObject]@{</span><span class="&quot;&quot;">key1</span><span class="&quot;&quot;">=</span><span class="&quot;&quot;">&quot;value&quot;</span><span class="&quot;&quot;">} ; [PSCustomObject]@{</span><span class="&quot;&quot;">keyA1</span><span class="&quot;&quot;">=</span><span class="&quot;&quot;">&quot;value&quot;</span><span class="&quot;&quot;"> ; </span><span class="&quot;&quot;">keyA2</span><span class="&quot;&quot;">=</span><span class="&quot;&quot;">&quot;value&quot;</span><span class="&quot;&quot;">} | </span><span class="&quot;&quot;">Out-Host</span><span class="&quot;&quot;">}</span>

      Output: 
      keyA1 keyA2
      —– —–
      value value

      key1
      —-
      value

      Output of the second object displayed before the first object when the second object is piped to Out-Host.

      What are the rules that govern these behaviors?

      In my actual code I am running into a scenario where XMLElement objects that are returned from Invoke-Restmethod are overwriting each other, but only if an XMLElement object that contains multiple properties is used before one that contains only a single property.

      More details:
      https://stackoverflow.com/questions/62025057/console-output-suppressed-only-for-second-invocation-of-invoke-restmethod-based

      Sources:

      https://devblogs.microsoft.com/powershell/how-powershell-formatting-and-outputting-really-works/

      Out-Default looks at the <strong>FIRST OBJECT IN THE STREAM</strong> to determine how many properties the object has 5 or more properties, it send the <strong>ENTIRE STREAM</strong> to Format-List, otherwise it sends the <strong>ENTIRE STREAM</strong> to Format-Table.When it sends the stream to Format-Table, that command needs to generate columns.  It does this by looking at the properties of the <strong>FIRST OBJECT</strong> – those become the columns.  If the first Object has 2 properties, youll get a 2 column table even if all the other objects in the stream have 10 properties. 

      It is interesting to note that if you and selected enough properties, Out-Default would have sent the object stream to Format-list and then each object would have all of its properties displayed.

      Well that seems to describe the behavior perfectly.

      • This topic was modified 5 months ago by Phatmandrake.
      • This topic was modified 5 months ago by Phatmandrake.
      • This topic was modified 5 months ago by Phatmandrake. Reason: JSnover Wisdom buff
      • This topic was modified 5 months ago by Phatmandrake.
    • #231736
      Participant
      Topics: 16
      Replies: 1795
      Points: 3,305
      Helping Hand
      Rank: Community Hero

      A GET is being performed with Invoke-RestMethod. Those results are returned in seperate calls or you have multiple elements that have different keys with a single call? Normally, I create a function wrapper and this data would be saved into an object and returned. There are some instances when there would be missing keys and the only way to work around it would be ensure you Select the properties

      Depending on the number of records, I’ve had to pull millions of records at a time, but you can programatically generate a property list:

      That is a lot of looping if you have to process large recordsets. You can use a Select -Top 100 to see if it generates all of the properties rather than process the entire result, but it’s still the only way I’ve been able to ensure it returns all properties with inconsistent keys.

    • #231943
      Participant
      Topics: 6
      Replies: 15
      Points: 141
      Rank: Participant

      What I’ve figured out — There’s a question at the bottom.

      Background: I was using Invoke-RestMethod, 1st to update user data, and a 2nd time to read the user data.

      Update: Returned as single XMLElement object with a single property.
      Read: Returned a single XMLElement object with multiple properties.

      Problem: If the XMLElement object with a single property $Obj1 was sent to the console first, it would suppress the XMLElement Object with multiple properties $obj2 from displaying to the console, and $obj1 would display in a Format-Table style.

      If $obj2 were displayed first, $obj1 would also display in a Format-List style.

      Explanation:
      As explained here: https://devblogs.microsoft.com/powershell/how-powershell-formatting-and-outputting-really-works/

      Under the covers, every command entered in through the console host is piped to Out-Default.

      Out-Default looks at the <strong>FIRST OBJECT IN THE STREAM</strong> to determine how many properties the object has 5 or more properties, it sends the <strong>ENTIRE STREAM</strong> to Format-List, otherwise, it sends the <strong>ENTIRE STREAM</strong> to Format-Table. When it sends the stream to Format-Table, that command needs to generate columns.  It does this by looking at the properties of the <strong>FIRST OBJECT</strong> those become the columns.  If the first Object has 2 properties, youll get a 2 column table even if all the other objects in the stream have 10 properties.

      This explains why $obj1 would suppress the output of $obj2. Conversely, $obj2 which contained more than 5 or more properties was being sent to Format-List the behavior being:

      That if you and selected enough properties, Out-Default would have sent the object stream to Format-list and then each object would have all of its properties displayed.

      When $obj2 was called first, the behavior was that since $obj2 was sent to console with Format-List, based on the rules, all subsequent objects will be sent to console through Format-List, thus every property on each subsequent obj will be displayed rather than suppressed.

      To test this I create a test XMLElment Object with less than 5 properties, and it was indeed sent to console through Format-Table

      Solution:

      Obviously this isn’t ideal for objects with varying properties. The solution that I found was to send the objects to Out-Default.

      https://gist.github.com/phatmandrake/b688aaee6f4a8cae206337ac0a29fcfc

      By itself, this has the unintended consequence of removing the object from the pipeline, which isn’t conducive to passing data to another function, but it works if it’s end of the line.

      What I haven’t been able to figure out is why when $XMLSuccess is called twice, it only shows up once. The behavior mimics that the second output is suppressed. My guess is because it’s turning a property into a table “anonymously” it just isn’t aware it would be appropriate to merge the outputs since it doesn’t have anything to key off of being the same.

Viewing 2 reply threads
  • The topic ‘What rules govern how objects are formatted to the console?’ is closed to new replies.