## The pain in the a** that is special characters. Understanding what is and isnt supported when migrating to the Microsoft Cloud.

So in recent months, I have been working a number of large organisation that have issues with special characters that are affecting their migration to the Microsoft Cloud. Yes, I IDFix does an excellent job of correcting a lot of the issues. However, in recent time I have been rolled into customer sites to troubleshoot and report on special characters contained in Distribution Lists and Shared Mailboxes which cannot be migrated to Exchange Online.

## What special characters are supported in Office 365?

So first of all, what is and is not supported. The below table gives an excellent break down what the character can be supported in UserNames, Password and Email Addresses.

 Allowed In Character Name Character User Name Password Email Address Accent  No Yes No Ampersand & No Yes No Angle Brackets < > No Yes No Apostrophe ’ No Yes Yes*** Asterisk * No Yes No At Symbol @ No Yes No Backslash \ No Yes No Braces [ ] No Yes No Brackets { } No Yes No Circumflex ^ No Yes No Colon : No Yes No Comma , No Yes No Dollar Sign $No Yes No Equal Sign = No Yes No Exclamation Point ! No Yes No Hyphen – Yes* Yes Yes* Number Sign # No Yes No Parentheses ( ) No Yes No Percent Symbol % No Yes No Period . Yes* Yes Yes* Pipe | No Yes No Plus Sign + No Yes No Question Mark ? No Yes No Quotation Mark “ No Yes No Semicolon : No Yes No Forward Slash / No Yes No Tilde ~ No Yes No Underscore _ Yes** Yes Yes** Uppercase Letters (A-Z) A-Z Yes Yes Yes Lowercase Letters (a-z) a-z Yes Yes Yes Numerals (0-9) 0-9 Yes Yes Yes In order to test for the special characters above I have created the following script  12345678910111213141516171819202122232425cls$array = @('~', '!', '#', '$', '%', '^', '&amp;', '(', ')', '-', '.+', '=', '}', '{', '\', '/', '|', ';', ',', ':', '&lt;', '>', '"')$samaccountarray = @('[', '\', '"', '|' , ',' , '/', ':', '&lt;', '>', '+', '=', ';', ']')
foreach ($char in$array) {
Write-Host "Please Wait... Detecting",$char," in samaccountname" -ForegroundColor Yellow$objects = Get-distributiongroup
foreach ($object in$Objects)
{
try {
if ($object.SamAccountName -like "*$char*")
{
Write-Host "Special Character",$char,"detected in SamAccountName",$object.samaccountname -ForegroundColor Red

}
else
{
#Write-Host "Special Character",$char," not detected in "$object.UserPrincipalName
}
}
catch
{
Write-Host "Great News!! we was unable to detect",$char,"in samaccountnames for all Distribution List" -ForegroundColor Green } } }  Get-SpecialCharacters (8 downloads) If you are interested in understanding what IDFix does and what special characters are not supported, please see this link https://docs.microsoft.com/en-gb/office365/enterprise/prepare-for-directory-synchronization?redirectSourcePath=%252fen-us%252farticle%252fPrepare-to-provision-users-through-directory-synchronization-to-Office-365-01920974-9e6f-4331-a370-13aea4e82b3e Regards The Author – Blogabout.Cloud ## Get Disabled Users who have an Exchange Mailbox with PowerShell If there’s one thing most IT department are not great at its removing Exchange Mailboxes for Disabled Users. So here’s a quick Powershell win to determine who within your Exchange organisation has a mailbox and a disabled AD account. ## On-Premises Users  123456789$Mailboxes = Get-Mailbox | where {$_.RecipientTypeDetails -eq 'UserMailbox'}$Disabled = @()

Foreach ($Mailbox in$Mailboxes) {
if((Get-ADUser -Identity $Mailbox.SamAccountName).Enabled -eq$False){
$Disabled += Get-MailboxStatistics$Mailbox.SamAccountName | Select -Property DisplayName,TotalItemSize
}
}
$Disabled | Export-Csv -Path$env:userprofile\desktop\DisabledADUserwithMailbox.csv -NoTypeInformation



## Cloud Users


1234567891011Connect-MsolService

