A Quick Note Regarding the ForEach-Object Cmdlet


Summary: Use Windows PowerShell to Manage Office 365 using Windows PowerShell cmdlets, scripts, and batch processes.

In a Working with SharePoint Online Users you might have noticed that we piped site information to the ForEach-Object cmdlet:

Get-SPOSite | ForEach-Object {Set-SPOUser -Site $_.Url -LoginName "kenmyer@litwareinc.com" -IsSiteCollectionAdmin $True}

That brings up an interesting question: why did we do that? After all, when working with the Azure Active Directory cmdlets we piped information directly from the Get-MsolUser cmdlet to the Set-MsolUser cmdlet:

Get-MsolUser | Set-MsolUser -UsageLocation "FR"

So then why didn’t we do something like this with our SharePoint Online command:

Get-SPOSite | Set-SPOUser -LoginName "kenmyer@litwareinc.com" -IsSiteCollectionAdmin $True

The main reason we didn’t do that is because it won’t work. With the Set-SPOUser cmdlet you must explicitly include the Site parameter followed by the name of the site. For example:

Set-SPOUser -Site "https://litwareinc.sharepoint.com/sites/communities" -LoginName "kenmyer@litwareinc.com" -IsSiteCollectionAdmin $True

That means that, if we try to pipe information directly to Set-SPOUser, the cmdlet won’t take all of our sites and make Ken Myer an administrator on each one. Instead, it will prompt us to enter the site URL:

Get-SPOSite | Set-SPOUser -LoginName "kenmyer@litwareinc.com" -IsSiteCollectionAdmin $True
cmdlet Set-SPOUser at command pipeline position 2
Supply values for the following parameters:

That means that we need to pipe site information to the ForEach-Object cmdlet instead. ForEach-Object takes each item passed to it (each site) and then does whatever we tell it to do to that item. In this case, we’re telling it to use the Set-SPOUser cmdlet to make Ken Myer an administrator on that site:

Set-SPOUser -Site $_.Url -LoginName "kenmyer@litwareinc.com" -IsSiteCollectionAdmin $True

The syntax $_.Url represents the URL of the site. The $_. Indicates that we’re using information that was piped to the ForEach-Object cmdlet by another cmdlet.

Confused? Here’s a quick example. Suppose we have three sites with the following URLs:

When we pipe that information to ForEach-Object, the cmdlet takes the first item in the collection (site1) and runs the Set-SPOUser cmdlet using the URL for that site. In other words, it runs this command:

Set-SPOUser -Site "https://litwareinc.sharepoint.com/sites/site1" -LoginName "kenmyer@litwareinc.com" -IsSiteCollectionAdmin $True

When that’s done, it then takes the second site (site2) and runs Set-SPOUser against that site:

Set-SPOUser –Site "https://litwareinc.sharepoint.com/sites/site1" –LoginName "kenmyer@litwareinc.com" –IsSiteCollectionAdmin $True

As you can see, now it’s using the URL of the second site in the collection. Eventually ForEach-Object will have run through all the sites in the collection, and made Ken Myer an administrator on each one.

For more information, take a look at this article. Needless to say, ForEach-Object is actually a handy little cmdlet to know about. For example, sometimes when you try to pipe information from one cmdlet to another you get an error message like this:

The input object cannot be bound to any parameters for the command either because the command does not take pipeline input or the input and its properties do not match any of the parameters that take pipeline input.

That happens because not all cmdlets accepted pipelined input. How do you get around that issue? You got it: use ForEach-Object.

Next: Using Windows PowerShell to Manage Lync Online

See Also

Using Windows PowerShell to Manage SharePoint Online