Ignite 2016 Sessions + Downloader

imageNote: Due to Microsoft putting Ignite 2016 contents on YouTube and a new portal, I had to rewrite the download script. Mattias Fors was also working on this, and after integrating his contents pointers, I present you Ignite2016Download.ps1. Check the description on Technet Gallery page for usage options.

Today, the Ignite 2016 event will kick off in Atlanta, US. The agenda contains the whopping number of 1412 sessions, of which 395 touch Office 365 and 133 Exchange in some way or another.

With those numbers it is impossible to attend every session for folks interested in these topics, but luckily Microsoft will also publish Ignite 2016 sessions on Channel 9 this year.

Some of the interesting sessions to watch out for are (links should resolve to on-demand sessions, as they become available):

Session Description Speaker(s)
BRK1021 Unplug with the Microsoft Outlook experts Julia Foran, Gabe Bratton, Allen Filush, JJ Cadiz, Eduardo Melo, Amanda Alvarado, Victor Wang, James Colgan
BRK1044 Dive deeper into what’s new and what’s coming in Outlook on the web Dave Meyers, Eduardo Melo
BRK2033 Discover Office 365 Groups – overview, what’s new and roadmap Amit Gupta, Christophe Fiessinger
BRK2035 Learn about advancements in Office 365 Advanced Threat Protection Jason Rogers, Phil Newman
BRK2053 Connect your business critical applications to Outlook and Groups David Claux
BRK2044 Discover what’s new and what’s coming for Office Delve Cem Aykan, Mark Kashman
BRK2093 Design your Exchange infrastructure right (or consider moving to Office 365) Boris Lokhvitsky, Robert Gillies, Adrian Moore
BRK2139 Protect your business and empower your users with cloud Identity and Access Management Nasos Kladakis
BRK2170 Discover what’s new with Microsoft Exchange Public Folders Sampath Kumar
BRK2215 Debate the top 10 reasons not to move your Exchange on-premises mailboxes to Exchange Online Tony Redmond, Greg Taylor, Steve Conn
BRK2216 Unplug with the experts on Exchange Server and Exchange Online Greg Taylor, Timothy Heeney, Jeff Mealiffe, Ross Smith IV, Wendy Wilkes
BRK2217 Discover modern support in Outlook for Exchange Online Julia Foran, Amir Haque, Gabe Bratton
BRK2218 Move from Exchange 2007 to Modern Exchange Greg Taylor, Steve Conn
BRK2219 Meet twin sons of different mothers – Exchange Engineers and Exchange MVPs Tony Redmond, Jeff Mealiffe, Andrew Higginbotham, Jeff Guillet, Karim Batthish
BRK2220 Peer behind the curtain – how Microsoft runs Exchange Online Paavany Jayanty, Eddie Fong, Karim Batthish, Mike Swafford
BRK3000 Unplug with the experts on Microsoft Exchange Top Issues Nino Bilic, Nasir Ali, Amir Haque, Shawn McGrath, Timothy Heeney, Gabe Bratton, Angela Taylor
BRK3001 Explore the ultimate field guide to Microsoft Office 365 Groups Tony Redmond, Amit Gupta, Benjamin Niaulin
BRK3007 Investigate tools and techniques for Exchange Performance Troubleshooting Nasir Ali, Jeff Mealiffe
BRK3019 Manage Microsoft Office 365 Groups Eric Zenz, Vince Smith
BRK3023 Understand how Microsoft protects you against Spoof, Phish, Malware, and Spam emails Jason Rogers
BRK3045 Use Microsoft Graph to reach users on hybrid Exchange 2016 Venkat Ayyadevara
BRK3046 Build intelligent line-of-business applications leveraging the Outlook REST APIs Venkat Ayyadevara
BRK3074 Discover what’s new in Active Directory Federation and domain services in Windows Server 2016 Sam Devasahayam
BRK3109 Deliver management and security at scale to Office 365 with Azure Active Directory Brjann Brekkan
BRK3139 Throw away your DMZ – Azure Active Directory Application Proxy deep-diveThrow away your DMZ – Azure Active Directory Application Proxy deep-dive John Craddock
BRK3216 Plan performance and bandwidth for Microsoft Office 365 William Looney, Ed Fisher
BRK3217 Run Microsoft Exchange Hybrid for the long haul Timothy Heeney, Nicolas Blank
BRK3219 Migrate to Exchange Online via Exchange Hybrid Michael van Horenbeeck, Timothy Heeney
BRK3220 Deploy Microsoft Exchange Server 2016 Brian Day, Jeff Guillet
BRK3221 Understand the Microsoft Exchange Server 2016 Architecture Ross Smith IV, Mike Cooper
BRK3222 Implement Microsoft Exchange Online Protection Jennifer Gagnon, Wendy Wilkes
BRK3227 Ask us anything about Microsoft Office 365 Groups Eric Zenz, Darrell Webster, Christophe Fiessinger, Martina Grom
BRK3253 Experience Scott Schnoll’s Exchange tips and tricks Scott Schnoll
BRK3254 Cert Exam Prep: Exam 70-345: Designing and Deploying Microsoft Exchange Server 2016 Vladimir Meloski
BRK4031 Overcome network performance blockers for Office 365 Deployments Paul Collinge
BRK4032 Dive deep into Microsoft Exchange Server High Availability Andrew Higginbotham
PRE18 The previous decade called…they want their Exchange Server back Michael van Horenbeeck, Greg Taylor, Sampath Kumar, Andrew Higginbotham, Timothy Heeney, David Espinoza, Nicolas Blank
THR1005R Dive deeper into what’s new and what’s coming in Microsoft Outlook 2016 for Windows Misbah Uraizee
THR1011R Dive deeper into what’s new and what’s coming in Outlook mobile Allen Filush, Victor Wang, James Colgan
THR2007R Fight back with advancements in Office 365 Advanced Threat Protection Phil Newman, Atanu Banerjee
THR2054 Understand the risk and value of your public folder data BEFORE you migrate Dan Langille
THR2190R Secure your sensitive email with Office 365 message encryption Gagan Gulati, Ian Hameroff
THR3001R Migrate DL to Microsoft Office 365 Groups Siva Shanmugam, Loveleen Kolvekar
THR3015 Use RMS in Microsoft Office 365 Nathan O’Bryan
THR3040 Automate Exchange deployment with Powershell Desired State Configuration Ingo Gegenwarth
THR3082 Secure Office 365 in a hybrid directory environment Alvaro Vitta

