Pages

Sunday, 1 November 2015

Is PowerShell Flawed?

Following my previous post about automating user licensing in Office 365, I came across a funny issue with Windows PowerShell for Active Directory. The project was to help the client connect to Office 365, they had multiple Active Directory forests in multiple international locations. For those that have worked with Office 365 you will know that before a license is allocated a “Usage Location” has to be set. So the plan was to use the “Country/Region” data from Active Directory. However some of the forests had not set this for their users. As this had not been set for a large number of accounts I thought the easiest solution would be to set this via PowerShell. I always say that if you’re using the GUI to do something twice, you’re doing it wrong… ;-) I ran the following cmdlet:

Set-ADUser [User] –Country:”GB”

image

Which in principal worked:  But after a Directory Synchronisation to Office 365 I noticed the change had not been applied to the Azure AD user?!? After some troubleshooting and digging around, I found the issue was that the PowerShell cmdlet run only sets the “c” attribute in Active Directory, whereas if you update the Country via the GUI it updates the “c”, “co”, and “countryCode” attributes. The Directory Sync server uses the “co” field to populate the “County/Region” field in Azure AD. So this got me thinking why the PowerShell cmdlet did not set these values? The sometimes much forgotten Active Directory Administration Centre or ADAC makes changes via PowerShell and gives you the history of the run cmdlets, so I made the change in ADAC, which updated all the attributes as expected, the in the PowerShell history it had run the following cmdlet:

 image

I copy and pasted the cmdlet from ADAC straight into Windows PowerShell, but it only set the “c” attribute again… So after a bit of digging around, I came up with the following:

$c ="US"
$co ="United States"
$countryCode = "840"
Set-ADUser <USER> -replace @{c=$c; co=$co; countryCode=$countryCode}

Which had the desired result on the Active Directory attributes and once synchronised to Office 365 the data in Azure AD was correct. I don’t fully understand why setting in ADUC and ADAC updates all the attributes, and if ADAC is making additional changes why it’s not being report in the PowerShell history.

So getting back to the title of the Blog “Is PowerShell Flawed?”… No of course not, PowerShell is a very powerful tool to aid any configuration or administration of infrastructure and systems, but you need to make sure you know what the PowerShell cmdlet are setting, you ask it to set something, it will set it!, it maybe not the desired setting you think it’s going to set, just make sure you check what you’re trying to set and what you’re running is applying the correct setting.

Disclaimer: All scripts and other PowerShell references on this blog are offered "as is" with no warranty.  While these scripts are tested and working in my test environment, it is recommended that you test these scripts in your own test environment before using in any production environment.

Friday, 30 October 2015

Office 365 Automate User Licensing

Recently working with a client they wanted to automate the licensing of Office 365 accounts, this client had multiple Active Directory forests being sync and cloud users in their Office 365 tenant. For those that have to assign licenses to users in Office 365 know it’s a two step process:

  1. Set user location
  2. Assign Office 365 license

To do this requires you to login to Office 365 and assign the information, We all know to run a local scheduled task, credentials can be stored in the task, however this is not possible (…Not that I’ve found) to store Office 365 credentials and pass them thru PowerShell from the scheduled task. For this reason you need to store the password on the local system. Before we get to this you need to make sure the user account your using has the correct permissions to assign licenses. Office 365 has a number of Admin roles Office 365 Admin Roles

So the only roles that can assign licenses are Global Admin and User Management Admin.

