Have you ever been troubleshooting Exchange Online (EXO) and MSOnline (Azure) objects and wished there was a way to aggregate all the data together into a single object that you could manipulate either via script or pipeline, output via FT, manipulate or otherwise report on?  

The following script will accept either UPN or ObjectID, locate the object in MSOnline, then find the associated Exchange online object, either User, MailUser or UserMailbox, and create a new object with a combination of all the object attributes from both Azure and EXO.   


Be sure to read the help and examples provided in the function.  

 

<#

.SYNOPSIS

This command will accept either ObjectID or UserPrincipalName, locate the MSOLUser account and combine with the EXO user.

.DESCRIPTION

This command will accept either ObjectID or UserPrincipalName, locate the MSOLUser account and combine with the Exchange Online object, either UserMailbox, MailUser or User to create a new single object with all the attrbutes from both MSOL and EXO.

All MSONLINE attributes will be prefixed with MSOL.

All Exchange Online UserMailBox attributes will be prefixed with EXOMBX.

All Exchange Online MailUser attributes will be prefixed with EXOMUSR.

All Exchange Online User attributes will be prefixed with EXOUSR.

If the object is not a particular type (e.g. Exchange Online Mail User) those attributes won't be included since they would all be null.

Additionally, the boolean values IsEXOMailBox, IsEXOuser and IsEXOMailUser are added to every output object so they can be used for evaluation purposes.

Lastly, if the MSOL user validation status is ERROR, two additional values, MSOLValidationStatusService and MSOLValidationStatusErrorMessage

are added to the object properties with error details.

IMPORTANT :

*** This cmdlet assumes you have the MSONLINE powershell module loaded and have connected to Azure.

*** This cmdlet assumes you have the Exchange Online PSSNAPIN loaded with the PREFIX EXO switch set and have connected to Exchange Online.

.PARAMETER UPN

User Principal Name to be used to search MSONLINE

.PARAMETER ObjectID

Object ID value to be used to search MSONLINE

.EXAMPLE

Get-O365User.ps1 userUPN@tenant.onmicrosoft.com

Passes the value userUPN@tenant.onmicrosoft.com to the script to locate the MSONLINE user

.EXAMPLE

Get-O365User.ps1 -UserPrincipalName userUPN@tenant.onmicrosoft.com

Passes the value userUPN@tenant.onmicrosoft.com to the script to locate the MSONLINE user

.EXAMPLE

Get-O365User.ps1 -ObjectID cd94fe89-4b2e-4bc9-888a-3fc650c96816

Passes the ObjectID value to the script to locate the MSONLINE user

.EXAMPLE

Get-MSOLUser -Userprincipalname XXXXXX@tenant.onmicrosoft.com | Get-O365User

Passes the UserPrincipalName value from the Get-MSOLUser command down the pipeline to the Get-O365User command.

.EXAMPLE

$date = [datetime] "4/1/2014 12:00:00"

Get-MSOLUser -all | where {$_.lastdirsynctime -lt $date} | Get-O365User | Select *Userprin*, *Externalemail*

Finds any MSOLUser who hasn't been dirsynced since April 1, 2014 at noon, passes that list of users down the pipeline

to the Get-O365User command and returns the UserprincipalName and ExternalEmailAddress (if exists) for each user

.INPUTS

UserPrincipalName

ObjectID

.OUTPUTS

Aggregated PSObject

.NOTES

NAME: Get-O365User.ps1

AUTHOR: Darryl Kegg

DATE: 20 April, 2014

EMAIL: dkegg@microsoft.com

REQUIREMENTS:

-Connection to Exchange online with -PREFIX EXO

-Connection to MSONLINE

VERSION HISTORY:

1.0 20 April, 2014

Initial Version

#>

Function Get-O365User

