BitTitan PowerShell Tips: How to connect the BitTitan SDK to the German instance

As many of you might know, the BitTitan SaaS has multiple instances across the globe, such as:

If you’re using the BitTitan SDK, to automate most, if not all of your project tasks, keep in mind the following:

  • By default, the BitTitan SDK connects to the global instance
  • There is no specific version of the SDK to connect to a different instance
  • There are 2 cmdlets that allow you to connect to the German instance:
    • Set-BT_Environment -Environment Germany
    • Set-MW_Environment -Environment Germany
  • You need to run the cmdlets above before you create the BitTitan PowerShell ticket

The BitTitan SDK interacts with both our MSPC platform – for tasks such as managing customers, endpoints, DeploymentPro, etc – and with our MigrationWiz platform, to manage your migration projects among many other things. Depending on the platform you want to interact with, you’ll need to run one of the commands above, or both. The “BT” commands applies to MSPC and the “MW” command applies to MigrationWiz.

See below the sample code screenshot.

BTSDK1

On a side note, if you’re wondering what a BitTitan PowerShell ticket is (mentioned multiple times in this blog post), all of the BitTitan cmdlets are backed by a ticket, that determines which environment we’re connecting into (MSPC or MigrationWiz), which workgroup/account and has the credentials to access it.

For much more information on how to code with the BitTitan SDK, go here or ping me an email via the blog contact form.

Advertisements

[Updated Version] Office 365: Script to bulk change the UserPrincipalName to match the Email Address

As I was seeing a lot of feedback in my original post, regarding how the scripts below had issues, I decided to post this new updated version. I will underline the updates  to be easier to follow, but if you never read the original post, please try not to skip any parts in this one.

When you are preparing your local Active Directory, to be synced with Office 365, one of the things you should consider is to make the UserPrincipalName of each user you are syncing to match the user’s email address. Why? Because that is going to be his UserPrincipalName and his primary SMTP address on Office 365.

So there are different ways of achieving this, some more manual than others. The procedure I am going to outline today on this blog post is a two step procedure:

Step 1: Export all UserPrincipalNames and Email Addresses from the local AD to a CSV File.

Step 2: Use that CSV file to bulk change the UserPrincipalNames to match those Email Addresses.

Like I said there are different ways of doing this, and I will probably develop a more elaborated script that can do this in a single step. The reason I went for this two step process is because most of the times customers want to check the CSV generated on step 1, and remove all the users that they don’t want to change the UPN, because those users will not be synced to Office 365.

Before we detail the steps above, make sure that you’ve added additional UPN domain suffixes for all the primary SMTP domains that you will have. See the article “How to add UPN suffixes to a forest” for more information.

Also have a detailed read on the article “Prepare to provision users through Directory Synchronization to Office 365”, to fully understand all the tasks you have to do to prepare your local Active Directory.

Making the UPN’s match the email addresses and have a domain that is validated on Office 365 is just one of the several tasks you have to do.

Now back to the two step process to change those UPN’s.

Step 1:

On step one all you have to do is open a PowerShell module on your local AD, and run the cmdlet below.

#If needed Import the Active Directory Module into your PowerShell session before you run the cmdlet

Import-Module ActiveDirectory

#Run the cmdlet to export all the users to a CSV. Change the CSV name and path as appropriate

Get-AdUser -Filter * -Properties UserPrincipalName, Name, EmailAddress | ? {$_.UserPrincipalName -notlike "DiscoverySearchMailbox*" -and $_.UserPrincipalName -notlike "HealthMailbox*" -and $_.UserPrincipalName -notlike "SystemMailbox*" -and $_.UserPrincipalName -ne $null} | Select-Object UserPrincipalName, Name, EmailAddress | Export-CSV -Path C:\MyADUsers.csv -NoTypeInformation
UPDATE: I’ve added some additional filtering in this cmdlet, specifically to filter out users that don’t have a UserPrincipalName, or users for some types of Exchange system mailboxes such as the discovery search or health mailboxes. You do not want to run the script to change UPNs for system users or any user which is not a regular user that will be syncing up to Office 365. Make sure you filter the output file appropriately before you use it to change the UPNs. Below some example of users that you might still need to filter out from the output CSV.
UPNUpdate1