$Mailboxes = Get-Mailbox | Where-Object {$_.RecipientTypeDetails -eq 'UserMailbox'}
$Disabled = @() Foreach ($Mailbox in $Mailboxes) { if((Get-msolUser -userprincipalname$Mailbox.userprincipalname).Enabled -eq $False){$Disabled += Get-MailboxStatistics $Mailbox.userprincipalname | Select-Object -Property DisplayName,TotalItemSize } }$Disabled | Export-Csv -Path $env:userprofile\desktop\DisabledAzureADUserwithMailbox.csv -NoTypeInformation  Regards The Author – Blogabout.Cloud ## Method invocation failed because [System.Management.Automation.PSObject] doesn’t contain a method named ‘op_Addition’. While constructing a PowerShell script for gathering information about Distribution Lists within a customers environment, I ran into the following error Method invocation failed because [System.Management.Automation.PSObject] doesn’t contain a method named ‘op_Addition’.  1 This error was being generated by a missing array within my PowerShell code  12345678910111213141516171819202122232425262728293031# Call Distribution Lists$dist = @(Get-DistributionGroup -resultsize unlimited)

# Start Transcript
Start-Transcript -Path $env:USERPROFILE\desktop\DLsandMember.txt # Report on Distribution List foreach ($dl in $dist) {$count =@(Get-DistributionGroup $dl.samaccountname).count$report = New-Object -TypeName PSObject
$report | Add-Member -MemberType NoteProperty -Name 'Group Name' -Value$dl.Name
$report | Add-Member -MemberType NoteProperty -Name 'samAccountname' -Value$dl.samaccountname
$report | Add-Member -MemberType NoteProperty -Name 'Group Type' -Value$dl.grouptype
$report | Add-Member -MemberType NoteProperty -Name 'DN' -Value$dl.distinguishedName
$report | Add-Member -MemberType NoteProperty -Name 'Manager' -Value$dl.managedby
$report | Add-Member -MemberType NoteProperty -Name 'Member Depart Restriction' -Value$dl.memberdepartrestriction
$report | Add-Member -MemberType NoteProperty -Name 'Member Join Restriction' -Value$dl.memberjoinrestriction
$report | Add-Member -MemberType NoteProperty -Name 'PrimarySMTPAddress' -Value$dl.primarysmtpaddress
$report | Add-Member -MemberType NoteProperty -Name 'EmailAddress' -Value$dl.emailaddresses
$report | Add-Member -MemberType NoteProperty -Name 'GrantSendOnBehalfto' -Value$dl.GrantSendOnBehalfto
$report | Add-Member -MemberType NoteProperty -Name 'EmailAddressPolicyEnabled' -Value$dl.EmailAddressPolicyEnabled
$report | Add-Member -MemberType NoteProperty -Name 'Number of Members' -Value$count
Write-Host ('INFO: {0} has {1} members' -f $dl.name, ($count))

$reportoutput +=$report
}

# Stop Transcript
Stop-Transcript



By adding the following lines to my above script I was able to successful export the required information into an Array and dump out to CSV.


12# Array
$reportoutput=@()  Regards The Author – Blogabout.Cloud ## PowerShell – ForEach do action X or do Y PowerShell is one of the greatest tools within any IT Professional toolkit, it enables you to do far more than any GUI available to you today. In my life as a Consultant for a Global Microsoft SI (System Integrator), I face challenges every day where PowerShell has come to the rescue. One of the best cmdlet I use in a lot of script is ForEach which is the alias name of ForEach-Object Imagine you need to modify an ExtensionAttribute for your entire organization or grant a permission to a subset of users, ask yourself this? How would I do this in a GUI? and the answer would be “with great difficulty or very time consuming”. This is Foreach-Object comes into play, in the below example I need to modify the PrimarySMTPAddress due to special characters being used In order to correct this, I will be using a source CSV file which contains SamAccountName for the identity of each DistributionList and the correct PrimarySMTPAddress. Now for the most important element, the powershell script which will be used to modify the PrimarySMTPAddress. The below script has been designed to achieve the required outcome but also includes the ability to; • Be ran using native PowerShell for On-Premises Exchange Servers (2007 through to 2019) • Be ran against Exchange Online So as we can see the Foreach command is being used in the following; • For each$row within the $csv which is being imported try and get the distribution list using the column heading SamAccountName • If the Identity cannot be found the script will move to the catch • If the Identity can be found the script will set the distribution list using the column heading PrimarySMTPAddress • The catch is alert if there are any unsuccessful attempts at setting the PrimarySMTPAddress Simples!!  Clear-Host$file = "$env:USERPROFILE\OneDrive\Desktop\groups.csv"$csv = import-csv -Path $file region Exchange Module SnapIn # Exchange 2007 #Add-PSSnapin Microsoft.Exchange.Management.PowerShell.Admin; # Exchange 2010 #Add-PSSnapin Microsoft.Exchange.Management.PowerShell.E2010; # Exchange 2013/2016 #Add-PSSnapin Microsoft.Exchange.Management.PowerShell.SnapIn; endregion Transcript Start-Transcript -Path$env:USERPROFILE\OneDrive\Desktop\Get-DistributionGroup.txt Foreach ($row in$csv) {   try {     Get-DistributionGroup -Identity $row.SamAccountName | Set-DistributionGroup -PrimarySmtpAddress$row.PrimarySmtpAddress     Write-Host 'INFO:' ($row.SamAccountName),'Primary SMTP Address has now been modified to',($row.PrimarySmtpAddress) -BackgroundColor Green   }   catch   {     Write-Host 'ERROR:' ($row.SamAccountName),'Primary SMTP Address has not been modified to',($row.PrimarySmtpAddress) -BackgroundColor Red   } } Stop-Transcript Get-DistributionGroup

