Cloud Migration Woes: Validating Office 365 Users and Licenses (Part-2)

Cloud Migration Woes: Validating Office 365 Users and Licenses (Part-2)

Previous Post: In the first part of this article I talked about the steps necessary using PowerShell to find information about users on Office 365 and validate their license status. We were able to connect to Office 365 with PowerShell and search for users via several parameters. This search mechanism helps us resolve the users that have been synchronized or created in the cloud. It is rather easy as well to include additional search fields if users are somehow addressed by a different format for logons & UPNs, it does not need to explicitly be Display Name or Alias, and it could be any combination of searches specific to an organization. This method works extremely well for a single user that you want to validate, however what would you do if you had a group of users, say a list of users exported from a SharePoint site? It would be extremely helpful to iterate through that list and compare the users to users in Office 365 and see if they should be successfully migrated. Luckily PowerShell makes this scenario very simple and we need to follow these logical steps:

  • Get a List of SharePoint Users
  • Iterate through List of SharePoint Users and Search Office 365 for matching Cloud Users
  • Validate the Licenses of Each Matching User
  • Create a List of Matches, Misses, and license results
  • Output the list of Users

I have made the completed  PowerShell script available for download at the end of the article and the following steps explain the processing and setup of each section of the script. Following the first part of the article, we should be on a SharePoint Server in the Farm (in order to get the users) and have installed the PowerShell CommandLets for Office 365 as well as the login feature. In our script we then reference both the SharePoint CommandLets as well as the Office 365 ones in the following script header.


Once we have created the references to the right CommandLets, we have to set up the global variables for the script. The only real global variable is a data table(ValidatedUsers) that stores the results of each of the matching actions in the following columns Email – Local Email  (On premise reference) Alias – Logon Name (On premise reference) Display Name – Local Display Name  (On premise reference) Validation Result – Was the script able to find the user in Office 365 User Principal Name(UPN) – If found what is the sign in name Is Licensed – Does this user have a license assigned to it User Mapping – Field to Create User Mappings for 3rd Party Products


This section creates a data table object that we can reference throughout the script, as well as the columns that we referenced above, and then adds those columns to the newly created datatable. Once we have the datatable available as a reference, we need to see if we are already connected to Office 365 or if we need to initiate a request for credentials and then generate a new connection.


This section attempts to get the current subscription info as a test to see if the service is already connected. this is useful if you want to run multiple searches against sites in one window without re-authenticating every time. If we see that no subscription information was returned we need to initiate a connection and therefore we request the user credentials and attempt the Office 365 connection. Now that we’ve got the bulk of our preparation done for connecting to Office 365, we step into the Search User function of the script. The SeachUser function takes a SPUser object as a parameter and then uses properties of that user to attempt a match in the cloud.


We get the user properties, Email, LoginName (Alias), and Display name from the user object to be used in the search.


Then we run the searches in the following order against the user properties 1 Email -> 2 Alias -> 3 Display Name Hopefully we’ll never hit the third condition where the display name is searched since we would rather make a match on a unique value like an email or a domain logon.


If a user is found, we then do a quick test to make sure that the user actually has a license available, if not the user migration will fail. And once we have the licensing results we create a row for the data table and add cumulative information we’ve obtained to the row and then to the data table. Bonus: The UserMappingXML Field can be modified to suit the format of the third party tool you may be using, it is otherwise not used. The script also outputs to the console the status of each check when it is finalized along with some nifty coloring.


In the case that we don’t find a matching cloud user, we record the user information as a row in the data table as well along with the failed validation result, as well as outputting it to the console. That covers the SearchUser function, next we need to get a bunch of users from SharePoint and then pass them over to the search so we can validate them.  Since the script can take any SPUser Object, getting those objects can be modified to suit a users needs at this point.


This section access iterates through the sites in a specified web application and gets a gigantic list of users to test, adding each user to the $allusers object.


Once we have all the users to check its pretty simple to go through and validate each one using the above SearchUser function.


And Bonus, once the users have been validated and the table created, the table can be exported to a CSV file in the current directory. The filename is in the format “Results-sp2010-134134134134.csv” for uniqueness. To make this work in your environment, there are only two things that need to be changed:

  1. $web should be updated to point to a valid web application in your environment
  2. $searchdomain needs to be updated to the domain that the majority of your users log into SharePoint with

So now that you know how the script works, you can Download the Powershell Script Here
Bonus Update: Additional Script using users in a CSV file is available here

Leave a Reply

Your email address will not be published. Required fields are marked *