Skip to content

Month: May 2014

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 … 🙂

Generating a sequence in SQL

I came through one of the many interesting SQL questions on one of the forums yesterday. The original poster of the question wanted to get a list of next 15 dates from today. And he wanted to do this by using cursors. While you can write a cursor to get the results in this case, but cursor are not meant to be used like this. A cursor is used to step through the results of a query that returns multiple results e.g. rows from a table.

One good old way of generating a sequence of next n dates would be to use the WHILE loop in SQL.


DECLARE @LoopCount INT
SET @LoopCount = 0
 
DECLARE @calcDate DateTime
SET @calcDate = GETDATE() 

DECLARE @outDate varchar(30) 

WHILE @LoopCount < 15
BEGIN
 
	 SET @outDate = CONVERT(NVARCHAR, @calcDate, 103) 
	 PRINT @outDate
	 SET @calcDate = DATEADD(dd, 1, @calcDate) 

	 SET @LoopCount = @LoopCount + 1
END

Generating a sequence of dates in SQL

Another better alternative would be to use the Common Table Expressions in SQL Server.

A common table expression (CTE) can be thought of as a temporary result set that is defined within the execution scope of a single SELECT, INSERT, UPDATE, DELETE, or CREATE VIEW statement. A CTE is similar to a derived table in that it is not stored as an object and lasts only for the duration of the query. Unlike a derived table, a CTE can be self-referencing and can be referenced multiple times in the same query.


WITH q AS
	(
	SELECT  GETDATE() AS datum
	UNION ALL
	SELECT  datum + 1
	FROM    q
	WHERE datum + 1 < GETDATE() + 15
	)
SELECT  CONVERT(NVARCHAR, DATEADD(dd, DATEDIFF(dd, 0, datum), 0), 103) AS MyDate
FROM    q

Generating a sequence of numbers in SQL

Similarly, you can generate the sequence of number in SQL using the Common Table Expressions


WITH q AS
	(
	SELECT  1 AS num
	UNION ALL
	SELECT  num + 1
	FROM    q
	WHERE num < 15
	)
SELECT  * FROM    q

Generating a sequence of alphabets in SQL

Or, you can even generate the sequence of alphabets in SQL using the Common Table Expressions


WITH q AS
	(
	SELECT  0 AS num
	UNION ALL
	SELECT  num + 1
	FROM    q
	WHERE num <= 26
	)
SELECT CHAR(num + 65) FROM    q

Add User Profiles in SharePoint 2013 using PowerShell Script

Setting up a SharePoint 2013 development environment is essentially a lengthy process. Apart from installation and configuring SharePoint 2013, you need to install SQL Server, Visual Studio etc. to get you started before developing your first SharePoint 2013 App.

MSDN has a detailed documentation available: Start: Set up the development environment for SharePoint 2013

However if you have Azure development subscription available, you can also use one of the Windows Azure developer image that comes with SharePoint 2013 and Visual Studio 2013 RC pre-installed.  The image also contains scripts to provision and configure SharePoint 2013 with or without an Active directory running on a different machine. This is surely a big helping hand as you don’t have to do all the pre-plumbing before you can get started.

Anyway, this is not this blog post about. It was just a background as I was using one of these pre-configured developer images. Once ready, for one of the Apps I was created I wanted to have my User Profile Service to have a considerable number of user profiles. As my development environment was not connected to any domain or active directory, the only users I had access to were the local computer accounts and there were not many. One way was to create the users manually and then import them in user profile, but that does not scale very well and requires repeated effort if I want to set up another similar environment later on. So, I decided to automate the process of creation of local users and then adding them to SharePoint User Profile.

Step 1: Generate the list of accounts to be created

Not really applicable in a real environment where you would have real accounts, but for my development environment I decided to create a Xml file using PowerShell with various elements for a User such as FirstName, LastName, EmailAddress etc.


<User>
	<Account>User0001</Account>
	<EmailAddress>User0001@WORKGROUP.com</EmailAddress>
	<FirstName>FirstName_User1</FirstName>
	<LastName>LastName_User1</LastName>
</User>

Here is the script which generate the specified number of user data in form of an xml file. It takes the number of accounts to generated as input and results into a Users.xml file.


