Active Directory

Exchange Online Migration Clears ‘Recent’ Document Lists from Word and Excel

I struggle to fit these issues into a short but descriptive headline sometimes :)

This issue is a little strange. If you didn’t know any better (like me), you’d expect the location of a user’s mailbox to have no impact whatsoever on the function of ‘Recent’ document history inside of Microsoft Excel and Word, but it actually does.

I found this out the hard way of course, when a couple of staff mentioned their recent lists had disappeared and it co-coincided with their Exchange on-prem to Exchange online migration.

After some digging, I came across this Reddit post: 
Users losing Recent Documents lists in Office 2016 due to upgrade to ADFS. It’s the same problem with a slightly different root cause, and goes into a much deeper technical explanation than what I’ll do here.

The short of it is that the Office applications detect what sort of login you’re using – if it’s Active Directory (AD) or Azure Active Directory (AAD). When that state changes, it uses a different registry path for a few things, including those recent documents.

Without knowing for sure but based on my testing, it must be doing some check to see if the associated account’s mailbox is in Exchange Online or not – and if not, it considers it an AD account. It doesn’t matter if you already have the users in Azure AD, Single Sign on and all that other good stuff set up – the single change of changing the mailbox location to online triggered the change for me.

For an AD account, the history paths are saved in the registry here:

HKEY_CURRENT_USER\SOFTWARE\Microsoft\Office\16.0\Word\User MRU\AD_1234567890 (the number on the end is some sort of unique GUID).

For an Exch account, it’s in this slightly different path:

HKEY_CURRENT_USER\SOFTWARE\Microsoft\Office\16.0\Word\User MRU\ADAL_1234567890 (again, unique GUID at the end).

In case you were wondering, MRU stands for ‘Most Recently Used’. AD is to do with on-prem Active Directory, and ADAL is (according to that reddit post) Azure Active Directory Authentication Library.

Also note the example above is for Word, there’s corresponding paths for other Office applications such as Excel.

There’s two subkeys below this key, one for File MRU and the other Place MRU.

The good news on hitting this scenario is that the values can just be exported, the path changed and re-imported. To do this, via regedit find the registry key that has the values you want (probably the AD one) and right click > export.

Find the file you exported and use notepad to do a find and replace on all the entires for AD_1234567890 and replace to the new value (which you can find from just looking in the registry).

Now, re-import the registry file and you’ll have all the recent document paths restored.

This should only be a one time problem for migrations, and only for people who had a bunch of document paths saved in there and can’t find where they are easily.

Users Managing Email Groups and Exchange Online

For a very long time, users have been able to manage email group members via the Outlook client. Going into the Address Book, finding the group in the Global Address list, going into Properties and choosing ‘Modify Members’:

From there, someone can add or remove members as long as they’d been added to the “Managed By” field against the object in Active Directory, as well as ticking the box “Manager can update membership list” below it.

Easy! Except, that no longer works if the user is in Exchange Online, and the Email Group is from on-premises AD rather than Azure AD/Office 365. It’s not supported. This problem has been around for a while, back in 2015 Perficent wrote about this same topic. The options given for managing these groups are:

  • Exchange Admin Center
  • Exchange Management Console
  • Exchange Management Shell

None of those are what you want your standard users touching in my opinion – although you can give someone access to the Exchange Admin Center and only see the distribution groups they own – but for me, I’m still on Exchange 2010 so this isn’t an option.  This leaves you with a few options:

1. Change all your email groups to Cloud based groups. If this makes sense for you, doing this will let the manager of a cloud based group add/remove members via the Outlook Address Book.
You can also look at changing distribution groups over to Office 365 Groups (which are also cloud based), which give a whole bunch of different features beyond a what a distribution group can do, while giving the same standard DG experience.

2. Make all requests come through to IT so you can make the changes yourself. Not great for anyone involved, as it’s double/triple handling something where the user could quickly do it themselves.

3. Create Dynamic Distribution Groups and let automation do it’s thing – which will work for some, but exceptions to rules and the inability to see who’s in a group can make this frustrating for some.

4. Provide another way for staff to change group members themselves.

I’ve gone with option 4 – as I’m a big fan of Adaxes which I’ve written about a few times on my blog before, and they have a nice way of giving users a web interface that only lets staff manage the groups they’re the owner of.

There’s other ways to do this as well of course and other 3rd party solutions that can expose ways of adding/removing members of a on-premises distribution group – but remember there could be up to a half hour delay in syncing the change from AD to AAD via Azure AD Connect. If possible, look at adding a trigger at the end of a group change to do a delta sync:

Start-ADSyncSyncCycle -PolicyType Delta

That’ll be the quickest way to get the change up quickly, as staff may be used to the change working immediately.

There’s a lot to consider on how you’ll manage this, so make sure it’s sorted before you migrate – or expect a lot more tickets going through your helpdesk.

Null Dynamic Membership Rules in Azure Active Directory

Azure Active Directory has the ability to create Security Groups with Dynamic membership. This is great if you can apply logic to a group, as members will fall in and out of scope without any work required.

Microsoft have a great writeup on how it all works and how to create rules, however I’ve run into a scenario not covered in the documentation.

If you create a Dynamic membership rule and want to include only attributes that have no value, the term ‘null’ works fine. You can create your group or modify the rule without issue.
However, if your binary operator (the equals part in the example above) is set to ‘not’, it won’t work.
The use case I had for ‘not null’ was to have a group of users which only had employee numbers, which was an easy way of filtering out test accounts, service accounts and so on.

You’ll get this error:

Failed to create group

Failed to create group ‘groupname’. Dynamic membership rule validation error: Invalid operands found for operator.Invalid operands found for operator -not

The way to fix this is to go into the ‘Advanced Rule’ option and change the term ‘null’ to ‘$null’

Note that you can’t do this from the simple rule view, changing ‘null’ to ‘$null’ there results in the code looking like this:

(user.extensionAttribute1 -eq “$null”)

 

Where it should look like this, without the quotes:

(user.extensionAttribute1 -eq $null)

A simple fix, but something that’s not documented on the support page. Hope this helps anyone who runs into the same problem.

Updating the Country Field in Active Directory

Wanting to have all users to have the country ‘Australia’ in Active Directory, I thought it would be a simple PowerShell command. Get all the users you want and set a field to ‘Australia’. However, it’s more complicated than that.

As you can see from the above, the Country/region field is a dropdown, where you can select the country. If you look in PowerShell using ‘get-aduser username -properties *’, there’s 4 fields that get populated with this setting:

c : AU
co : Australia
Country : AU
countrycode: 36

Trying to just change one of these fields will result in an error such as:

Set-ADUser : A positional parameter cannot be found that accepts argument ‘Au’.
Set-ADUser : A positional parameter cannot be found that accepts argument ‘Australia’.
Set-ADUser : A value for the attribute was not in the acceptable range of values

The answer is that all fields need to be set at the same time. The C and Country fields are based on ISO 3166 codes, with Australia being AU and 36.

The resulting command would end up being:

set-aduser adam.fowler -Replace @{c="AU";co="Australia";countrycode=36}

Of course this can be done on a boarder scale by using ‘get-user’ with a larger scope, and piping that into the set-aduser command:

get-aduser -filter "company -eq 'Contoso'" | foreach {set-aduser $_ -Replace @{c="AU";co="Australia";countrycode=36}}

That’s all that’s required to change the field.

Checking CSV Against Active Directory Users

I’ve written before on how to update Active Directory from a CSV. This time, I’ve got a CSV list of users that I want to check are valid users against my Active Directory (AD) environment.

There’s a huge amount of ways this can be done, and this is just one of them. If you have others, or ways to improve this I’m always keen to hear!

This script assumes you have a CSV file with the header (first line) with the word ‘users’. Here’s an example CSV file: myusers.csv

Below is the PowerShell script I wrote. I’ve also written about ‘If’ and ‘Else’ before, so read that if you want some clarification. The user list I have is based on User Principal Name (UPN) rather than just username, so I’m searching AD to see if there’s a match or not.

Import-Module ActiveDirectory

$Data = Import-Csv myusers.csv

foreach ($user in $data){
$upn = $user.user
$check = $(try {get-aduser -filter "userprincipalname -eq '$upn'"} catch {$null})
if ($check -ne $null) { }
else { "$upn Doesn't Exist" }
}

What I’m doing here is setting each line of the CSV as the $UPN variable to search for. Then using the ‘Try‘ function, I’m catching if there is no result/match (null). If there’s a match, it won’t equal null, so display nothing. Else, show the UPN via the $UPN variable and follow that with ‘Doesn’t Exit’.

This way, I will only get results back from each AD search where the UPN in the CSV doesn’t match a user’s UPN in my AD environment – and I get to see what those results are.

This script method can be applied in many different ways of course, but it was the first time I’d used the Try function, and it worked really well.