Monday, 16 July 2018

Confused about deprecated O365 commands?



I was getting pretty confused with the various options around powershell commands to use with Exchange online.  For example, to add a user to a distribution group in O365, I had come across 4 different commands:









So after some digging I realised that the *-AzureRM* are powershell cmdlets to modify general Azure resources using the Azure Resource Manager model – read more here (first couple of links are most useful)


Furthermore, the current way to manipulate Azure AD is to use the V2 cmdlets:  *-AzureAD* read more here 


The older *MSOL* cmdlets have been completely replaced by the *-azureAD* cmdlets.  Although the older cmdlets still work, they have been marked as deprecated so at some point they will stop but that might not be for a while. Read more here.


The Add-DistributionGroupMember cmdlet applies to Exchange and Exchange Online.  Given that Microsoft haven’t given any indication that they are likely to remove support for hybrid environments it is likely these will be around for a while.





Friday, 13 July 2018

Powershell script for creating an O365 cloud mailbox within a hybrid exchange environment



I recently wrote this script that creates an O365 mailbox within a hybrid exchange environment, creating all the necessary attributes etc in exchange and AD

Log all output to a local logfile, that is unique each time and won't get overwritten



Start-Transcript -Path $env:LOCALAPPDATA"\Cloudwyse\Logs\"$(get-date -Format ddMMyy_HHmmss)".log" -NoClobber



Clear output from the screen to prevent previous command being sent as first name






Prompt user to enter the details of the new account



$FirstName = Read-Host -Prompt "Carefully type the user`'s First name"

$SecondName = Read-Host -Prompt "Carefully type the user`'s Second name"



Format the AD fields in the right way



$UserName = $FirstName.ToLower() + "." + $SecondName.ToLower()

$DisplayName = (Get-Culture).TextInfo.ToTitleCase($FirstName.ToLower() + " " + $SecondName.ToLower())

$ProperFName = (Get-Culture).TextInfo.ToTitleCase($FirstName.ToLower())

$ProperSName = (Get-Culture).TextInfo.ToTitleCase($SecondName.ToLower())

$UPN = $UserName + ""

write-host -ForegroundColor Green "Your User`'s DisplayName is $($DisplayName)"

write-host -ForegroundColor Green "Your User`'s Username is $($UserName)"



Get credentials for the new user account and the connection to the on-prem exchange server



$UserCreds = Get-Credential -UserName "DO NOT EDIT THIS FIELD" -Message "Please set the password for the new user"

$ExchangeCreds = Get-Credential -UserName "CONTOSO`\" -Message "Please enter your credentials which are required to connect to CONEXCH01"

write-host -ForegroundColor Green "Your User`'s UPN is $($UPN)"



Connect to on-prem exchange and create mailbox



$Session = New-PSSession -ConfigurationName Microsoft.Exchange -ConnectionUri -Authentication Kerberos -Credential $ExchangeCreds

Import-PSSession $Session

New-RemoteMailbox -Name $DisplayName -FirstName $ProperFName -LastName $ProperSName -Password $UserCreds.Password -UserPrincipalName $UPN -OnPremisesOrganizationalUnit " Users/Swap"



Disconnect from exchange and stop logging



Remove-PSSession $Session

write-host -ForegroundColor Green "The script completed, any errors will appear in the log file"





Thursday, 12 July 2018

Adding Users to O365 Distribution List


A script I recently used to add members to an office 365 distribution group using a remote exchange session in a hybrid setup (covered at the end). 


$SourceFile = "<path to file>"