After you run the cmdlet you should get a CSV like the one shown below:

ChangeUPN1

On the example above you can see that the UserPrincipalName does not match the user’s email address, and therefore needs to be changed.

Once you get the CSV check all users that you want to change and remove from that CSV the ones that you don’t.

Step 2:

Now that you have the CSV with all the users you want to change, all you have to do on step 2 is run the script below. The script will change all the UPN’s to match the email address, based on the CSV file you will use.

#Script to Change the UPN on the Active Directory

#This script should run from an Active Directory Module for Windows PowerShell

#Version 2.0 - 06/22/2018

#Author: Antonio Vargas - antonio.vargas@myexchangeltd.co.uk

#Disclaimer: All scripts and other powershell references on this blog are offered "as is" with no warranty. While these scripts are tested and working in my environment, it is recommended that you test these scripts in a test environment before using in your production environment.

#Import the AD Module

Import-Module ActiveDirectory

#Static properties (change where needed)

$CSVPath = "C:\MyADUsers.csv"

#Count variables

$usersprocessed = 0

$userswitherrors = 0

$usersskipped = 0

#Import CSV

Try {

$CSV = Import-Csv -Path $CSVPath -ErrorAction Stop

}

Catch {

Write-Host "ERROR: Cannot import the CSV file. The script will abort. '$($Error[0].Exception.Message)'" -foregroundcolor Red

Exit

}

Write-Host "INFORMATION: The CSV was imported and you have '$($CSV.count)' users to be processed." -foregroundcolor Green

ForEach ($line in $CSV) {

$UPN = $line.UserPrincipalName

$Email = $line.EmailAddress

if ($UPN -eq $Email) {

Write-host "SKIPPING: The UPN '$($UPN)' matches the email address" -foregroundcolor Yellow

$usersskipped++

}

Else {

try {

$ADUser = Get-ADUser -Filter {UserPrincipalName -eq $UPN -and Enabled -eq $true} -ErrorAction Stop

If ($ADUser -eq $null) {

write-host "SKIPPING: The user '$($UPN)' is disabled or cannot be found." -foregroundcolor Yellow

$usersskipped++

}

Else {

Write-Host "Working on User '$($AdUser.UserPrincipalName)'" -foregroundcolor Yellow

try {

$result = Set-ADUser -Identity $ADUser.SamAccountName -Userprincipalname $Email -ErrorAction Stop

$usersprocessed++

Write-Host "SUCCESS: UPN Changed from '$($AdUser.UserPrincipalName)' to '$($Email)'." -foregroundcolor Green

}

catch {

Write-Host "ERROR: Cannot change the UPN of the user '$($AdUser.UserPrincipalName)'. '$($Error[0].Exception.Message)'." -foregroundcolor Red

$userswitherrors++

}

}

}

Catch {

Write-Host "ERROR: Cannot retrieve user '$($UPN)'. '$($Error[0].Exception.Message)'." -foregroundcolor Red

$userswitherrors++

}

}

}

write-host "`n"

write-host "############################# REPORTS ####################################" -foregroundcolor Green

Write-Host "REPORT: Total number of users processed with success '$($usersprocessed)'" -foregroundcolor Green

Write-Host "REPORT: Total number of users that were skipped for not meeting the criteria '$($usersskipped)'" -foregroundcolor Yellow

Write-Host "REPORT: Total number of users that failed to process '$($userswitherrors)'" -foregroundcolor Red

Copy the entire content above into a notepad, and save it as a .ps1 file.

Some changes done to the script from the original blog post:

  • Error handling added
  • the script imports the Active Directory module
  • added count for users done with success, skipped or failed
  • small report at the end
  • the entire logic of the code on when to process users was changed 

Disclaimer: All scripts and other PowerShell references on this blog are offered “as is” with no warranty. While these scripts are tested and working in my environment, it is recommended that you test these scripts in a test environment before using in your production environment.