For those that wish to view sessions offline, there is a script to download the slidedecks and videos. It does so by scraping the Ignite portal, downloading slidedecks from the portal itself, and videos from the related YouTube video link using an utility youtube-dl.exe (which you can also use to download playlists, quite neat). The script can take some parameters:

  • DownloadFolder to adjust the download folder.
  • Format to alter the dimensions and quality of the downloaded videos (see help for supported formats).
  • Title to filter on title keyword
  • Keyword to filter on description keyword.
  • Start to use a different version number to start scraping. Scraping is done sequentially; in the output you will notice a (#nnn) next to the title. That is the current post number.
  • NoVideos to skip downloading videos.

You can download the script from the TechNet Gallery here.

HTTP Proxy TargetBackEnd limits

powershellLast Update: February 4th, 2016

When deploying Exchange 2013 or Exchange 2016 in co-existence with a legacy version of Exchange, there comes a point where all traffic is routed through Exchange 2013/2016. Traffic for mailboxes hosted on legacy Exchange versions will be proxied by Exchange 2013/2016 to the back end.

This proxy process has some built-in limits for certain protocols, which you could encounter. Symptoms of these limits are Event 2022’s being logged in the Application log by the MSExchange Front End HTTP Proxy service:


Per Exchange 2013 CU7, this message should be considered a notice, despite the confusing event description. No connections are being blocked. However, the events create noise in your logs, which can be prevented by raising these limits. To accomplish this, you need to dive in to the web.config of the applicable HTTP Proxy protocols:

  • $ExInstall\FrontEnd\HttpProxy\sync\web.config (for ActiveSync, EAS)
  • $ExInstall\FrontEnd\HttpProxy\rpc\web.config (for OA, RPC/http)

In those files, create or adjust the entry in the <appsettings> configuration node, where <value> is the limit you want to configure (default is 150):

<add key=”HttpProxy.ConcurrencyGuards.TargetBackendLimit” value=”<value>” />

After adjusting these values, recycle the relevant application pools, e.g. MSExchangeSyncAppPool and MSExchangeRPCProxyAppPool.

The above steps need to be performed on all Exchange 2013/2016 Client Access Servers.

To automate this process of tedious editing in web.config files, I have created a small script which lets you alter these values for EAS and RPC against the local server or remotely. The script, Configure-HTTPProxyTargetBackEnd.ps1, has the following parameters:

  • Server to specify server to configure. When omitted, will configure local server.
  • AllServers to process all discoverable Exchange Client Access servers
  • TargetBackEnd specifies Target Backend limit (default 150).
  • NoRecycle to prevent recycling the MSExchangeSyncAppPool and MSExchangeRPCProxyAppPool

For example, to configure the local server with a limit of 2000 for Exchange Active-Sync and RPC access, use:

.\Configure-HTTPProxyTargetBackEnd.ps1 -TargetBackEnd 2000


Note that the script will create a backup copy of the web.config files before editing, using the current timestamp.

You can download the script from the TechNet Gallery here.

Feedback is welcomed through the comments. If you got scripting suggestions or questions, do not hesitate using the contact form.

See TechNet Gallery page.

Connecting to Office 365/Exchange


Last update: Version 1.4, October 5th, 2016

Almost 3 years ago, I wrote an article on how to enhance the PowerShell Integrated Scripting Environment, or ISE. That seemed adequate for the Exchange admin back then, who mostly connected their PowerShell session to their his on-premises environment, and perhaps occasionally a bit of Exchange Online.

Fast forward to 2015, most modern Exchange administrators not only require a connection – if any – to their Exchange on-premises environment, but likely to one or more of the Office 365 services as well. This includes Exchange On-Premises, Azure Active Directory, Exchange Online Protection and perhaps even Skype for Business Online, SharePoint Online, Azure Rights Management Services or Compliance Center.

All these services use a different PowerShell session, use a different endpoint FQDN, and in some cases require a locally installed PowerShell module. Likely common denominator is the credential used to access each of these services. So, tired of re-entering my credentials every time when switching from Exchange Online to Exchange Online Protection, I created a script with a set of functions to allow me connect to each individual Office 365 service or Exchange Online:

  • Connect-AzureAD: Connects to Azure Active Directory
  • Connect-AzureRMS: Connects to Azure Rights Management
  • Connect-ExchangeOnline: Connects to Exchange Online
  • Connect-SkypeOnline: Connects to Skype for Business Online
  • Connect-EOP: Connects to Exchange Online Protection
  • Connect-ComplianceCenter: Connects to Compliance Center
  • Connect-SharePointOnline: Connects to SharePoint Online
  • Get-Office365Credentials: Gets Office 365 credentials
  • Connect-ExchangeOnPremises: Connects to Exchange On-Premises
  • Get-OnPremisesCredentials: Gets On-Premises credentials
  • Get-ExchangeOnPremisesFQDN: Gets FQDN for Exchange On-Premises
  • Get-Office365Tenant: Gets Office 365 tenant name (SharePoint)

Note that functions and credentials used in the script are global, and in principle only need to be entered once per shell or ISE session. If you need different credentials, call Get-Office365Credentials again. User interaction is a very basic Read-Host, but it does the job.

During initialization, the script will detect the modules which are required for certain Office 365 services. When not installed, it will notify you, and provide a link where to obtain the PowerShell module. The related Connect function will not be made available. The Azure Active Directory module also requires the Microsoft Online Sign-In Assistant to be installed. Needless to say, PowerShell is required to run this script, which is tested against version 4 (but should work with 3)

The functions are contained in a script called Connect-Office365Services.ps1. You can call this script manually from your PowerShell session to make the functions available. However, more convenient may be to have them always available in every PowerShell or ISE session. To achieve this, you need to edit your $profile, which is a script which always starts when you start a PowerShell or ISE session. By default this file does not exist and you need to create it, including the path. Also note that the files for PowerShell and ISE are different, Microsoft.PowerShell_profile.ps1
and Microsoft.PowerShellISE_profile.ps1 respectively.

Now, of course you can copy and paste the functions from the script file to your own $profile. Better is to call the script from your $profile, as this allows you to overwrite the Connect-Office365Services.ps1 with updates. To achieve this, assume you copied the Connect-Office365Services.ps1 in the same location as your $profile, for example C:\Users\Michel\Documents\WindowsPowerShell. You can then make PowerShell and ISE call this script by adding the following line to the $profile scripts:

& “$PSScriptRoot\Connect-Office365Services.ps1”

Now when you start a PowerShell session, you might see the following:


This shows the Microsoft Online Sign-In Assistant and Azure Active Directory PowerShell module is available, and related connect functions should be available.

When you load the script from ISE, it will show something similar. However, it will also show ISE is detected and make all functions available through the Add-On menu:


Customize this script to your liking. For example, if you always want to connect to Azure Active Directory when connecting to Exchange Online, add Connect-AzureAD in the Connect-ExchangeOnline function, or when you always want to connect to a fixed FQDN for Exchange On-Premises, insert it in the script or – better – configure your $profile to predefine the FQDN, e.g. $global:ExchangeOnPremisesFQDN=’mail.contoso.com’.

Also, you may with to leverage prefixing the imported cmdlets so you can easily switch between Exchange On-Premises and Exchange Online. For example, you can then having something like Get-EXOMailbox and Get-EOPMailbox corresponding to Get-Mailbox in your Exchange Online or Exchange On-Premises within the same shell session. However, as with aliases, think of the ‘the next guy’ who may not have these prefixed cmdlets, and instructions or scripts may require adoption to work, etc. But if you insist, for more information on prefixing cmdlets when importing a PowerShell session, see here.

Windows 10
Be advised that when used with Windows 10 build 10525 or 10532, your PowerShell session might crash when connecting to certain services, e.g. Exchange Online Protection. Fellow Exchange MVP Tony Redmond wrote about this here, including a possible workaround. Windows 10 RTM does not have this issue.

Download / Revisions
You can download the script from the TechNet Gallery here. The TechNet Gallery page as well as the script contains revision information.

Feedback is welcomed through the comments. If you got scripting suggestions or questions, do not hesitate using the contact form.

Client Message Size Limits

powershellLast Update: Version 1.11, November 4th, 2015

Exchange 2013 enforces certain message size limits when it comes to client messages. These limits are in-place so clients can’t generate excessive load on your Exchange environment. These limits are determined for various access methods in multiple web.config files on Exchange Client Access Servers as well as Mailbox Servers.

Sometimes you may have good reasons to increase those limits. For example, when migrating to Office 365 using a product like MigrationWiz, you may want to increase the limit for Exchange Web Service (EWS) requests to allow for migration of larger items. Another example is when you want to allow for bigger attachments in Outlook WebApp (OWA). On TechNet, there’s an article on how to reconfigure these limits. However, the process consists of editing multiple web.config files, replacing multiple values in the same file, and following this process on each Exchange 2013 server in your environment. This is not only labor intensive and prone to error, but becomes tedious when you consider that each Cumulative Update will overwrite your web.config files.

But do not despair. To execute these changes for OWA and EWS, I have created a PowerShell script which will perform these tasks for you.

Using the script requires Exchange 2013. You need to provide the server name (default is local server) or AllServers to apply to all Exchange 2013 servers in your environment. The script will modify the web.config remotely using the system share (e.g. C$), using the location of the Exchange installation, and uses IISRESET tool to restart IIS. It will create a backup of the web.config before modifying it.


  1. The script checks for running in elevated mode when running against the local machine.
  2. Current version of the script requires Exchange Management Shell, to run Exchange cmdlets for checking installed roles a.o., as the web.config files which require editing depend on the installed roles.
  3. For OWA, add ~33% to the value you want to specify to compensate for encoding overhead.
  4. When connected to an Exchange server, the script processes the server hosting the EMS session last to prevent abortion caused by IIS reset.
  5. Script currently runs against Exchange 2013.

The script Configure-ClientSizeLimits.ps1 uses the following syntax:

.\Configure-ClientSizeLimits.ps1 [-Server |-AllServers] [-OWA ] [-EWS ] [-Reset] 

A quick walk-through on the parameters and switches:

  • Server specifies the server to configure. When omitted, it will configure the local server. This parameter is mutually exclusive with AllServers.
  • AllServers switch specifies to configure all Exchange 2013 servers. This switch is mutually exclusive with Server.
  • OWA configures the message size limit for OWA. Value is in 1KB units.
  • EWS configures the message size limit for EWS. Value is in 1KB units.
  • Reset switch specifies to perform an IISRESET against servers after reconfiguration of client-specific message size limits.

So, suppose you want to configure an OWA message size limit for you can use:

.\Configure-ClientSizeLimits.ps1 -Server EX01 -OWA 100 -EWS 10240 -Reset

Configure Client Size Limits If you want to configure EWS limits for all servers without resetting IIS, you could use:

.\Configure-ClientSizeLimits.ps1 -AllServers -EWS 10240

You can download the script from the TechNet Gallery here.

Feedback is welcomed through the comments. If you got scripting suggestions or questions, do not hesitate using the contact form.

See TechNet Gallery page.

To Do
Compatibility with Exchange 2010 and removal of dependency on Exchange Management Shell.

Ignite 2015 Session Download Script

ignite ButtonYesterday was the first day of Ignite, and Exchange fellow Tony Redmond put up a nice summary of the first day, keynoted included, here.

For those not attending Microsoft Ignite, attending different sessions or not able to enter a session because the room was full, Microsoft publishes Ignite sessions on Channel 9. Because you may want to watch sessions offline, some people created scripts to retrieve all session videos and slidedecks.

Here is a slightly modified script, originally from Claus Nielsen, to download all Microsoft Ignite 2015 videos and slidedecks as the become available on Channel9. You can select sessions based on category or speaker, which helps narrowing down the contents offered at Ignite to sessions you are interested in. The script also allows you to download other session videos and decks, for example from Build 2015 or last year’s TechEd NA.

You can download the script from the TechNet Gallery here.

(Re)configuring IM Integration

Last Update: August 16th, 2016.

powershellNote: The procedure has changed for Exchange 2016, which can use overrides to make this setting persistent. For these instructions, consult this article.

Anyone who has configured Exchange 2013 IM integration with Lync Server at some point has to modify the web.config file on the Mailbox servers to configure OWA with the proper certificate for enabling IM. Another thing (read: nuisance) is that when you have configured IM integration and you apply a Cumulative Update to Exchange 2013, the web.config will be overwritten, in which case you need to reapply those changes to the web.config file.

This is where the script Configure-IMIntegration.ps1 might come in handy.

Using the script requires Exchange 2013 and Lync Server. You need to provide the Lync pool and the Mailbox server you want to configure needs to have a valid certificate assigned to IIS (or UM) service. The script will modify the web.config remotely using the system share (e.g. C$), using the location of the Exchange installation, and uses WMI to recycle the OWA Application Pool in IIS. It will create a backup of the web.config before modifying it.

Note that the script does not perform the following steps:

  • It does not perform the Lync Server parts to configure IM integration, e.g. configure Exchange as a trusted application.
  • It does not configure Lync Server as an partner application for Exchange (Configure-EnterprisePartnerApplication.ps1).

The script Configure-IMIntegration.ps1 uses the following syntax:

.\Configure-IMIntegration.ps1 [-Server <String>[]] -PoolFQDN <String> [-AllCAS] [-AllMailbox] [-UM] [-Thumbprint <String>]

A quick walk-through on the parameters and switches:

  • Server specifies the server(s) to configure. When omitted, it will configure the local server. This parameter is mutually exclusive with AllMailbox.
  • AllMailbox switch specifies to configure all Mailbox servers. This switch is mutually exclusive with Server.
  • AllCAS switch specifies to enable IM integration on all Client Access servers.
  • PoolFQDN specifies the FQDN of the Lync Pool to use. This parameter is required.
  • UM specifies that the script should look for a certificate assigned to UM services instead of IIS (default).
  • Thumbprint to manually specify the thumbprint of the certificate to use.

So, suppose you want to quickly reconfigure IM integration on a Mailbox server after applying a Cumulative Update, you can use:

.\Configure-IMIntegration.ps1 -PoolFQDN lync.contoso.com –Server exchange01.contoso.com


Or, you can quickly configure Mailbox servers and CAS servers for IM integration after performing the required steps to configure the trusted application settings and installing and assigning the certificate for UM:

.\ Configure-IMIntegration.ps1 -PoolFQDN lync.contoso.com -AllMailbox –AllCAS


Also, in the example above, the CAS servers had already been enabled for IM.

You can download the script from the TechNet Gallery here.

Feedback is welcomed through the comments. If you got scripting suggestions or questions, do not hesitate using the contact form.

Revision History
See TechNet Gallery page.

Exchange-Processor Query Tool: PowerShell Edition

powershellLast Update: Version 1.1, June 28th, 2016.

Anyone sizing for Exchange Server 2013 or even still Exchange Server 2010, using the Server Role Requirements Calculator, has to determine processor requirements at some point. This is accomplished by looking up the SPECint_rate2006 score of the planned processor configuration and matching that against the calculated number of required megacycles by the calculator. To account for fail-over situations, additional overhead needs to be added to the number of megacycles. The process as part of the overall sizing has been explained in detail by Jeff Mealiffe here.

The Exchange consultants’ Swiss army knife when determining SPECint rates is the Exchange Processor Query Tool, an Excel sheet designed by Scott Alexander from Microsoft, which allows you to easily look up and determine the SPECint_rate2006 value by inputting a processor model. While still useful, the tool has been out there since 2011. Also, it would be nice sometimes to see which systems are eligible for a certain sizing specification, rather than validating if the planned processor configuration meets the sizing requirements.

So, I wrote a PowerShell script which can query the SPECint rates for you. Because the rating scores are returned as objects, you can perform additional tasks using PowerShell functionality, such as:

  • Use additional criteria, such as vendor, min/max number of cores, etc.
  • Calculate the average SPECint2006 Rate Value for a certain CPU/cores configuration.
  • You can use the SPECint value calculated by the Server Role Requirements Calculator  to find hardware configurations which meet the required total megacycles requirements, optionally including a required overhead percentage.
  • You can select if you are sizing for Exchange Server 2010 or Exchange Server 2013.

The script requires PowerShell and internet access to query the SPECint database.

The script is called Exchange-PQT.ps1, in honor of the Processor Query Tool (PQT).  The syntax is as follows:

Exchange-PQT.ps1 [-CPU <String>] [-Vendor <String>] [-System <String>] [-Overhead <Int32>] [-MinMegaCycles <Int32>] [-Type <String>] [-MinCores <Int32>] [-MaxCores <Int32>] [-MinChips <Int32>] [-MaxChips <Int32>] [<CommonParameters>]

The information returned and which you can use for post-processing is: Vendor, System, CPU (processor description), Cores, Chips (number of CPU’s), CoresPerChip (number of Cores per CPU), Speed, Result, Baseline, MCyclesPerCore (megacycles per core), MCyclesTotal (total megacycles), OS and Published. Note that megacycles calculations are based on the selected Exchange version, by default this is Exchange Server 2013.

A quick walk-through on the parameters:

  • CPU, Vendor or System can be used for partial matching on the respective attribute.
  • Type specifies what calculation to perform. Possible values are 2010 for Exchange Server 2010 and 2013 for Exchange Server 2013. Default value is 2013.
  • MinCores/MaxCores/Cores can be used to only return information for systems with less, more or a specific number of cores.
  • MinChips/MaxChips/Chips can be used to only return information for systems with this more, less or a specific number of CPU’s.
  • MinMegaCycles can be used to specify a threshold for the total megacycles value for returned items, using the specified Type for calculations.
  • Overhead can optionally be used to take into account a certain percentage for megacycles overhead. Default is 0 (0%).
  • Ratio/vCPU can be used to specify the vCPU:pCPU ratio. For example, specify a Ratio of 2 to use a 2:1 vCPU to pCPU ratio. Default is 1 (1:1). Use the vCPU paramete to specify the the number of vCPU allocated.

Few notes:

  • MinCores/MaxCores and MinChips/MaxChips are mutually exclusive, because we can not specify both in the query against the SPECint database. However, you can use additional filtering on objects returned in the pipeline to distill information, e.g.
    Exchange-PQT.ps1 –MaxCores 32 –MaxChips 8 | Where { $_.Cores –ge 4 –and $_.Chips –ge 2}.

    Do note that usage of these parameters is recommended when possibe, as it will minimize the result set from SPECint.

  • Make sure you set Type to 2010 when sizing for Exchange 2010.


Lookup the specifications of the server used by Jeff in his sizing example (Hewlett-Packard DL380p Gen8 server with Intel Xeon E5-2630 processors @2.30GHz):

.\Exchange-PQT.ps1 -System 'DL380p Gen8'  -CPU 2630 | select System,MCycle*

Search all specs for systems from Dell containing x5470 processors and return megacycle information for Exchange 2010 calculations:

.\Exchange-PQT.ps1 -CPU x5470 -Vendor 'Dell Inc.' -Type 2010 | Select System,*cycle*


Calculate average SPECint 2006 rate values for  hex-core x5450 systems:

.\Exchange-PQT.ps1 -CPU x5470 | Where { $_.Cores -eq 8 } | Measure -Average Result

Search all specs for Dell systems using x5670 CPUs, with a minimum total of 16,000 megacycles and 20% megacycle overhead:

.\Exchange-PQT.ps1 –Vendor Dell -CPU x5670  -MinMegaCycles 16000 -Overhead 20 


To calculate when using a non-1:1 vCPU:pCPU ratio, use Ratio in combination with vCPU. For example, to calculate the average SpecInt rate for 20 core systems with an E5-2670 CPU, using a 2:1 vCPU:pCPU ratio, allocating 12 vCPU cores:

.\Exchange-PQT.ps1 -CPU 'e5-2670' -Cores 20 -Ratio 2 -vCPU 12 | Measure-Object -Average -Property Result

You can download the script from the TechNet Gallery page.

Feedback is welcomed through the comments. If you got scripting suggestions or questions, do not hesitate using the contact form.

Revision History
See TechNet Gallery page.

Impersonation: To be, or pretend to be

imageAs frequent readers of this blog may know, I made several Exchange-related scripts available to the community. Some of these scripts make use of what is called Exchange Web Services (EWS). I receive lots of questions via e-mail and through the comments about configuring impersonation or permission-related issues when running those scripts, which support delegated access as well as impersonation, against mailboxes. This blog shows how can configure delegation, why you should use impersonation, and how to configure impersonation on Exchange 2007 up to Exchange 2013 and Exchange Online in Office 365.


EWS provides functionality to allow client applications, such as Outlook or OWA apps, tools, or in my case scripts, to communicate with Exchange server. Even Exchange itself makes uses of EWS when performing Free/Busy lookups by the Availability services for example. EWS was introduced in Exchange Server 2007 back in December 2006, which now seems decades ago.

Some of these EWS scripts or tools access or even manipulate mailbox contents. In the MAPI era, in order for you to access a mailbox that’s not yours, you required delegated full access permissions. These permissions could be granted at the mailbox, mailbox database or mailbox server level. The latter would grant you access to all mailboxes hosted in that mailbox database. For example, to grant an account Archibald full access permission on the mailbox of Nestor, you would typically use something like:

Add-MailboxPermission –Identity Nestor –User Archibald –AccessRights FullAccess –InheritanceType All

Note: Specifying InheritanceType is sometimes overlooked. Not specifying it only configures an Access Control Entry (ACE) on the top level folder (InheritanceType None), resulting in symptoms like scripts not processing subfolders for example.

EWS enables you to use another access method besides delegation, which is impersonation. Impersonation, as the many online available dictionaries may tell to you, is ‘an act of pretending to be another person for the purpose of entertainment or fraud’ or something along those lines. In the Exchange world, this means you can have an account which has the permission to pretend to be the owner of the mailbox, including being subject to the same effective permissions. So, if for some reason the owner only has Read permission on a certain folder, so will the impersonator. Typical use cases for impersonation are for example applications for archiving, reporting or migration, but also scheduled scripts that need to process mailboxes could be one.

Before we dive into the configuration itself, first some of the reasons why you should should prefer Impersonation over delegated access:

  • No mailbox needed for the account requesting access.
  • Throttling benefits, since the operation is subject to the throttling policy settings configured on the mailbox accessed, not the throttling policy configured on the mailbox requesting access. To bypass these delegate limits, one had to configure and assign a separate throttling policy with no limits for the account. Of course, a bad behaving application could then run without boundaries from a resource perspective, something throttling policies try to limit.
  • In Exchange 2010 and up, impersonation leverages Role Based Access Control, which is better manageable than a collection of distributed  ACEs.
  • Actions performed by the impersonator are on behalf of the impersonated. This may complicate auditing, as logging will come up with actions performed by the impersonated user, not the impersonator.

Note that where ‘user’ is specified below with regards to granting permissions, one could also specify a security group as well unless mentioned otherwise.

Impersonation on Exchange 2007

On Exchange 2007, you configure impersonation by granting the following two permissions:

  • The ms-Exch-EPI-Impersonation permission grants the impersonator the right to submit impersonation calls. It is configured on Client Access Servers. This does not grant the impersonation right, just the right the make the call through a CAS server.
  • The ms-Exch-EPI-May-Impersonate when granted, allows the impersonator to impersonate selected accounts.

To configure these permissions in your Exchange 2007 environment, use:

Get-ClientAccessServer | Add-AdPermission –User svcExchangeScripts –ExtendedRights ms-Exch-EPI-Impersonation

Then, we can configure impersonation permission on the mailbox level:

Get-Mailbox Tintin| Add-ADPermission –User svcExchangeScripts –ExtendedRights ms-Exch-EPI-May-Impersonate

on the database level:

Get-MailboxDatabase MailboxDB1 | Add-ADPermission –User svcExchangeScripts –ExtendedRights ms-Exch-EPI-May-Impersonate

or mailbox server level:

Get-MailboxServer MailboxServer1 | Add-ADPermission –User svcExchangeScripts –ExtendedRights ms-Exch-EPI-May-Impersonate

Be advised that members of the various built-in Admin groups are by default explicitly denied impersonation permissions on the server and database level, and deny overrules allow. You will notice this when querying impersonation configuration settings, for example on the database level (in the screenshot example, olrik was granted impersonation permissions):

Get-MailboxDatabase | Get-AdPermission | Where { $_.ExtendedRights –like ‘ms-Exch-EPI-Impersonation’} | Format-Table Identity, User, Deny, IsInherited, ExtendedRights –AutoSize


Note that permissions assigned on the mailbox may not immediately be reflected as you are administering them in Active Directory. Changes in Active Directory are subject to AD replication, and the Exchange Information Store caches information for up to 2 hours, so worst case it may take up to 2 hours and 15 minutes for new permission settings to be re-read from Active Directory.

Impersonation on Exchange 2010 and 2013

Exchange 2010 introduced Role Based Access Control, better known by its acronym RBAC. For a quick introduction to RBAC, see one of my earlier blogs here. There is a management role associated with impersonation, which is ApplicationImpersonation.

To enable a user impersonation rights, create a new assignment for ApplicationImpersonation and assign it to the user:

New-ManagementRoleAssignment –Name 'AIsvcExchangeScripts' –Role ApplicationImpersonation –User svcExchangeScripts

Note that if we want to assign these permissions to a security group, we need to use the SecurityGroup parameter instead of User, specifying the group name.

Now be careful, when used like this you will have granted that user or group permission to impersonate all users in your Exchange organization. Here is where RBAC comes into play, or more specific the RBAC feature named management role scopes. With write scopes for example, you can limit the scope of where you can make changes in Active Directory. For more information on management role scopes, see here.

Let  us assume we want to limit the scope to a distribution group named ‘All Employees’, using New-ManagementScope in combination with RecipientRestrictionFilter. Note that when specifying MemberOfGroup in the filter, you need to use the distinguishedName of the group:

New-ManagementScope –Name 'Employee Mailboxes' –RecipientRestrictionFilter { MemberOfGroup –eq 'CN=All Employees,OU=Distribution Groups,OU=NL,DC=contoso,DC=com'} 

We can then apply this scope to the assignment created earlier:

Set-ManagementRoleAssignment –Identity 'AIsvcExchangeScripts' –CustomWriteScope 'Employee Mailboxes'

Be advised that in a multi-forest environment, impersonation doesn’t work when you assign permissions to cross-forest accounts. You either need to assign impersonation permissions to an account residing in the same forest as Exchange, or create a linked role group.

Impersonation on Exchange Online

Impersonation is available in most Office 365 plans, but currently not in the small business plans.  To configure Impersonation in Exchange Online we need to connect anyway, so we’ll first open a remote PowerShell session to Exchange Online:

$EXO= New-PsSession -ConfigurationName Microsoft.Exchange -ConnectionUri https://ps.outlook.com/powershell -AllowRedirection -Authentication Basic
Import-PsSession $EXO

Provide tenant administrator credentials when prompted. You can then see if you have the ApplicationImpersonation role at your disposal using:

Get-ManagementRole –Identity ApplicationImpersonation

If nothing is returned, you may need to resort to delegate access permissions.

Configuring impersonation is identical to configuring it in Exchange 2013. Nonetheless, some people may be more comfortable using the Exchange Admin Center. If so:

  1. Open up Exchange Admin Center.
  2. Navigate to Permissions > Admin Roles
  3. Now we can’t directly assign a management role through EAC, so assume we’ll create a role group for our application account by clicking New (+).
  4. Enter a name for your role group, e.g. ExchangeMaintenanceScripts.
  5. Add the role ApplicationImpersonation.
  6. Add the accounts which need Impersonation permissions, e.g. svcExchangeScript.
  7. Optionally, you can also select a Write Scope, which you need to create upfront through Exchange Management Shell.
  8. In Exchange on-premises, instead of a Write Scope you will have the option to select a a specific OU instead (scope filter RecipientRoot parameter) .
  9. When done, Save.


One word of caution: scopes are not automatically updated when objects referenced are relocated or change names. Now, for your own environment you may have this under control through some form of change management process. For Exchange Online however, your tenant might get relocated without notice. Therefor, should impersonation fail, verify any management scopes you may have defined for distinguishedName references, and check if they require updating, e.g.

Set-ManagementScope -Name 'All Employees' -RecipientRestrictionFilter { MemberOfGroup -eq 'CN=All Employees,OU=contoso.onmicrosoft.com,OU=Microsoft Exchange Hosted Organizations,DC=EURPR05A001,DC=prod,DC=outlook,DC=com'}

Final words

Note that many EWS-based scripts or tools do not natively support EWS but make use of the Exchange Web Services Managed API. This installable package consists of support files (e.g. DLL’s) which provide EWS functions to your PowerShell environment. You can download the current version of EWS Managed API here (2.2). You can read more on developing with EWS Managed API here, or you can have a peek at the source of code of one of my EWS scripts or the ones published by Exchange MVP-fellow Glen Scales’ here.

Script Updates

powershellA small heads-up for those not following me on Twitter of one of the other social media channels. Last week I made updates to the following three scripts:

Install-Exchange2013.ps1, version 1.72

  • Added CU5 support
  • Added KB2971467 (CU5 Disable Shared Cache Service Managed Availability probes)

Remove-DuplicateItems.ps1, version 1.3

  • Changed parameter Mailbox, you can now use an e-mail address as well.
  • Added parameter Credentials.
  • Added item class and size for certain duplication checks.
  • Changed item removal process
  • Remove items after, not while processing folder. Avoids asynchronous deletion issues.
  • Works against Office 365.

Remove-MessageClassItems.ps1, version 1.3

  • Changed parameter Mailbox, you can now use an e-mail address as well
  • Added parameter Credentials
  • Added parameter PartialMatching for partial class name matching.
  • Changed item removal process. Remove items after, not while processing folder. Avoids asynchronous deletion issues.
  • Works against Office 365.
  • Deleted Items folder will be processed, unless MoveToDeletedItems is used.
  • Changed EWS DLL loading, can now be in current folder as well.

Be advised I keep am overview of the scripts and their current versions with publish dates here.



powershellLast update: Version 1.02, November 21st, 2014.

Those leveraging quota settings to manage their Exchange environments, you are probably periodically running some sort of script or set of cmdlets to retrieve information on mailbox sizes, quota settings and if any mailbox is above any of the quota thresholds. For a quick indication of the current size in relation to the quota settings, StorageLimitStatus may contain one of the following indicators depending on the quota settings on the mailbox or mailbox database hosting the mailbox:

  • BelowLimit – Speaks for itself
  • IssueWarning – Mailbox size above Issue Warning limit
  • ProhibitSend – Mailbox size above Prohibit Send limit
  • NoChecking – No quota checking
  • MailboxDisabled – Mailbox size above Prohibit Send and Receive quota limit

So, to get a list of all mailboxes with any over-quota status, you can use:

Get-MailboxDatabase | Get-MailboxStatistics | Where {$_.StorageLimitStatus -match 'IssueWarning|ProhibitSend|MailboxDisabled'} | Select DisplayName, ItemCount, TotalItemSize, StorageLimitStatus, LastLogonTime

Unfortunately, in Exchange 2013 the StorageLimitStatus gets no longer populated:


As KB2819389 explains, this is by design. In Exchange 2013, mailbox quotas are no longer cached. By not being cached, retrieving quota information may result in poor performance as it queries Active Directory for quota related attributes. The argument is a bit puzzling, considering there is a NoADLookup switch which directs the cmdlet to retrieve information from the mailbox database (cache) instead of Active Directory. Perhaps a better workaround would have been to make NoADLookup a parameter, make it $true by default and leave StorageLimitStatus unpopulated when NoADLookup is $true.

Of course, that does not help customers who want a quick quota report. For this purpose I have created two things in 1 script:

  1. A helper function Get-StorageLimitStatus() which will take a mailbox statistics object and return a StorageLimitStatus object.
  2. A script Get-MyMailboxStatistics.ps1, a proxy function for Get-MailboxStatistics which will use the Get-StorageLimitStatus helper function to populate the StorageLimitStatus.

When you want to use the helper function, extract it and include it in your quota reporting script or PowerShell profile (making it available when firing up a shell). To use the helper function in the cmdlet shown earlier, use:

Get-MailboxDatabase | Get-MailboxStatistics | Select -ExcludeProperty StorageLimitStatus DisplayName, ItemCount, TotalItemSize, @{n="StorageLimitStatus"; e={ Get-StorageLimitStatus $_}}, LastLogonTime | Where {$_.StorageLimitStatus -match 'IssueWarning|ProhibitSend|MailboxDisabled'}

This will remove StorageLimitStatus from the output and add a calculated field bearing the same the name, calling the Get-StorageLimitStatus helper function with the current mailbox statistics object to set its value.

This is a proxy function for the Exchange Management Shell cmdlet Get-MailboxStatistics. This means that the current, original cmdlet was used to create a wrapper which will call the original cmdlet. Having a wrapper allows you to restrict or enhance the original cmdlet and tailor it to your needs.

A quick tip on how to create a proxy script in the clipboard (more information on creating proxy commands here):

$data= New-Object System.Management.Automation.CommandMetaData (Get-Command Get-MailboxStatistics) 
[System.Management.Automation.ProxyCommand]::create($data) | clip.exe

Downside is that future changes to the Get-MailboxStatistics cmdlet will not be automatically incorporated in the wrapper. Feeding it objects also doesn’t work, but you can work around that by temporary storing the objects in a variable and passing that to the script (see examples below).

To populate the StorageLimitStatus, we will post-process each object in the output of Get-MailboxStatistics, using Add-Member to overwrite (-Force) its current value and –PassThru to pass it along in the pipeline. Being a proxy command, the parameter options are identical to the original Get-MailboxStatistics. Some examples:

.\Get-MailboxStatistics.ps1 -Database MDB2
$m= Get-Mailbox –Database MDB2 
$m | .\Get-MailboxStatistics.ps1 | ft –AutoSize DisplayName,TotalItemSize,StorageLimitStatus


Do be aware that this will incur Active Directory queries and thus performance of the script may not seem fast. However, in previous versions of Exchange you got immediate results as all the quota information was readily available from the cache. On the plus side, the status you see will be non-cached, current information.

On a final note and maybe needless to say that in order to use this you need to run it from the Exchange Management Shell and since it’s an unsigned script you need to set ExecutionPolicy to Unrestricted.

Feedback is welcomed through the comments. If you got scripting suggestions or questions, do not hesitate using the contact form.

You can download the script from the TechNet Gallery here.

Revision History
See Technet Gallery page.