$Path = (Get-Item -Path ".\" -Verbose).FullName + "\Users.xml"
 
$XmlWriter = New-Object System.XMl.XmlTextWriter($Path,$Null)
 
$xmlWriter.Formatting = 'Indented'
$xmlWriter.Indentation = 1
$XmlWriter.IndentChar = "`t"
 
$xmlWriter.WriteStartDocument()
 
# create root element "Users" and add some attributes to it
$XmlWriter.WriteComment('List of Users')
$xmlWriter.WriteStartElement('Users')

$nrOfUsers = Read-Host 'Please enter the numbers of users you want to create:'
 
# add a couple of random entries
for($x=1; $x -le  [int]$nrOfUsers; $x++)
{
    $User = 'User{0:0000}' -f $x
    $email = $User +  '@' +  (gwmi WIN32_ComputerSystem).Domain
 
    $guid = [System.GUID]::NewGuid().ToString()
 
    # each data set is called "User"
    $xmlWriter.WriteStartElement('User')
   
    # add three pieces of information:
    $xmlWriter.WriteElementString('Account',$User)
    $xmlWriter.WriteElementString('EmailAddress',$email)
    $xmlWriter.WriteElementString('FirstName','User')
	$xmlWriter.WriteElementString('LastName',$x)
 
    # close the "User" node:
    $xmlWriter.WriteEndElement()
}
 
# close the "Users" node:
$xmlWriter.WriteEndElement()
 
# finalize the document:
$xmlWriter.WriteEndDocument()
$xmlWriter.Flush()
$xmlWriter.Close()

Step 2: Create local account using PowerShell

PowerShell is very useful for automating Active Directory. It allows to quickly and relatively easy automate mundane actions or perform same operations with many objects.

PowerShell provides very broad set of methods to work with Active Directory. There is some of them:

  • Microsoft Active Directory Module for Windows PowerShell
  • ADSI adapter
  • .Net Classes
  • Non Microsoft free extensions, such as Quest Active Directory Cmdlets or AD provider from PowerShell Community Extensions.

Read more about these methods here on MSDN.


$HostName =(gwmi WIN32_ComputerSystem).Name
[ADSI]$server= "WinNT://$HostName" 

$localUsers = $server.Children | where {$_.SchemaClassName -eq 'user'}  |  % {$_.name[0].ToString()}

#Add a new local user after checking that it does not exist
if($localUsers -NotContains $user.Account){
	$Account = $server.Create("User", $user.Account) 
	$password = [System.Web.Security.Membership]::GeneratePassword(10,2)
	$Account.SetPassword($password)
	$Account.SetInfo() 
}
else{
	Write-Host "User Account " $user.Account " already exists"
}

Step 3: Add the User Profile to SharePoint 2013 using PowerShell

You also need to add the user account which is running the PowerShell script to have the Full Control on the User Profile Service application via the Central Administration. To add the permission:

  • Go to Central Administration
  • Go to Manage Service Applications
  • Select User Profile Service Application and click on the Permissions button in the ribbon.
  • Select the user who is running the script and give him ‘Full Control’ access.

User Profile Service Application Permission

You must create the UserProfileManager object before you access a UserProfile object. You can then retrieve the user profiles that the user can access. Full access to everyone’s user profile requires “Manage User Profiles” rights. Full access to your own profile requires “Use Personal Features” rights. Everyone has read access to all profiles.


#instantiate the user profile manager
$mysite = new-object microsoft.sharepoint.spsite($siteurl)
$servicecontext = get-spservicecontext($mysite)
$userprofilemanager = new-object microsoft.office.server.userprofiles.userprofilemanager($servicecontext)

Next, use the userprofilemanager object to check if the profile exists for this particular user. If it does not, the create a new user profile as shown below.

However, this is a crude implementation as I wanted to use it one time. To make it even better, you might also update the existing profile if any with the new data specified in the xml file.


#Add a new user profile for the user
if($userprofilemanager.UserExists($user.Account)){
	Write-Host "User Profile for " $user.Account " already exists"
}
else{
	$newprofile = $userprofilemanager.createuserprofile($user.Account)
	$newprofile.DisplayName = $user.Account
	$newprofile["FirstName"].add($user.FirstName)
	$newprofile["LastName"].add($user.LastName)
	$newprofile["WorkEmail"].add($user.EmailAddress)
	$newprofile.commit()
}    

If you run the CreateUserProfiles.ps1 from the script download, it asks you the following parameters to enter.

  • Number of users to be created. I entered 1000 in this case which seemed to be created without any issues.
  • Site Url of the Central Administration site. This is required to get the context of the service application.

Create User Profile

And the result is as below. Without any manual effort, we have 1000 user profiles ready in our development environment.

User Profiles

Download Scripts

The curious case of Scrum Master’s role

At the very core, both agile manifesto and scrum are frameworks and not a detailed method or process. This was intentional because the founders of scrum wanted to keep it as lightweight framework which can be used by the organizations to develop the software with value.

However, the reason often leads to different interpretations of scrum and sometimes leads to the result which is completely against the scrum framework.

There are three distinct roles which identified within the Scrum methodology:

  • The Scrum master, who ensures the process is followed, removes impediments, and protects the Development Team from disruption.
  • The Product Owner, who represents the stakeholders and the business.
  • The Development Team, a cross-functional, self-organizing team who do the actual analysis, design, implementation, testing, etc.

Scrum_Roles

And one of the most misunderstood role in scrum team is of Scrum Master. Before we go more into details of Scrum Master, if you are interested to read about the fundamentals of Scrum and the various roles defined in a Scrum team, refer to my previous post ‘A beginners guide to Scrum’

A whole lot of development organizations and teams are using scrum these days. Having said that, I have noted that most of these teams use scrum as a planning methodology focusing only on the daily scrum meetings and/or sprints. And just because it’s fashionable to say that the project follows scrum approach, someone from the team takes the responsibility of being a scrum master. In most of the cases, as the world ‘master‘ is involved, it is either the erstwhile project manager or the architect/lead developer of the project.

Scrum Master is not Project Manager

By definition, project managers have the responsibility of the planning, execution and closing of project. In addition, project manager is often a client representative and has to determine and implement the exact needs of the client, based on knowledge of the firm they are representing. A project manager is the bridging gap between the team and client.

On the other hand, a scrum master does not have any responsibility of planning and delivery of the project. The main focus of a scrum master is to make sure that he removes any impediment or blockage which comes in the way of development team.

Scrum Master is not Lead Developer

The Development Lead’s role is focused on providing more detail to the Solution Architect’s architecture. This would include creation of detailed technical design, program specifications etc. The Development Lead is also the first line of support for the developers who need help understanding a concept or working through a particularly issue. The Development Lead does not need to be hierarchically up in the organizational chart and is not responsible for the administrative work of the employees. Their primary focus is on helping the developers to deliver the quality software on time.

There has been a real debate and questions coming in if the Scrum Master should know the technical details of the software development.

It’s completely OK if the scrum master does not understand a single bit of architecture, technical design or other details of the software project.

The real focus of a scrum master is on the process and not the details of the work which development team is responsible. However, if the development team is stuck with a technical impediment which they can not solve themselves then they should contact scrum master. For e.g. it could a technical or architectural decision which they are not sure how to progress with. In such case, a scrum master can reach out to other parts of organizations or even outside organizations to make sure development team gets the answer and they can continue with.

So, Who exactly is Scrum Master?

Schwaber & Sutherland gave a precise definition of Scrum Master role in the scrum guide without detailing the day-to-day activities.

The Scrum Master is a servant-leader for the Scrum Team. The Scrum Master helps those outside the Scrum Team understand which of their interactions with the Scrum Team are helpful and which aren’t. The Scrum Master helps everyone change these interactions to maximize the value created by the Scrum Team.

Scrum master is for sure not a project manager and/or a development lead. He does not manage people and he is not someone to whom people should be reporting (in context of Scrum). Having said that, it should be noted that Scrum Master is a management position. Scrum Master should have organizational management powers and ability to reach other parts of the organization to make sure he is able remove any impediment faced by the team.

Scrum Master is a shield for the development team so that they focus on what they should be doing and continue the same. A Scrum Master makes sure that the product owner is aware of the scrum process and acknowledges the structure of the framework to formulate and prioritize the product/sprint backlog.

At the same time, I am a believer that scrum master is a role rather than a position.

Have you also observed similar situation where the Scrum Master role is mingled or is not properly defined in your organization?