Import-CSV $SourceFile | ForEach `

{Add-DistributionGroupMember -Identity "Group Name" -Member $_.UPN

Write-Host -ForegroundColor Green "Processed the record for $($_.UPN)"




CSV file contains UPNs of all users to be added.


I also found it useful to see who had permissions to send to this group using



(Get-DistributionGroup -Identity "Group Name").AcceptMessagesOnlyFrom | ForEach {Get-User -Identity $_}



To open remote exchange shell:



$UserCredential = Get-Credential



A prompt will appear for your login credentials then,



$Session = New-PSSession -ConfigurationName Microsoft.Exchange -ConnectionUri -Credential $UserCredential -Authentication Basic -AllowRedirection

Import-PSSession $Session




Tuesday, 10 July 2018

Add New Users using Exchange Admin Center (Exchange 2016)

This only applies to new Active Directory users.  To look at how to use SMTP matching to link an on-prem user to an existing O365 mailbox in a hybrid environment follow this guide.
1. Log into the Exchange Admin Center:
2. In the EAC console of your on-premises hybrid server, go to Recipients > Mailboxes and click on the plus sign above the “Display Name” column and choose “Office 365 mailbox.”

3. Complete all the fields as required and click save. You can edit the user’s mailbox properties afterwards to add information such as title, manager, address and phone number if you wish.  Exchange will automatically create the AD account for you.

4. Sync using AD Connect. 
You can either wait for the next sync cycle or force it.  The user will appear in Office 365 and an Exchange Online mailbox will be provisioned not long afterwards. Once everything is synced you can add a license.
5. License the User.
1. Go to
2. Select the Admin tile
3. Go to Users and choose Active users
4. Select the user in question, go to the Product Licenses field and click Edit
5. Choose a location then click the slider to activate an available license
At the bottom of the Product licenses pane, choose Save

O365 hybrid setup - how to use SMTP matching to match an on-prem user to an O365 account



The scenario is that a user account has been created in Office 365 in a hybrid setup. This scenario is actually ok and is supported by Microsoft. However, it causes problems for an Office 365 user when they require access to public folders on the on-premises Exchange server.


First make sure you have the correct UPN for the online account by running the following (you'll have to have the msonline module by following this guide but please note some of these commands are now deprecated so would need to be manually added to powershell).



Get-MsolUser -SearchString "foo" | select-object Displayname, UserPrincipalName, ProxyAddresses





Foo Bar      









Create a user object in your local AD with the same attributes as the one in O365 (first name, last name, UPN, etc.).


Set up the primary SMTP address for the AD object so that it is the same as the capitalised SMTP address in the previous step eg


You can do this in Active Directory either by adding the address into the email field on the general tab or by adding it to the proxyAddresses attribute directly (you will need to enable advanced features from the view settings in active directory to be able to see the Attributes tab).  The second option is probably better as we need to add the other email aliases anyway.  Add them in this format (the capitalised address will be your primary SMTP address):


Force a manual sync of AD


repadmin /syncall /APed



Force a manual sync of AAD Connect


Start-ADSyncSyncCycle -PolicyType Delta









In the exchange admin centre you should see the status change from "Cloud" to "Synced with Active Directory"


Don’t forget the online account password will have changed to the one you specified when you created the AD account.




Set O365 Password to never expire for just one user



Recently I needed to do this for our PRTG alerting account which was failing to send notifications as the O365 password had expired.  I did this from Powershell within Windows 10 as follows:

Launch powershell as Administrator then run


Install-Module MsOnline



Then run





at this point an O365 authentication box pops up - enter your credentials. Once connected run:


Set-MsolUser -UserPrincipalName -PasswordNeverExpires $true



Some of these commands have since been deprecated. For an explanation look at this post.



Thursday, 5 July 2018

Add AD security group to local administrators on Hyper-V server running core



First connect to the remote server with powershell



Enter-PSSession -ComputerName contosohv01



Next run the command to add the group:



Add-LocalGroupMember -Group "Administrators" -Member "CONTOSO\Hyper-V Admins"



If you're paranoid (like me) and want to check this worked you can use:



Get-LocalGroupMember "Administrators"




Wednesday, 4 July 2018

Configuring log-on scripts to run via powershell from the "Run" key in Windows registry


If you’ve tried to add a powershell script to a registry run key, you’ve probably discovered that it doesn’t run with powershell.  Instead, Windows just opens the script in Notepad and leaves it sitting there all naked and exposed!  So in order to launch the powershell scripts we’re going to need to use a .bat or .cmd file launched from the run key in the registry.  So we’re going to add a string (REG_SZ) to






When you create the key you can call it whatever you like but the value has to be exactly right – and point to the script you want to launch.  In my case this is:



Cloudwyse Scripts


cmd /c START /MIN "Cloudwyse Env Execution" cmd /c "C:\Cloudwyse\Scripts\lch_powershell.cmd"



So I’m telling windows to launch a minimised command prompt, and then I’m passing the command I want running within that command prompt which means that users won’t have a big black box pop up on their screen everytime they log in.  Within that .cmd script, I need to launch Powershell but if I just go ahead and use the “powershell -File” command then I will hit issues with the execution policy within Windows which is disabled by default.  So we need the scripts to bypass the Powershell execution policy, but we don’t necessarily want to change the execution policy for the whole server for good.  So we can use this within the .cmd file:



@ECHO OFF SET CloudwyseScriptsDIR=C:\Cloudwyse\Scripts\

SET PSScriptPath=%CloudwyseScriptsDIR%wrapper.ps1

PowerShell -NoProfile -ExecutionPolicy Bypass -Command "& {Start-Process PowerShell -ArgumentList '-NoProfile -ExecutionPolicy Bypass -File ""%PSScriptPath%""' -WindowStyle Hidden}";



So we’re asking Windows to launch powershell, temporarily bypassing the execution policy for the context of this command only.  Then we pass the command which also bypasses the execution policy, but this time within the context of the file we’re about to launch which is “wrapper.ps1”.

So now we have our Powershell wrapper script running automatically everytime a user logs in.  We can now nest within that script all the other powershell scripts we would also like to run by doing the following:



$ScriptPath = Split-Path $MyInvocation.MyCommand.Path

. "$ScriptPath\date_check.ps1"

. "$ScriptPath\vmcheck.ps1"

. "$ScriptPath\IE_ESC.ps1"



Simply add a new line to this script for every logon script you want to run for users.

And if you’re wondering why the “$MyInvocation” variable doesn’t seem to be used anywhere, that’s because it’s an automatic variable.  There’s a great article on it here if you’re interested in learning more.