I highly recommend running the script first against a small group of up to 5 users, and then make sure that the changes were applied successfully. Also you need to take into account that you are changing the UserPrincipalName of the user on your local Active Directory, so make sure to test the access to all internal systems that rely on AD for authentication, before you replicate the change to all of your users.

For large environments, if you want a version of the script that exports to CSV all the user results (i.e changed, skipped, failed) feel free to send me an email via the blog.

Go ahead and test the script with its new changes and let me know how that goes.

As always, if you have any questions please let me know.

Exchange Public Folders: Export item count, per item type, of your public folder structure

Just recently, I was asked to help investigate which Exchange cmdlets would help a partner the I work with, do an item count in an on premises Exchange Public folder structure. Their specific ask was to get, per folder, the number of contact items.

So starting with the best command to do this, it’s easy to get to the conclusion that it will be the Get-PublicFolderItemStatistics, and the first thing that you need to know about that cmdlet is that it’s only available in Exchange 2010+.

The second thing you need to focus on is, in which folders do you want to run the count on? All of them? And if not all, do you want to run the count based on folder type? i.e do you want to just count calendar items on folders of type calendar? How can we achieve this?

Lets break this down:

  • To be able to select the folders you want to count the items for, you need of course to start with the Get-PublicFolder cmdlet
  • If you want to filter just one or multiple folder type (i.e Calendar, Contacts, etc) you need to do it using the “FolderClass” attribute.

Note: The “FolderClass” attribute doesn’t exist in all versions of Exchange. I haven’t checked in detail but at least apparently in Exchange 2010 you won’t be able to leverage this attribute to filter just the folders you want. Worst case scenario you can always run a count against all folders. Also note that as you can see below, not all folders have a “FolderClass”.

PFCount1

And finally the code to grab all the folders you want.

With the FolderClass attribute filtering:

#Get all folders
$folders = get-publicfolder \ -recurse -resultsize unlimited | ? {$_.FolderClass -like “IPF.Contact”}
And without:
#Get all folders
$folders = get-publicfolder \ -recurse -resultsize unlimited

 

Note: The Where-Object filtering (? sign in the command above) in PowerShell caches all its results into memory, so if you have a very large public folder structure you might want to have that in mind and run the commands in a machine with enough resources.

Now that we know how to grab all the folders we need, lets look at how to do the folder count:

  • The command used to do the folder count is, as mentioned above in this post, the Get-PublicFolderItemStatistics
  • Because all you want to do is count items of a certain type, you will leverage the “ItemType” attribute in your filtering
  • Don’t forget that the Get-PublicFolderItemStatistics is an Exchange 2010+ cmdlet

Below see the output of an item count of a specific folder.

PFCount2

Now, finally, the entire script (in bold the item count):

PFCount4

(and the copy/paste version)
#Get all folders
$folders = get-publicfolder \ -recurse -resultsize unlimited | ? {$_.FolderClass -like “IPF.Contact”}
#Process All folders
Foreach ($folder in $folders){
$ContactCount = 0
$Contacts = get-publicfolderitemstatistics $Folder.Identity|? {$_.ItemType -like “IPM.Contact”}
If($Contacts -eq $null){
Write-Host”The folder ‘$($Folder.Identity)’ has 0 Contacts”
}
Else{
foreach($Contact in $Contacts){
$ContactCount++
}
Write-Host”The folder ‘$($Folder.Identity)’ has $($ContactCount) Contacts”
}
}
Lets break down the script above:
  • we start by getting all folders of class contact. Again you can do this filtering or not, depending on the Exchange version and what you need exactly.
  • we then enter a loop where, for each folder, we will grab all items of type contact and count them
  • once that is done we write the output into the console

This script is very simple and doesn’t have error handling, logging and output to CSV. If you want those features feel free to contact me via the blog and I can build you a very complete version of the script.

Running the simple version of the script in a large environment can make the results difficult or impossible to analyse, however, with the code above gives you an insight in how to filter and count Public folders, by type and class.

As always I hope this is helpful.