{

[CmdletBinding()]

param

(

[Parameter(Mandatory = $false,ValueFromPipeline=$true,ValueFromPipeLineByPropertyName=$true)]

[string]$UserPrincipalName,

[Parameter(Mandatory = $False,ValueFromPipeline=$true,ValueFromPipeLineByPropertyName=$true)]

[string]$ObjectID

)

BEGIN {}

PROCESS{

$msoluser = Get-MsolUser -UserPrincipalName $UserPrincipalName -ErrorAction SilentlyContinue

if (!($msoluser)) {write-host -fore Red "MSOLUser provided does not exist";exit}

$MSOLUSERproperties = $msoluser | get-member

$objTemplateObject = New-Object psobject

# set variables to null

$exomailbox = $null

$exomailuser = $null

 

# Get EXOUSER and then branch based on USERMAILBOX versus USER versus MAILUSER

$exouser = get-exouser ($msoluser.userprincipalname) -erroraction silentlycontinue

if (!($exouser))

{

$objTemplateObject | Add-Member -MemberType NoteProperty -Name "IsEXOMailBox" -Value $false

$objTemplateObject | Add-Member -MemberType NoteProperty -Name "IsEXOMailuser" -Value $false

$objTemplateObject | Add-Member -MemberType NoteProperty -Name "IsEXOuser" -Value $false

}

if ($exouser -and $exouser.recipienttype -eq "UserMailbox")

{

$exomailbox = get-exomailbox $exouser.userprincipalname

$exouser = $null

$objTemplateObject | Add-Member -MemberType NoteProperty -Name "IsEXOMailBox" -Value $true

$objTemplateObject | Add-Member -MemberType NoteProperty -Name "IsEXOMailuser" -Value $false

$objTemplateObject | Add-Member -MemberType NoteProperty -Name "IsEXOuser" -Value $true

}

if ($exouser -and $exouser.recipienttype -eq "MailUser")

{

$exomailuser = get-exomailuser $exouser.userprincipalname

$exouser = $null

$objTemplateObject | Add-Member -MemberType NoteProperty -Name "IsEXOMailBox" -Value $false

$objTemplateObject | Add-Member -MemberType NoteProperty -Name "IsEXOMailuser" -Value $true

$objTemplateObject | Add-Member -MemberType NoteProperty -Name "IsEXOuser" -Value $true

}

if ($exouser -and $exouser.RecipientType -eq "User")

{

$objTemplateObject | Add-Member -MemberType NoteProperty -Name "IsEXOMailBox" -Value $false

$objTemplateObject | Add-Member -MemberType NoteProperty -Name "IsEXOMailuser" -Value $false

$objTemplateObject | Add-Member -MemberType NoteProperty -Name "IsEXOuser" -Value $true

}

 

# create the properties for MSOLUSER

foreach ($property in $MSOLUSERproperties)

{

if ($property.membertype -eq "Property")

{

$objTemplateObject | Add-Member -MemberType NoteProperty -Name "MSOL$($property.Name)" -Value $Null

}

}

# Add 2 properties if the object has a validation status of ERROR

if ($msoluser.validationstatus -eq "Error")

{

# add members here if its in validation status error

$objTemplateObject | Add-Member -MemberType NoteProperty -Name "MSOLValidationStatusService" -Value $Null

$objTemplateObject | Add-Member -MemberType NoteProperty -Name "MSOLValidationStatusErrorMessage" -Value $Null

}

 

# Create the properties for UserMailBox if exists

if ($exoMailbox)

{

 

$EXOMAILBOXproperties = $exomailbox | get-member

foreach ($property in $EXOMAILBOXproperties)

{

if ($property.membertype -eq "Property")

{

$objTemplateObject | Add-Member -MemberType NoteProperty -Name "EXOMBX$($property.Name)" -Value $Null

}

}

}

if ($exomailuser)

{

$exomailuser = get-exomailuser ($msoluser.UserPrincipalName) -erroraction silentlycontinue

$EXOMAILUSERproperties = $exomailuser | Get-Member

foreach ($property in $EXOMAILUSERproperties)

{

if ($property.membertype -eq "Property")

{

$objTemplateObject | Add-Member -MemberType NoteProperty -Name "EXOMUSR$($property.Name)" -Value $Null

}

}

}

if ($exouser)

{

$EXOUSERproperties = $exouser | Get-Member

foreach ($property in $EXOUSERproperties)

{

if ($property.membertype -eq "Property")

{

$objTemplateObject | Add-Member -MemberType NoteProperty -Name "EXOUSR$($property.Name)" -Value $Null

}

}

}

# Done deciding what properties to add to the new Object, now lets populate those values

$objTemp = $objTemplateObject | Select-Object *

# populate the MSOLUSER values

foreach ($property in $MSOLUSERproperties)

{

if ($property.membertype -eq "Property")

{

$PropName = "MSOL$($property.name)"

 $objTemp.$propname = $msoluser.($property.Name)

}

}

if ($msoluser.ValidationStatus -eq "Error")

{

$objTemp.MSOLValidationStatusService = $msoluser.Errors.ErrorDetail.Name.split("/")[0]

$objTemp.MSOLValidationStatusErrorMessage = $msoluser.Errors.ErrorDetail.ObjectErrors.ErrorRecord.ErrorDescription

}

# populate the EXOMAILBOX values

If ($exomailbox)

{

foreach ($property in $EXOMAILBOXproperties)

{

if ($property.membertype -eq "Property")

{

$PropName = "EXOMBX$($property.name)"

 $objTemp.$propname = $exomailbox.($property.Name)

}

}

}

# populate the MAILUSER values

If ($exomailuser)

{

foreach ($property in $EXOMAILUSERproperties)

{

if ($property.membertype -eq "Property")

{

$PropName = "EXOMUSR$($property.name)"

 $objTemp.$propname = $exomailuser.($property.Name)

}

}

}

# populate the EXOUSER values

If ($exouser)

{

foreach ($property in $EXOUSERproperties)

{

if ($property.membertype -eq "Property")

{

$PropName = "EXOUSR$($property.name)"

 $objTemp.$propname = $exouser.($property.Name)

}

}

}

$objtemp

}

}#PROCESS