I have included Start-Transcript as this will dump out all Write-Host entry whether they was successful or not.

Regards

## Import Exchange PowerShell Module into your PowerShell ISE console

When working with Exchange there may be a requirement to create a PowerShell script using PowerShell ISE. Even if you run ISE on a Exchange Server you are unable to get the Exchange cmdlet in ISE, so the workaround for this is to use the following command;

• If you are trying to add the Exchange cmdlets to your client machine you will need to Install the Exchange Management Tools from the Exchange installation media

The command to import the Exchange modules is different for each version – please use the appropriate command below:

Regards

## Do I have duplicate Recipient Alias within my Exchange organization?

So do you know if you have duplicate recipient alias within your Exchange organisation? Heres a quick script that will look at your Exchange Environment and download all recipient address into a handy csv file you to play with.

Regards

## QuickTip: PowerShell scripting – How long did it take to run the script?

Have you ever wondered how long it took to run your script? Well, you dont need to wonder anymore. The following couple of lines will provide a visual output how long it take to execute your script from start to finish

$Start = [system.datetime]::Now { Script run…. }$End = [system.datetime]::Now

Regards

## Merging Excel files using PowerShell, yes it can be done.

Have you ever worked with Excel files where you wanted to match and compare Columns/Rows? In the past, this has been quite difficult tasks to achieve using the native commands within PowerShell.

So have you heard of the PowerShell module ImportExcel?

It’s is a PowerShell module that is available on the PowerShell Gallery and introduces a number of functions that allow you to work with Excel files using the good old blue background.

From this module we will be working with the following function;

• Merge-Worksheet

Syntax
Merge-Worksheet [-Referencefile] [-Differencefile] [[-WorksheetName] ] [-Startrow ]
-Headername [[-OutputFile] ] [[-OutputSheetName] ] [-Property ] [-ExcludeProperty ]
[-Key ] [-KeyFontColor ] [-ChangeBackgroundColor ] [-DeleteBackgroundColor ]
[-AddBackgroundColor ] [-HideEqual] [-Passthru] [-Show] [-WhatIf] [-Confirm] []

## Example usage of Function

The below shows the Reference and Difference Excel files that are being used in this example. I am going to merge the two excel files based on Column A the EmployeeNumber. During my testing, I have had issues using -HeaderName parameter. In this post I will not be specifying the headings and just modify the output file.

# Variables
$ref = “$env:USERPROFILE\desktop\test\ref.xlsx”
$dif = “$env:USERPROFILE\desktop\test\dif.xlsx”
$out = “$env:USERPROFILE\desktop\test\out.xlsx”

# Script Block
Merge-Worksheet -Referencefile $ref -Differencefile$dif -OutputFile \$out -WorksheetName Sheet1 -Startrow 1 -OutputSheetName Sheet1 -NoHeader

As we can see from below, the output field has organised Column A and aligned the rows

Every useful if you are working with Excel files but only annoying thing is the HeaderName parameter not working.

Regards