Add users to SharePoint Group using PowerShell

Yet another moment when you get frustrated trying to solve a simple issue and as a last resort search for ‘Why SharePoint Sucks?‘. And it turns out that we are just used to complain about SharePoint even when we are not understanding how it works. And most of the times, ignoring those hidden words and hints in MSDN documentation can be costly.

captain-america-says-sharepoint-does-not-suck
[Image credit: Scott Ellis]

But hey, who goes to MSDN when the first search result in StackOverflow gives you an answer. However, most of the time the questions and their answers in forums such as CodeProject, StackOverflow etc. are limited in scope and do not really cover the whole aspect. Having said that, MSDN should still be considered as the first source of documentation when it comes to Microsoft products.

Add bulk users to SharePoint Group using PowerShell

I wanted to add bulk (literally 100s) of users to a SharePoint group in a site collection. And of course, I was in no mood to put the list of users as an attachment to the manual and ask operations to add these users in various environments.

I wrote the following PowerShell script (yes, I love PowerShell) to read a file with list of users and add them in a loop to a SharePoint group using Set-SPUser. There isn’t much description or documentation available on MSDN for this cmdlet, but it basically adds a user to a SharePoint site within a certain group.


$loc = Get-Location		
$Users = Get-Content "$loc\Data\Users.txt"	

foreach ($User in $Users) { 	
	Set-SPUser -Identity $User -Web $siteCollUrl -Group $group 	 
} 	

But here comes the surprise. Using Set-SPUser, I was not able to add all the users to the group and it gave the following error on most of the users.

You must specify a valid user object or user identity

The nearest hint or solution was from Guna Kuppusamy where he had mentioned the same problem and the work around using stsadm.


stsadm -o adduser -url "<<Site URL>>" -userlogin "<<Domain\account>>" -useremail "<<Email address>>" -group "<<SP Group>>" -username "<<Display Name of the User>>"

To be honest, stsadm does not feel right when you are working with SharePoint 2010 or 2013. There has to be a better solution.

Solution 1: Use New-SPUser

It turns out to be that Set-SPUser can only set properties, permissions to a user account if it has already been added to SharePoint site. This means, you have to make sure that the user is already present in the SharePoint site. Otherwise, you can use the New-SPUSer cmdlet to add the user.

The New-SPUser cmdlet adds an existing user to a SharePoint Web site with the designated permissions. This user has the given permissions in all subsites that inherit permissions. The user account must already exist in the user directory.
If your environment is in Active Directory mode, the user must already exist in Active Directory Domain Services (AD DS) and only the UserAlias parameter is required; all other fields are pulled from AD DS. If only an alias is given and the farm is in Active Directory Account Create mode, the Email parameter is also required.

So, I added an extra step to check if the user exists by calling the Get-SPUser and when the user does not exist, call the New-SPUser just before using the Set-SPUser to set the permission.


$loc = Get-Location		
$Users = Get-Content "$loc\Data\Users.txt"	

foreach ($User in $Users) { 	
	$user = Get-SPUser -Identity $User -Web $siteCollUrl -ErrorAction SilentlyContinue
	if ($user -eq $null)
	{
		Get-SPWeb $siteCollUrl | New-SPUser –UserAlias $User
	}
	Set-SPUser -Identity $User -Web $siteCollUrl -Group $group 	  
} 		

Solution 2 (Recommended): Ensure User

It just gets better. And I should be asked to bake a cake for anyone who is reading this blog as it was only while I writing this post I realized that it was even simpler and straight forward by using the EnsureUser.

SPWeb.EnsureUser checks whether the specified logon name belongs to a valid user of the website, and if the logon name does not already exist, adds it to the website.

In fact, EnsureUser does the same thing which I implemented myself in Solution 1 by using Get and New-SPUser.


$loc = Get-Location		
$Users = Get-Content "$loc\Data\Users.txt"	

$web = Get-SPWeb -identity $siteCollUrl
foreach ($User in $Users) { 
    $web.EnsureUser($User)	
    Set-SPUser -Identity $User -Web $siteCollUrl -Group $group 	
} 

Thus, lesson learnt! The chances are that it’s not SharePoint but we … đŸ™‚

  • GB

    Nice. Adding a little bit: as I generated my list of users from AD ($users = Get-ADUser -SearchBase “OU=GETEC,OU=Usuarios,OU=Sede,DC=gb,DC=local” -Filter *), I had to pass the “claims user name” to Set-SPUser otherwise it would fail:

    $users | % { Set-SPUser -Identity (“i:0#.w|gb” + $_.Name) -Web $web -Group $visitors }

    Thanks,
    GB