Office 365 PowerShell and Scheduled Tasks

There are many reasons why you might want to run PowerShell scripts against Office 365/Exchange Online on a schedule, so I won’t fuss with any examples. Here is how it is done.

First you must create an encoded script file which contains the password for the Exchange Online/Office 365 admin which you want to use to login. It is important that you create the .key file

a) on the computer which will be running the scheduled task
b) using the account which will run the Scheduled Task

This is because as only the creator can decrypt the .key file, and this can only be done on the computer which generated the key file. To create your encrypted password file, open Powershell and run the following command:

Read-Host "Enter Password" -AsSecureString |  ConvertFrom-SecureString | Out-File "C:\scripts\Password.txt"

This will ask you to enter the password and then give you a file full of rubbish. Now let’s do something with that rubbish! Your script to connect to Exchange Online and Office 365 should look like the following:

$TenantUname = "admin@myoffice365tenant.onmicrosoft.com"
$TenantPass = cat "c:\scripts\password.key" | ConvertTo-SecureString
$TenantCredentials = New-Object -TypeName System.Management.Automation.PSCredential -ArgumentList $TenantUname, $TenantPass
$msoExchangeURL = “https://ps.outlook.com/powershell/”
$session = New-PSSession -ConfigurationName Microsoft.Exchange -ConnectionUri $msoExchangeURL -Credential $TenantCredentials -Authentication Basic -AllowRedirection 
Import-PSSession $session
Connect-MSOLService -Credential $TenantCredentials

After these lines, add in the Powershell commands you wish to run, or a reference to a script. Save this as a .ps1 file.

For example, Clutter can’t be disabled for the whole tenancy, so to get around this I might want to disable clutter for all my users every night by adding this line to the end of my script:

Get-Mailbox -ResultSize Unlimited | Set-Clutter -Enable $false

Once you are all done with your script, open Task Scheduler and create a new task.

On the general tab, ensure that the user account being used to run the task is the same account which created the password file, and make sure the ‘Run whether user is logged on or not’ is ticked. Add whichever time based triggers you need, and on the Actions page choose to ‘Start a Program’ with the following settings:

Program/script: C:\Windows\System32\WindowsPowerShell\v1.0\powershell.exe
Add arguments: C:\Scripts\TestScript.ps1

Voila! You now have a script which uses an AES encrypted text file to connect to Exchange Online and Office 365 so that you can run your daily maintenance tasks from a single management server. Yay!

Advertisements

Append Description to a list of users

Today I needed to append, not overwrite, the description variable for a list of users. To do this, I created a simple .txt file containing the usernames I wanted to change.

lewish
nicor
maxv
sebastienv
kimir
danielr

I then ran this very simple command which takes the existing Description and adds the phrase “User Enabled 07/06/2016” to the end of the Description.

Get-Content "c:\migration\userstest.txt" | get-aduser -Properties Description | ForEach-Object { Set-ADUser $_ -Description "$($_.Description) User Enabled 07/06/2016" }

Easy peasy lemon squeezy!

Setting the ImmutableID to $null

Here’s a small Friday afternoon snippet of useful information for all you Office 365/Identity nerds out there.

If you have converted an AAD user from ‘Synced with Active Directory’ to ‘In Cloud’ and you want to sync a new user object with that user, you will need to clear the ImmutableID and then match it up with the new user object. I’m planning on creating a more extensive post on that very subject in the near future, but for now, I’ll give you this titbit of information:

Clearing the ImmutableID is done using the Powershell command:

Set-MSOLUser -UserPrincipalName emily@misstech.co.uk -ImmutableID "$null"

You might think that those quote marks are a bit pointless, but you would be wrong! If you were to run the command as shown below, without the “” marks, it wouldn’t show you an error, but it also wouldn’t actually clear the ImmutableID.

Set-MSOLUser -UserPrincipalName emily@misstech.co.uk -ImmutableID $null

As with all things PowerShell, syntax is everything!

Exchange Online Public Folder Migration Fail

Today I have been migrating Public Folders (yuk!) from Exchange 2010 to Exchange Online, and have come across a slightly odd issue.

I had followed the lovely guide to Public Folder migrations provided by Microsoft here, however I could not complete my migration as the migration batch had completed with errors. The error I was receiving was as follows:

Error: MigrationMRSPermanentException: Error: There are 2 mail public folder‎(s)‎ in Active Directory that were not linked to any public folder during migration.

The Public Folders referenced in the error message were both Exchange system folders, so I wasn’t sure why it was bothering to try and synchronise them. Luckily the error message does give us a clue as to what to do;

You may also run "Set-MailPublicFolder -IgnoreMissingFolderLink:$true" for each AD object that is a legacy system folder and resume the migration

