Karl
Karl

Reputation: 345

Powershell foreach

I am trying to iterate through a list of users so I can pull their properties, but I am fairly new to Powershell and don't understand the output I'm getting.

foreach ($user in $AllUsers) 
{  
  get-member -inputobject $user; 
  write-host " "
}

The $AllUsers object has six users, each with a set of properties and methods. However when I run the code block above, the output is six empty lines, then the list of properties and methods for each user six times in a row. I am trying to get the properties and methods of each user separated out by a blank line. Can someone help me understand why the output is running write-host six times and then get-member six times?

Upvotes: 1

Views: 658

Answers (3)

Ansgar Wiechers
Ansgar Wiechers

Reputation: 200503

Get-Member writes to the success output stream, whereas Write-Host writes to the console (or rather the host program). Different output is not guaranteed to be displayed in the order the respective statements were run. You can also get this behavior when you have statements write output to the success output stream as well as the error output stream (or one of the other output streams, like warning or debug). See here for a more thorough discussion of output in PowerShell.

If you want a blank line printed after each set of object members, replace Write-Host with Write-Output:

foreach ($user in $AllUsers) {  
  Get-Member -InputObject $user
  Write-Output ''
}

You could also do something like this:

foreach ($user in $AllUsers) {  
  (Get-Member -InputObject $user) + ''
}

or like this:

$AllUsers | % { (Get-Member -InputObject $_) + '' }

Upvotes: 1

Mike Zboray
Mike Zboray

Reputation: 40838

I think what is happening is that the results of Get-Member are getting put into the pipeline and queued up until the block completes. In contrast, the side-effect of Write-Host is happening immediately on each loop. You can remedy this by writing to string output:

foreach($user in $AllUsers)
{
    $user | gm | out-string
}

This will print the members for each item with some whitespace in between. Most of the time all objects of a given type will have the same members, but occasionally there are dynamically defined members.

Upvotes: 2

ojk
ojk

Reputation: 2542

It's behaving this way, because you told it too :)

When you use foreach, you are doing whatever's in the codeblock for each item in a collection ($AllUsers). So for each user, first a get-member is done, then write-host is writing an empty line.

Why would you want to write out the properties and methods for each user? They would be identical.

If you just want to list out the users with all the properties you can do this:

$AllUsers | format-list *

Then you can see all properties, when you have decided which one you want to display, you can choose to view only those:

$AllUsers | Select-Object Prop1,Prop2,Prop4,Prop10

Upvotes: 1

Related Questions