I’ve broken the PowerShell into five sections:

  1. Get Office 365 Credentials
  2. Connect to Office 365
  3. Set user usage location
  4. Get Office 365 license SKU
  5. Assign License

    Get Office 365 Credentials

    To be able to pass the password from the schedule task to PowerShell the password needs to be stored in plain text, to store passwords in plain text is never recommend. For this reason I’ve not used a domain account, I’ve used a cloud only account with a complex password. The location of the password is a local domain server which has restricted logons and additional NTFS permissions can be added to the location.

    ## MSOL Credentials
    $MsolAdmUser = “MSOL@yourdomain.onmicrosoft.com” 
    $pwd = Get-Content C:\Common\msol.txt | ConvertTo-SecureString -AsPlainText -Force
    $cred = New-Object System.Management.Automation.PSCredential $MsolAdmUser, $pwd

    Connect to Office 365

    To connect to Office 365 you need the follow these instructions Manage Azure AD using Windows PowerShell as Prerequisites. Once these steps have been completed. you will be able to connect:

    ## Connect To Office 365
    Import-Module MSOnline
    Connect-MsolService -Credential $cred

    Set user usage location

    A colleague of mine pointed me to this script in the TechNet Gallery, this script makes the local Active Directory country/region field to the Office 365 usage. Download and store this script.

    ## Set Usage Location for MSOl Users
    C:\Common\Set-MSOLUsageLocation.ps1

    Get Office 365 license SKU

    Before a license can be assigned, we need to get the correct SKU.

    ## Get Office 365 Account SKUs
    $AccountSku = Get-MsolAccountSku

    Its possible that you will have a number of different SKU’s on your tenant, you can list individual SKU:

    ## Account SKU Array
    $AccountSku[0].AccountSkuId
    $AccountSku[1].AccountSkuId
    $AccountSku[2].AccountSkuId

    For this project we’re only assign one type of SKU to all users, I’ll post another blog later how to assign different SKU’s within the same script.

    Assign Licenses

    Last but not least is to assign the license to the users. This takes data from the previous steps and assigns licenses:

    ## Set License for MSOL Users
    $Users = Get-MsolUser -All -UnlicensedUsersOnly
    $users = $users | ? {$_.Country -ne $null}

    ForEach ($User in $Users)
        {
            Set-MsolUserLicense -UserPrincipalName $user.UserPrincipalName -AddLicenses $AccountSku[0].AccountSkuId
        }

    Put all of these steps together in a PS1 script and set a scheduled task. Next steps are to put a query/variable into the Set-MsolUSerLicense this will allow different types of SKU’s to be applied in the same script, I’ll post this once complete…

    Disclaimer: All scripts and other PowerShell references on this blog are offered "as is" with no warranty.  While these scripts are tested and working in my test environment, it is recommended that you test these scripts in your own test environment before using in any production environment.

    Sunday, 25 October 2015

    Exchange 2016 Installation…

    Here are my notes of deploying Exchange 2016 into my home lab for testing, My current Exchange deployment is 2013 connected to Office 365 with a hybrid configuration. I plan to deploy two Exchange 2016 servers in Database Availability Group. This post will deal with the initial upgrade to the Schema, Configuration and Domain, then the installation of the first Exchange 2016 server.

    Prerequisites

    Download Exchange 2016 Download Link, and extract the setup files to local on the Exchange Server. To upgrade the Schema, Configuration and Domain this can be done from a 64-Bit Domain Controller or from an Exchange Server with the Remote Tools Administration Pack feature installed, The Server also requires .NET Framework 4.5.2,  To install this feature:

    1. Download and install .NET Framework 4.5.2 (If Windows Update has been run this may already be installed)
    2. Open Windows PowerShell (Run as Administrator)
    3. Install the Remote Tools Administration Pack using the following command

      Install-WindowsFeature RSAT-ADDS

    To upgrade the Schema, Configuration and Domain(s) open a command window (Run as Administrator) and run the following commands:

    1. Setup.exe /PrepareSchema /IAcceptExchangeServerLicenseTerms
    2. Setup.exe /PrepareAD /IAcceptExchangeServerLicenseTerms
    3. Setup.exe /PrepareDomain /IAcceptExchangeServerLicenseTerms

    If you you have multiple domains to in the Active Directory Forest you can use the /PrepareAllDomains.

    Note: To prepare The Schema the service account used must be a member of Schema Admins and Enterprise Admins, To update the Configuration and Domain(s) the service account used must be a member of Enterprise Admins.

    Reference: TechNet Prepare Active Directory and Domains

    PrepareSchema, PrepareAD, PrepareDomain

    image

    image

    image

    Server Preparation

    Before Exchange 2016 is installed a number of Windows Features need to be installed, To install these features:

    Reference: TechNet Exchange 2016 Prerequisites

    1. Open Windows PowerShell (Run as Administrator)
    2. Install required features:

      Install-WindowsFeature AS-HTTP-Activation, Desktop-Experience, NET-Framework-45-Features, RPC-over-HTTP-proxy, RSAT-Clustering, RSAT-Clustering-CmdInterface, RSAT-Clustering-Mgmt, RSAT-Clustering-PowerShell, Web-Mgmt-Console, WAS-Process-Model, Web-Asp-Net45, Web-Basic-Auth, Web-Client-Auth, Web-Digest-Auth, Web-Dir-Browsing, Web-Dyn-Compression, Web-Http-Errors, Web-Http-Logging, Web-Http-Redirect, Web-Http-Tracing, Web-ISAPI-Ext, Web-ISAPI-Filter, Web-Lgcy-Mgmt-Console, Web-Metabase, Web-Mgmt-Console, Web-Mgmt-Service, Web-Net-Ext45, Web-Request-Monitor, Web-Server, Web-Stat-Compression, Web-Static-Content, Web-Windows-Auth, Web-WMI, Windows-Identity-Foundation

    3. Restart Server

    4. Install Additional Software:
      1. .NET Framework 4.5.2
      2. Microsoft Unified Communications Managed API 4.0, Core Runtime 64-bit
    5. Run Windows Update

    Graphical User Interface Installation

    The following screenshots are taken from the Graphical User Interface Installation (GUI) of Exchange 2016.

    Reference: TechNet Install the Exchange 2016 Mailbox role using the Setup wizard

    Note: Please note these installation requirements:

    • If you're installing the first Exchange 2016 server in the organization, the account you use needs to be a member of the Enterprise Admins group
    • If you haven't previously prepared the Active Directory schema, the account you use also needs to be a member of the Schema Admins group
    • If you've already prepared the schema and aren't installing the first Exchange 2016 server in the organization, the account you use needs to be a member of the Exchange 2016 Organization Management role group
    1. image
      First window will ask Check for Updates? This the RTM of Exchange 2016 and currently no updates, click Next
    2. image
      Click Next
    3. image
      The file setup will display Copying Files…
    4. image
      The setup will display Initializing Setup… 
    5. image
      The setup will display Introduction with links to Exchange 2016 technical information, click Next
    6. image
      The License Agreement will be displayed, Once read… Select the radio I accept the terms in the license agreement, and click Next
    7. image
      Then select Recommend Settings that you want, the links will display information on these settings, I leave this set on Use Recommended Settings but some clients I work with prefer this to changed, once selected click Next
    8. image
      Now there is just a single role to install, check Mailbox Role, and click Next
    9. image
      This screen allows you to change the installation directory, please not that Exchange 2016 is still installed in V15, this is the same as Exchange 2013, once installation path has been confirmed click Next
    10. image
      Leave the default Malware Protection Settings enabled unless you requirement for them to be turn off, and click Next
    11. image
      The setup will run Readiness Checks… to ensure the server and infrastructure is ready for Exchange 2016 to be installed.
    12. image
      Any errors and warnings will be displayed, for instance in my environment it warned me that “MAPI over HTTP is the preferred Outlook desktop connectivity…” Now I thought this was default in Exchange 2016 need to check the release notes, this might just be for New/Greenfield installations, if there is no errors and only warnings, click Install to begin the installation.
    13. image
      Setup will go through all of the required steps to install Exchange 2016
    14. image
      Once complete the last screen will be displayed, click Finish to close the setup window
    15. The server should be restarted post installation

    Unattended Installation

    The over method of installing Exchange 2016 is through a Unattended Installation, this installs Exchange 2016 through the command window, this method uses switches to configure all the options of the Exchange 2016 installation.

    Reference: TechNet Install Exchange 2016 using unattended mode

    1. Open a command window (Run as Administrator)
    2. For a basic Exchange 2016 installation, enter the following command:

      Setup.exe /mode:Install /role:Mailbox /InstallWindowsComponents /IAcceptExchangeServerLicenseTerms

    This will install Exchange 2016 with a random mailbox database, you can use the switches to change the installation directory and database name and paths etc. The following screen is a completed unattended installation of Exchange 2016.

    image

    This completes the basic installation of Exchange 2016, all in all the setup process is very similar as Exchange 2013. Next up will be the configuration of Exchange 2016 including Mailbox Databases, Database Availability Group, Virtual Directories, Office Online Server… and much much more.

    Disclaimer: All scripts and other PowerShell references on this blog are offered "as is" with no warranty.  While these scripts are tested and working in my test environment, it is recommended that you test these scripts in your own test environment before using in any production environment.

    Exchange 2013 Cumulative Update

    The latest Exchange 2013 Cumulative Update (CU) 10 was released on 15th September 2015. There was no schema changes compared to CU9 , in fact the last schema change was in CU7.

    Download the CU10 Download Link, and extract the setup files to local on the Exchange Server. To upgrade the Schema, Configuration and Domain this can be done from a 64-Bit Domain Controller or from an Exchange Server with the Remote Tools Administration Pack feature installed. To install this feature:

    1. Open Windows PowerShell (Run as Administrator)
    2. Install the Remote Tools Administration Pack using the following command

      Install-WindowsFeature RSAT-ADDS

    To upgrade the Schema, Configuration and Domain(s) open a command window (Run as Administrator) and run the following commands:

    1. Setup.exe /PrepareSchema /IAcceptExchangeServerLicenseTerms
    2. Setup.exe /PrepareAD /IAcceptExchangeServerLicenseTerms
    3. Setup.exe /PrepareDomain /IAcceptExchangeServerLicenseTerms

    If you you have multiple domains to in the Active Directory Forest you can use the /PrepareAllDomains.

    Note: To prepare The Schema the service account used must be a member of Schema Admins and Enterprise Admins, To update the Configuration and Domain(s) the service account used must be a member of Enterprise Admins.

    Reference: TechNet Prepare Active Directory and Domains

    PrepareSchema, PrepareAD, PrepareDomain

    image

    image

    image

    Unattended Installation

    Once the Schema, Configuration and Domain has been updated, allow time for this to replicate to all Domain Controllers in the forest, The easiest way to upgrade a Exchange 2013 server is with an Unattended Installation. Open a command window (Run as Administrator) and run the following command:

    1. Setup.com /Mode:Upgrade /IAcceptExchangeServerLicenseTerms
    image

    The setup will check the environment to ensure that it’s ready to install, any warnings will be displayed, for instance my installation warned that I didn’t have a send connector for ‘*’, this is because my lab sits behind a dynamic IP address and I can’t send external SMTP.

    Note: This upgrade was on a standalone Exchange server that was not a member of a Database Availability Group(DAG), If a server is a member of a DAG it needs to removed/suspended from the load balanced environment and put into maintenance mode, I’ll get this posted on another day.

    Disclaimer: All scripts and other PowerShell references on this blog are offered "as is" with no warranty.  While these scripts are tested and working in my test environment, it is recommended that you test these scripts in your own test environment before using in any production environment.

    Tuesday, 28 April 2015

    Azure Active Directory Sync Issue…

    Working on an Azure Active Directory Sync for a client with multiple forests I came across a strange issue. The first forest was setup with password synchronization for the On-Premises AD accounts, stepped through the wizard and did the initial sync to Azure AD. Once the sync was complete tested login to Office 365 using one of the synced accounts and all worked as expected.

    The issue came when adding the second AD connection. Disabled the scheduled task, then open the Microsoft Azure AD Connection Tool to use the wizard to add the second AD forest. Once the new forest was added and synchronization was complete I tested the new logins with Office 365, however this time I was not able to use the accounts that had been synched.

    After double checking all settings and making sure I’d not missed anything, I checked the connector using PowerShell:

    Get-ADSyncAADPasswordSyncConfiguration –SourceConnector ForestB.Domain.com

    This reported back that:

    Password hash synchronization isn’t configured for this connector

    I checked the original connector

    Get-ADSyncAADPasswordSyncConfiguration –SourceConnector ForestA.Domain.com

    This reported back:

    SourceConnector: ForestA.Domain.com
    TargetConnector: Tenant.Onmicrosoft.com
    Enabled: True

    I ran the PowerShell to add password synchronization to the new connector:

    Set-ADSyncAADPasswordSyncConfiguration –SourceConnector ForestB.Domain.com –TargetConnector “tenant.onmicrosoft.com – AAD” –Enable $True

    Re-checked the AD Connector, which reported back:

    SourceConnector: ForestB.Domain.com
    TargetConnector: Tenant.Onmicrosoft.com
    Enabled: True

    Re-ran the synchronization to Azure AD, once completed tested the same login and all worked.

    Note: We plan to add another AD forest to this Azure Active Directory Sync installation, so will update if the issue was with this AD connector or all connectors…

    Friday, 6 March 2015

    Road to MCSE Messaging complete…

    Back in August 2013 I set myself a goal to complete my MCSE Messaging exams, this meant I needed to pass three exams… but in reality it was really six in my opinion.

    My exam path was 70-417 (Upgrading Your Skills to MCSA Windows Server 2012), I was able to sit the upgrade as I already had MCITP: Messaging 2010, this is also the reason I believe it was six exams, because 70-417 is three exams in one covering content from 70-410, 70-411 and 70-412. I passed this in April 2014. Passing this exam gave me a MCSA: Server 2012

    Next up was 70-341 (Core Solutions of Microsoft Exchange Server 2013), annoyingly it took two attempts, I think I took the first attempt to early and it knocked me for six, and wasn’t looking forward to retaking. However I took again and passed in December 2014.

    Last up 70-342 (Advanced Solutions of Microsoft Exchange Server 2013), which I passed yesterday!!! and now have my MCSE: Messaging.

    Back in August I said to myself I want to complete this in a year… well six months late, but I still got there, in that time I did have a skiing accident which didn’t help, so was more focused on me than my study, so I going to say I still meet my target ;-)

    Here is some of the tools I used during my study

    Books:
    Server 2012

    Installing and Configuring Windows Server 2012 – Link (Now updated for R2)
    Inside Out Windows Server 2012 – Link (Now updated for R2)
    Exam Ref 70-417 Upgrading from Windows Server 2008 to Windows Server 2012 R2 (MCSA) - Link

    Exchange 2013
    Inside Out Microsoft Exchange Server 2013: Mailbox and High Availability – Link
    Inside Out Microsoft Exchange Server 2013: Connectivity, Clients, and UM – Link
    Exam Ref 70-342 Advanced Solutions of Microsoft Exchange Server 2013 (MCSE) – Link
    Mastering Microsoft Exchange Server 2013 - Link
    Microsoft Exchange Server 2013 High Availability - Link

    Videos:
    Microsoft Virtual Academy – Link
    Channel 9 - Link

    Finally a big thanks to friends and colleagues (You know who you are…) that have put up with all my stupid questions during various stages of my study and exams.

    I know I’ve just finished but next goal is MCSA: Office 365… where to start…

    Friday, 20 February 2015

    Deploying Address Book Policies

    This blog will cover deploying Address Book Policies (hereafter ABP) in Exchange 2013. This post will cover both from an Admin point-of-view, and a User point-of-view. In my home lab and to help illustrate how the ABP works we’ll take two of world’s favourite cartoon families “The Simpsons” and “the Griffins”.

      

    The Basics

    Each ABP must contain at least one on the following:
    • Address List (AL)
    • Offline Address Book (OAB)
    • Global Address List (GAL)
    • Room Address List (RAL)

      Plan, Plan, Plan…

      Its important that you plan your deployment of ABP, as there are a number of different elements that can cause the ABP not to function how you envision.

      Address Book Policy Routing agent… (Optional)

      The ABP routing agent allows complete separation of users based on there ABP; From TechNet: - https://technet.microsoft.com/en-us/library/jj657455(v=exchg.150).aspx
      If you’re using ABPs, and you don’t want users in separate virtual organizations to view each other’s potentially private information, you can turn on the Address Book Policy Routing agent. The Address Book Policy Routing agent is a Transport agent that runs on the Mailbox server that controls how recipients are resolved in the organization. When the Address Book Policy Routing Agent is installed and configured, users that are assigned different GALs appear as external recipients in that they can’t view external recipients’ contact cards.

      What this means to the a user, is displayed in the following screenshots:
      Without the routing agent configured

      Using an Outlook client you can see the “Display Name” has resolved when the SMTP has entered, and when you right click and select “Open Outlook Properties” it will display the information from Active Directory. In OWA the experience is a little different

      You can see the SMTP name has resolved to be the “Display Name”  but no additional details are shown in the contact.

      With the routing agent configured

      Using an Outlook client you can see the “Display Name” has not resolved when the SMTP has been entered, and when you right click and select “Open Outlook Properties” it will display the SMTP details. in OWA the experience is a little different

      You can see the SMTP name has not resolved, however the User image still appears.

      NOTE: The OWA experience may just be in my lab environment, I couldn’t get this to change, and will do further troubleshooting and update accordingly.

      How to install the ABP Routing agent

      Run the following commands to install the ABP Routing agent:
      1. Open Exchange Management Shell (EMS) as Administrator
      2. Run the following command to install the agent

        Install-TransportAgent -Name "ABP Routing Agent" -TransportAgentFactory "Microsoft.Exchange.Transport.Agent.AddressBookPolicyRoutingAgent.AddressBookPolicyRoutingAgentFactory" -AssemblyPath $env:ExchangeInstallPath\TransportRoles\agents\AddressBookPolicyRoutingAgent\Microsoft.Exchange.Transport.Agent.AddressBookPolicyRoutingAgent.dll

      3. Run the following command to enable the transport agent

        Enable-TransportAgent "ABP Routing Agent"

      4. The transport service needs to be restarted

        Restart-Service MSExchangeTransport

      5. Run the following command to enable the ABP Routing agent

        Set-TransportConfig -AddressBookPolicyRoutingEnabled $true

      Divide your Organisation

      This is where you separate for Exchange objects into groups, this maybe separate companies, departments, or regions. From TechNet:- https://technet.microsoft.com/en-us/library/jj657455(v=exchg.150).aspx
      You'll need to develop a way to divide your organizations. We recommend using the CustomAttribute1-15 property on the mailboxes, contacts, and groups instead of the pre-canned conditional attributes such as Company, Department, or StateOrProvince to divide the virtual organizations for the following reasons: Not all recipient types of objects have precanned conditional attributes in Active Directory. For example, Distribution Group and Dynamic Distribution Group do not support company, department, or state attributes.
      • Not all precanned conditional attributes are exposed in cmdlets for some recipients. For example, the Company, department, and StateOrProvince parameters are not available on the exposed in cmdlets for mail users, contacts, distribution groups, and mail-enabled public folders.
      • Multiple cmdlets are required to segregate recipient when you use the pre-canned conditional attribute. For example, you need to run Set-User to tag Company, Department, StateOrProvince for a UserMailbox after you run New-Mailbox or Set-Mailbox cmdlets.
      • The CustomAttributeX parameters are all exposed in the Set-* cmdlet for each recipient type, we can complete all segregation for that type via single Set- cmdlet
      • CustomAttributeX attributes are explicitly reserved for customization of an organization and are entirely under the control of the organization administrators.

      Note: From experience and working on a number of different environments I find that “CustomAttribute 1-15” are normally the best fit, however it’s worth noting that these attributes are also commonly used in Email Address Policies, so it’s worth checking if these attributes are not being used for another purpose.

      Create Address Lists, Global Address Lists, and Offline Address Lists

      At the start of the post I said that each ABP requires at least one AL, GAL, OAB, and RAL. Here I find that a good naming convention helps with any design, however I’ll also highlight a couple areas that I find them to be an issue and how to address them.
      For this demonstration I’m keeping it fairly simple and just separating the two groups of users “The Simpsons” and “Family Guy”, for this reason I’ve used the “Company” fields in the following PowerShell, as explained earlier this may not be the best fit. Some of the following processes can be created in the Exchange Admin Console (EAC) I’ll indicate where you can’t use the EAC.

      Address Lists

      I’ve formatted the name of the address list “AL_The Company_Object”, obviously the middle section may change based on separation, this gives me:

      • AL_The Simpsons_All User
      • AL_Family Guy_All Users
      • AL_The Simpsons_All Rooms
      • AL_Family Guy_All Rooms

      To create the these AL’s run the following commands into EMS:

      New-AddressList -Name 'AL_The Simpsons_All Users' -ConditionalCompany @('The Simpsons') -IncludedRecipients 'MailboxUsers'
      New-AddressList -Name 'AL_Family Guy_All Users' -ConditionalCompany @('Family Guy') -IncludedRecipients 'MailboxUsers'
      You will also need a RAL, these are just AL’s with a RecipientType filter applied to the list (This type of filter cannot be applied in the EAC), To create the these AL’s run the following commands into EMS:
      New-AddressList -Name 'AL_The Simpsons_All Rooms' -RecipientFilter {(RecipientDisplayType -eq 'ConferenceRoomMailbox') -and (Company -eq 'The Simpsons')}
      New-AddressList -Name 'AL_Family Guy_All Rooms' -RecipientFilter {(RecipientDisplayType -eq 'ConferenceRoomMailbox') -and (Company -eq 'Family Guy')}
      If you don’t use “Room Mailboxes” in your organisation you can use the default Room AL or create a blank AL that will not be populated with any objects:
      New-AddressList -Name AL_BlankRoom -RecipientFilter {(Alias -ne $null) -and (RecipientDisplayType -eq 'ConferenceRoomMailbox')}

      This creates the necessary AL’s and RAL’s for each ABP; but I would just highlight a functionality point here, this is not a Exchange Admin point, but from the User’s point of view and how I address this. By running the previous commands you get the following the EAC:

      However the user will see the name used during creation of the AL

      This can easily be updated, but this is where the EAC is not always great, the EAC will display the “DisplayName” and not the “Name”, so when you update the lists to be “All Users” etc you get this:

      However EMS gives you this:

      This also however does mean you get happy users ;-)

      Global Address Lists

      I’ve formatted these similar to the AL’s; “GAL_The Company”, obviously you may need to extend based on separation, this gives me:

      • GAL_The Simpsons
      • GAL_Family Guy

      NOTE: New GAL’s cannot be created in the EAC, these need to be created in the EMS:

      New-GlobalAddressList -Name "GAL_The Simpsons" -IncludedRecipients MailboxUsers -ConditionalCompany "The Simpsons"
      New-GlobalAddressList -Name "GAL_Family Guy" -IncludedRecipients MailboxUsers -ConditionalCompany "Family Guy"

       

      Offline Address Books

      The last part before creating the ABP, is to create an OAB; I’ve formatted these the same as the GAL’s; “OAB_The Company”, obviously you may need to extend based on separation, this gives me:

      • GAL_The Simpsons
      • GAL_Family Guy
      NOTE: New OAB’s cannot be created in the EAC, these need to be created in the EMS:

      New-OfflineAddressBook -Name "OAB_The Simpsons" -AddressLists '\AL_The Simpsons_All Users'
      New-OfflineAddressBook -Name "OAB_Family Guy" -AddressLists '\AL_Family Guy_All Users'

       

      Address Book Policies

      The final part is to put all the above together to create an ABP; ABP’s cannot be created in the EAC, these need to be created in the EMS:

      New-AddressBookPolicy -Name "The Simpsons" -GlobalAddressList "\GAL_The Simpsons" -AddressLists '\AL_The Simpsons_All Users' -OfflineAddressBook '\OAB_The Simpsons' -RoomList '\AL_The Simpsons_All Rooms'
      New-AddressBookPolicy -Name "Family Guy" -GlobalAddressList "\GAL_Family Guy" -AddressLists '\AL_Family Guy_All Users' -OfflineAddressBook '\OAB_Family Guy' -RoomList '\AL_Family Guy_All Rooms'

       

      Assign the ABPs to the Mailboxes

      This is where I eat my words about “Plan, Plan, Plan…” throughout this blog I’ve filtered the list based on “Company” however to then apply a ABP to a mailbox with the filter of “Company” you can’t use the Get-Mailbox Cmdlet. You can use another common filter i.e.:

      Get-Mailbox -resultsize unlimited | where {$_.CustomAttribute15 -eq "Family Guy"} | Set-Mailbox -AddressBookPolicy "Family Guy"

      You can of course use the EAC and filter by the company, which will use the Get-Recipent filter, and then apply the ABP to your mailboxes.

      I hope this helps someone in the future and saves them some time.

      Reference Links:

      Address book policies:- https://technet.microsoft.com/en-us/library/hh529948(v=exchg.150).aspx
      Scenario: Deploying address book policies:- https://technet.microsoft.com/en-us/library/jj657455(v=exchg.150).aspx
      Address book policy procedures:- https://technet.microsoft.com/en-us/library/hh529916(v=exchg.150).aspx 

      Disclaimer: All scripts and other PowerShell references on this blog are offered "as is" with no warranty.  While these scripts are tested and working in my test environment, it is recommended that you test these scripts in your own test environment before using in any production environment.