Being the silly person I am, I assumed that this command needed to be run against the legacy Public Folders On Premise, but apparently -IgnoreMissingFolderLink is not a parameter in Exchange 2010. What I actually needed to do, which is not obvious from the error message,  was to run this command in Exchange Online. I ended up using a catch all command, which looked like this:

Get-MailPublicFolder | Set-MailPublicFolder -IgnoreMissingFolderLink:$true

Once this was done, I stopped the migration batch, and then started it again. It then performed it’s initial sync and I was able to continue the migration!

 

Out-GridView Awesomeness

This post is more for me than anybody else but some may find it useful. I feel a bit late to this particular party, but I have recently encountered the awesomeness that is Out-Gridview, and have started using it to help me easily define variables. Here is an example. I want to display a list of all Mail Users and then select the objects which I would like to save to a variable. To do this I can run the following command:

$mailuser = Get-MailUser | Select Name,UserPrincipalName,RecipientType |  Out-GridView -Title "Select Mail User" -PassThru

This gives me a selection box, containing the columns I specified, which I can then use to select the mail users I need for my variable. I can also search and define additional criteria to filter by. As I want to select multiple mail users, I can just Ctrl select as many users as I’d like and then click OK. Obviously IRL there would not be a gigantic black box covering your view, I am just protecting the innocent here!

out-gridview

If I now use $mailuser to show the results of my variable, I can see that the users I selected are there and I can manipulate them as I see fit. How I’ve lived my life before Out-Gridview I don’t know, but now I’ve found it I’m sure to cherish it for all time!

Disable Clutter feature for all users in Office 365

DisableClutter

Now I’m not one to advocate turning features off in Office 365, but sometimes when deploying Office 365 for a customer, there is simply too much change at one time. And if there is one thing that users hate, it is too much change!

Many customers I work with will choose to disable Skype for Business or OneDrive during the initial migration of email into the cloud. They can then plan the roll out of these services at a later date, and educate users on how to make the best use of it. This is much more preferable to just throwing a load of new functionality at users and expecting them to just start using it all with no training. After all, adoption of new technology starts with giving users the knowledge and power to be able to use the tools effectively!

And on that subject is a feature which has baffled and confused some users. This is called ‘Clutter’, and it uses machine learning to help organise the email which you don’t look at regularly, but may not want to delete (for example, that weekly newsletter from exchangeserverpro.com). This mail is automatically moved into your Clutter folder, clearing up your inbox so that it contains the email you need to know about now!

Email which is automatically moved out of your inbox does have the ability to freak users out if they aren’t expecting it, so you may want to disable this at first and then enable once you can communicate it’s purpose and usefulness to the business. To do this, you will need to make use of the mighty PowerShell!

Log yourself into Exchange Online PowerShell and use the following commands depending on your needs:

To disable Clutter for a single user:

Set-Clutter -Identity user@domain.com -Enable $false

To disable Clutter for all users:

Get-Mailbox | Set-Clutter -Enable $false

This command has a long list of outputs. If you want to hide the outputs, just add > $null to the end of the command, like this:

Get-Mailbox | Set-Clutter -Enable $false > $null

You can check to see if a mailbox has Clutter enabled by running:

Get-Clutter -Identity MailboxID | fl

And look for the IsEnabled parameter, which should be set to False!

So in summary, feel free to turn it off, but whatever you do, make sure you turn it on again as Clutter is definitely a useful tool to have in your email armoury!

Office 365 MSOnline PowerShell and Proxy Servers

If you administrate Office 365 regularly, especially from different locations, you may well have seen this error:

There was no endpoint listening at https://provisioningapi.microsoftonline.com/provisioningwebservice.svc

The number one cause for this error is a proxy servers. The likely cause is that your Internet Explorer browser has a proxy server configured. If this is in the format of a .pac file, you will need to go into IE>Internet Options>Connections>LAN Settings and remove the Proxy entry. Your connection will now be successful.

However if you have a proxy server manually set to a specific server, you need to tell PowerShell to go via the proxy. First though, check your winhttp configuration by running CMD as Administrator and running the following command:

netsh winhttp show proxy

This will probably show the following result:

netsh winhttp show proxy

Now run the following command:

netsh winhttp import proxy ie

This will import your proxy settings into your winhttp configuration and PowerShell should now navigate through the proxy and (hopefully) get to Office 365. Remember to restart PowerShell before attemping this! If this still doesn’t work, try removing the proxy settings in IE completely and retrying. If even this doesn’t do it, then you likely have a web filter blocking your traffic, in which case you will need to make sure the Office 365 IP addresses and/or URLs are allowed through your filter.

A lot of the above information depends on your network configuration and whether you are using transparent proxies or not, so information may not be 100% accurate to your specific setup. If you end up with incorrect winhttp settings and need to reset to defaults, run:

netsh winhttp reset proxy

from an Administrative CMD prompt and you will be back to square one.

Hopefully this helps some of you suffering from issues when trying to connect to Office 365 PowerShell.