Category Archives: 13186

Reporting Outlook Client Versions Using Log Parser

I’m doing a little cross-pollination today. Chris Lehr, one of my colleagues at ExtraTeam, worked up a Log Parser script that produces a report showing all the clients versions connecting to Exchange.  This is very helpful to show which clients are running Office versions in your organization that should be updated prior to migration.  Check out his blog post here.



Outlook Client Version Report

Clients will always get the best experience using the latest version of Office, currently Office 2013 SP1. The best practice is to always update your clients with the latest cumulative update prior to migration. this is especially true when you’re migrating to Office 365, since most updates pertain to Office 365, Exchange Online, and Exchange 2013 compatibility.



If you find that you need to upgrade clients to a new version of Office, I recommend that you install the x86 version of Office to provide the best compatibility with add-ons and third-party products. Some customers think they need to install Office x64 on Windows x64 operating systems, but that’s not the case. See 64-bit editions of Office 2013 for details on when it makes sense to install Office x64.



If you’re an Office 365 customer, I strongly recommend checking out using the Office 2013 ProPlus software deployment that’s most likely part of your Enterprise license. This version of Office 2013 can be installed on up to 5 PCs, iPads, tablets, etc. and is always up-to-date since it’s a cloud-managed service.




Fix for Exchange ActiveSync Failures After Migration to Exchange 2013

There’s a bug in Exchange 2013 that causes Exchange ActiveSync to fail for newly migrated users from Exchange 2010. It only affects migrated users who already have a mobile device configured, not new users (i.e., test mailboxes). This issue was discussed in the Exchange Server forums back in August 2013.


The issue occurs because the IIS application pools on the CAS 2013 servers do not automatically detect that the mailbox has been moved to Exchange 2013. When the user’s mobile device connects to CAS 2013, CAS 2013 proxies the user back to CAS 2010 which responds with an error saying the mailbox is corrupt or missing. If you run an Exchange ActiveSync test using ExRCA you will see the X-CalculatedBETarget value reported by CAS2013 is still pointing to the Exchange 2010 server. The problem usually resolves itself in 1-8 hours, depending on the Exchange 2013 build.

The workaround is to manually recycle the MSExchangeAutodiscoverAppPool and MSExchangeSyncAppPool application pools in IIS on all CAS2013 servers.

I wrote a PowerShell script for this called Recycle-AppPools.ps1:

#Recycle-AppPools.ps1
#Jeff Guillet, MCM|MCSM|MVP|CISSP
#Use this script to recycle IIS Application Pools to overcome Exchange 2013 SP1 ActiveSync bug for migrated users

#Get all Exchange 2013 CAS servers
$CASServers = Get-ClientAccessServer | where {$_.WorkloadManagementPolicy -ne $null}

#Loop through each CAS2013 and recycle the IIS App Pools
foreach ($CAS in $CASServers) {
  Write-Host “Recycling App Pools on $CAS…”
  $appPool = Get-WmiObject -Authentication PacketPrivacy -Impersonation Impersonate -ComputerName $CAS -namespace “root/MicrosoftIISv2″ -class IIsApplicationPool | Where-Object {$_.Name -eq “W3SVC/AppPools/MSExchangeAutodiscoverAppPool” }
  $appPool.Recycle()
  $appPool = Get-WmiObject -Authentication PacketPrivacy -Impersonation Impersonate -ComputerName $CAS -namespace “root/MicrosoftIISv2″ -class IIsApplicationPool | Where-Object {$_.Name -eq “W3SVC/AppPools/MSExchangeSyncAppPool” }
  $appPool.Recycle()
}

You will need to run the script after an EAS user or batch of users have been migrated. There is no outage associated with recycling the app pools and it recycles very quickly. A fix is scheduled for Exchange 2013 CU5.



Script to Force Download of the Lync 2013 Address Book

In a previous article I wrote a script that forces Lync 2010 clients to update the Lync Server 2010 address book.



The Lync 2013 client not only changes the location where the address book is stored on the local machine, but changes the address book file name for Lync Server 2013, as well.



The script below sets the GALDownloadInitialDelay key in the registry to force the Lync client to download the address book immediately after signing in.  It then enumerates all the SIP_* sub-folders in the C:\Users\%username%\AppData\Local\Microsoft\Office\15.0\Lync folder and deletes the ABS__sipdomain.cache file which makes up the local Lync 2013 address book and the GAL*.* files that make up the local Lync 2010 address book.



@echo off
echo.
rem Check if Lync is running, exit if it is…
tasklist /fi “IMAGENAME eq lync.exe” | find “lync.exe” >nul
If %errorlevel%==0 goto LyncIsRunningError
rem Add x86 GALDownloadInitialDelay registry entry
reg add HKCU\Software\Policies\Microsoft\Communicator /v GALDownloadInitialDelay /t REG_DWORD /d 0 /f >nul
If %errorlevel%==1 goto ElevationError
rem Add WOW64 GALDownloadInitialDelay registry entry if x64
If %PROCESSOR_ARCHITECTURE%==AMD64 reg add HKCU\Software\Wow6432Node\Policies\Microsoft\Communicator /v GALDownloadInitialDelay /t REG_DWORD /d 0 /f >nul
If “%LOCALAPPDATA%”==”” Set LOCALAPPDATA=%USERPROFILE%\Local Settings\Application Data
dir “%LOCALAPPDATA%\Microsoft\Office\15.0\Lync\sip_*” /b > list.txt
FOR /F “tokens=1″ %%i in (list.txt) do (
rem Delete the Lync Server 2010 address book…
If Exist “%LOCALAPPDATA%\Microsoft\Office\15.0\Lync\%%i\gal*.*” del “%LOCALAPPDATA%\Microsoft\Office\15.0\Lync\%%i\gal*.*”
rem Delete the Lync Server 2013 address book…
If Exist “%LOCALAPPDATA%\Microsoft\Office\15.0\Lync\%%i\abs*.cache” del “%LOCALAPPDATA%\Microsoft\Office\15.0\Lync\%%i\abs*.cache”
)
del list.txt
echo Clearing Lync 2013 Address Books…  Done!
echo.
echo Sign back into Lync 2013 to download the current address book.
goto End
:ElevationError
echo ERROR: You must run this command from an elevated Command Prompt.
echo.
goto End
:LyncIsRunningError
echo ERROR: You must exit Lync 2013 before running this command. Right-click the Lync icon and choose Exit.
echo.
:End

Save the script above as UpdateLync2013AddressBook.bat.  Exit out of the Lync client and run the script from an elevated Command Prompt. Then sign back into Lync and the address book will download immediately.




Output from UpdateLync2013AddressBook.bat


Working with Hi-Res Photos in Exchange 2013 and Lync 2013

Exchange 2013 and Lync 2013 now have the ability to use high-resolution photos for users to view photos of their contacts and to make their own photos
available to others.  Usually these photos were stored as part of the user’s thumbnailPhoto
attribute in Active Directory.  The recommended resolution for photos stored in the thumbnailPhoto attribute is 96 pixels by 96 pixels.  In addition, the thumbnailPhoto attribute has a physical limit of 100KB, but Exchange 2010 and Lync 2010 impose a limit of 10KB.  This limit was imposed to reduce the size of the Active Directory database and increase replication performance.



Lync 2013 now features a larger contact photo for meeting participants.  It scales those small 96×96 pixel thumbnailPhotos up to 278×278 pixels, which results in a blurry, but still usable, photo.



96×96 pixel photo displayed in Lync 2013

The new high-res photos used by the Wave 15 products (Exchange 2013, Lync 2013, SharePoint 2013, and Office 2013) are now stored in the user’s Exchange 2013 mailbox and are accessed using Exchange Web Services (EWS).  This makes a lot of sense since Exchange is installed in almost all of these environments.  Lync 2013 now allows for photo sizes up to 648 pixels by 648 pixels – a 700% improvement!  Just look at that handsome devil!



648×648 pixel photo displayed in Lync 2013

The following script sample can be used to store a 648 by 648 pixel photo in Ken Myer’s Exchange 2013 mailbox:



$photo = ([Byte[]] $(Get-Content -Path “C:\Photos\Ken Myer.jpg” -Encoding Byte -ReadCount 0))
Set-UserPhoto -Identity kenmyer -PictureData $photo -Confirm:$False
Set-UserPhoto -Identity kenmyer -Save -Confirm:$False



Exchange 2013 automatically scales this 648×648 photo for various applications. The following examples show the same hi-res photo in Office 2013 and Lync 2013 scaled to different sizes.



Outlook 2013 contact view

My Picture option in Lync 2013

Notice in the Lync 2013 example above that there’s a button to allow users to edit or remove their picture.  That button only lights up in Lync 2013 if the user’s mailbox is hosted on an Exchange 2013 server.  There is no “self-service” way to upload pictures with Exchange 2010, although it can be done from SharePoint 2010.



But before you go updating all the photos of employees in your company with new hi-res photos, you should know a few things about backward compatibility.  The Set-UserPhoto cmdlet, which only exists in Exchange 2013 and is used in the script above, not only stores the hi-res photo in the user’s mailbox, it also stores a 48×48 pixel version in the thumbnailPhoto AD attribute.  That’s half the resolution of the 96×96 recommended size and results in a terrible photo for users on Exchange 2010.



48×48 pixel thumbnailPhoto displayed in Lync 2013

It’s interesting to note that Exchange 2010 users always use the 48×48 thumbnailPhoto attribute in AD.  Lync 2013 won’t look for a hi-res photo in the Exchange 2013 user’s mailbox if the Lync 2013 user is on Exchange 2010.  This gives a less than optimal view for the Exchange 2010 Lync user:






This is really only an issue for customers in an migration scenario, but it’s worth noting.  The point is that you should only update Exchange 2013 mailbox users with hi-res photos.



For more information about high resolution photos used in Lync 2013 see Configuring the Use of High-Resolution Photos in Microsoft Lync Server 2013, but please keep in mind that the script examples in that article have typos in them.  The script above corrects those errors.



You may also want to read GAL Photos in Exchange 2010 and Outlook 2010.


How to Boot Directly into Desktop with Windows Server 2012




I love Windows Server 2012, I really do.  But who’s bright idea was it to boot to the “Modern UI” (aka, Metro) instead of the Windows Desktop?  There’s really no reason for this, so I wrote a PowerShell script that configures Windows Server 2012 to boot directly into the Desktop after signing in.



This is not a hack.  The script simply changes rights on an existing registry key to allow the value to be changed, and changes it.



NOTE: This script does not work on Windows 8 — It only works on Windows Server 2012.  Early beta builds of Windows 8 allowed you to toggle booting to the Desktop.  Microsoft removed those hacks in the RTM build of Windows 8, sorry.  :(



You may also want to read my article, How to Enable Autologon for Windows Server 2008 Member Servers and Windows 7 Member Workstations.  Those procedures also work for Windows Server 2012 and Windows 8.



Copy and paste the following text into Notepad and save it as BootToDesktop.ps1 on your Windows Server 2012 computer:



#Take Ownership of the “HKLM:\SOFTWARE\Microsoft\Windows NT\CurrentVersion\Server” registry key
$definition = @”
using System;
using System.Runtime.InteropServices;
namespace Win32Api
{
    public class NtDll
    {
        [DllImport(“ntdll.dll”, EntryPoint=”RtlAdjustPrivilege”)]
        public static extern int RtlAdjustPrivilege(ulong Privilege, bool Enable, bool CurrentThread, ref bool Enabled);
    }
}
“@
Add-Type -TypeDefinition $definition -PassThru
$bEnabled = $false
$res = [Win32Api.NtDll]::RtlAdjustPrivilege(9, $true, $false, [ref]$bEnabled)
$key = [Microsoft.Win32.Registry]::LocalMachine.OpenSubKey(“SOFTWARE\Microsoft\Windows NT\CurrentVersion\Server”, [Microsoft.Win32.RegistryKeyPermissionCheck]::ReadWriteSubTree,[System.Security.AccessControl.RegistryRights]::takeownership)
$acl = $key.GetAccessControl()
$acl.SetOwner([System.Security.Principal.NTAccount]”Administrators”)
$key.SetAccessControl($acl)

#Give Full Control of the key to BUILTIN\Administrators

$acl = Get-Acl “HKLM:\SOFTWARE\Microsoft\Windows NT\CurrentVersion\Server”
$rule = New-Object System.Security.AccessControl.RegistryAccessRule(“BUILTIN\Administrators”,”FullControl”,”Allow”)
$acl.SetAccessRule($rule)
$key.SetAccessControl($acl)
$key.Close()

#Set the value of ClientExperienceEnabled to 0 to enable boot to Desktop

Set-ItemProperty -Path “HKLM:\SOFTWARE\Microsoft\Windows NT\CurrentVersion\Server” -Name ClientExperienceEnabled -Value 0



Optionally, you can download the BootToDesktop.ps1 script here.



Now simply run the BootToDesktop.ps1 script from an elevated Windows PowerShell prompt and reboot.  The next time you sign in Windows Server 2012 will go straight into the Desktop.



The PowerShell script does three things:

  • It assigns ownership of the HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows NT\CurrentVersion\Server registry key to the local built-in Administrators group.  By default this key is owned by the protected TrustedInstaller security principal.
  • Full control is given on the key to the built-in Administrators group.  By default built-in Administrators only have Read access.  Full control gives us the ability to change values in the key.
  • Changes the ClientExperienceEnabled value from 1 to 0, which configures Windows to start directly to the Desktop.






Windows Server 2012 and Windows 8 secure protected registry keys and files using the TrustedInstaller security principal.  TrustedInstaller is a core part of Windows Resource Protection (WRP) technology.  Windows usually assigns ownership of WRP protected items to TrustedInstaller and they normally cannot be modified or deleted.  This script overcomes that and allows you to change the value of the ClientExperienceEnabled value.



Since this is really just a simple registry change, you can safely use it in your server imaging process for all your Windows Server 2012 computers.  It only needs to be run once per server and affects all users who logon to that server.

Great New Free Utilities from Microsoft

Microsoft has released a number of great new utilities designed to make administration easier, especially in the Exchange space.  Most of these have been released in just the past three weeks.



  • Exchange Client Network Bandwidth Calculator BETA2 (link)

Helps reduce the risks involved in Exchange Server network bandwidth planning.  The Exchange Client Network Bandwidth Calculator has been designed to help anyone planning an Exchange Server deployment to predict the network bandwidth requirements for a specific set of clients.  The prediction algorithms used within this calculator are entirely new and have been derived after significant testing and observation.



  • Log Parser Studio (link)

Log Parser Studio is a utility that allows you to search through and create reports from your IIS, Event, EXADB and others types of logs. It builds on top of Log Parser 2.2 and has a full user interface for easy creation and management of related SQL queries.



Anyone who regularly uses Log Parser 2.2 knows just how useful and powerful it can be for obtaining valuable information from IIS (Internet Information Server) and other logs. In addition, adding the power of SQL allows explicit searching of gigabytes of logs returning only the data that is needed while filtering out the noise. The only thing missing is a great graphical user interface (GUI) to function as a front-end to Log Parser and a ‘Query Library’ in order to manage all those great queries and scripts that one builds up over time.

Log Parser Studio was created to fulfill this need; by allowing those who use Log Parser 2.2 (and even those who don’t due to lack of an interface) to work faster and more efficiently to get to the data they need with less “fiddling” with scripts and folders full of queries.

  • Outlook Configuration Analyzer Tool (OCAT) (link)

The Outlook Configuration Analyzer Tool provides a detailed report of your current Outlook profile. This report includes many parameters about your profile, and it highlights any known problems that are found in your profile. For any problems that are listed in the report, you are provided a link to a Microsoft Knowledge Base (KB) article that describes a possible fix for the problem. If you are a Help Desk professional, you can also export the report to a file. Then, the report can be viewed in the Outlook Configuration Analyzer Tool on another client computer where the tool is installed.



  • CalCheck – The Outlook Calendar Checking Tool (link)

 The Calendar Checking Tool for Outlook is a command-line program that checks Outlook Calendars for problems. To use this tool, the Outlook calendar must reside on a Microsoft Exchange Server. The tool does not work with IMAP, with POP3, or with other non-Exchange mail servers.



The tool opens an Outlook profile, opens the Outlook Calendar, and then checks several things such as permissions, free/busy publishing, and auto booking. Then, the tool checks each item in the calendar folder for problems that can cause items to seem to be missing or that might otherwise cause problems in the Calendar.



And last, but not least…








  • Microsoft Script Explorer for Windows PowerShell Beta 1 (link)

Helps scripters find Windows PowerShell scripts, snippets, modules, and how-to guidance in online repositories such as the TechNet Script Center Repository, PoshCode, local or network file systems and Bing Search Repository.

 



 

 

Script to Force Download of the Lync Address Book

I wrote a script (batch file, really) that users can run to force a download of the Lync address book. 

The Lync address book is generated automatically on the Lync server every 24 hours at 1:30AM, local server time.  The address book is then downloaded by the Lync clients in a randomized schedule from 1 to 60 minutes after the client starts up.  Lync Server MVP Jeff Schertz wrote about this process in great detail in his post, Updating the Lync 2010 Address Book.

You can use the Update-CsAddressBook cmdlet on the Lync server to force the server to update the address book.  You will need to wait 5 minutes for the server to run the update.  Look for Lync Server event 21056 from LS Address Book Server to confirm that the address book update has completed, as shown below:


My script sets a GALDownloadInitialDelay key in the registry to force the Lync client to download the address book immediately after signing in.  It then enumerates all the SIP_* folders in the C:\Users\username\AppData\Local\Microsoft\Communicator folder and deletes the GalContacts.db and GalContacts.db.idx files which make up the Lync address book.

@echo off
echo Clearing Lync Address Books…
reg add HKEY_CURRENT_USER\Software\Policies\Microsoft\Communicator -v GALDownloadInitialDelay -t reg_dword -d 0 -f
If %errorlevel%==1 goto Error
dir %LOCALAPPDATA%\Microsoft\Communicator\sip_* /b > list.txt
FOR /F “tokens=1″ %%i in (list.txt) do del %LOCALAPPDATA%\Microsoft\Communicator\%%i\gal*.*
echo.
echo Sign out of Lync and sign back in to download the current address book.
goto End
:Error
echo You must run this command from an elevated Command Prompt.
echo.
:End
Save the script above as ClearLyncAddressBook.bat and run it from an elevated Command Prompt.  Then sign out and back into Lync and the address book will download immediately.


Deploying the Lync 2010 Client to different architectures

The Lync Server 2010 client is a single unified communications client that replaces both the Office Communicator and Live Meeting clients.  This single client performs all the functions of the previous clients, including instant messaging (IM), web conferencing, white boarding, desktop sharing, and enterprise voice.

There are two versions of the Lync 2010 client, one for x86 and one for x64 operating systems.  The difference is the bootloader.  Somewhat surprisingly, the Lync client itself is always 32-bit.  If you try to deploy the x86 version of the client on an x64 computer (or vice versa), you will get an error message.


This can be somewhat problematic if you are trying to automatically deploy the Lync client using Group Policy or some other automated scripting mechanism to mixed-architecture computers in your environment.

Note: The Outlook Online Meeting add-on will match the 32- or 64-bit version of Office 2007/2010 installed, regardless of the Lync client architecture installed.

The rest of this article discusses how to run the correct architecture Lync client using a single batch file.  This batch file can be called using a computer startup script or a user logon script in Group Policy, or any other automated process.

First, create a network share called Lync Clients for the Lync 2010 client installer packages, with subfolders called x86 and x64.  Then copy the x86 and x64 Lync client installers into the proper folder, as shown below.

Lync Client Share
 This sample batch file will run the correct Lync client installer for the computer’s given architecture. 
Set ARCHITECTURE=x86
If Exist “%SystemDrive%\Program Files (x86)” Set ARCHITECTURE=x64

“\\server\Lync Clients\%ARCHITECTURE%\LyncSetupVolume.exe”
As mentioned earlier, you can then deploy this script via Group Policy or your favorite deployment mechanism.  Note that the Lync installer must be run as a user with rights to install software.  For this reason, it may be easier to install as a computer startup script.

Introducing LyncAddContacts!

The Office Communications Server 2007 Resource Kit Tools featured a nifty tool called LCSAddContacts.  This WSF script allows you to add contacts to LCS or OCS (but not Lync Server) using WMI.  I was hoping to see a version of this tool for Lync Server, but no such luck — So I wrote one myself.

I’m surprised to find that there is no PowerShell cmdlet that allows you to add contact groups or contacts, and since there are no WMI classes for Lync Server anymore, I needed a way to do this — so I wrote a tool myself.  I leverage the DBIMPEXP utility from the Lync Server DVD to import and export contacts. 

The purpose of LyncAddContacts is to add the same contact groups and contacts to multiple users programatically.  For example, you may want to import a contact group called “Company Contacts”  that contains contacts for everyone in the company.  Here’s how it works:
  1. Create a template (source) user in Lync with the contact groups and contacts that you want to export.
  2. Run the LyncAddContacts tool to export the source user’s contacts
  3. Run the LyncAddContacts tool again in import mode and target the user or OU that you want to import the contacts to.
Prerequisites:
  • The tool must be run on the Lync server from which you will export/import the data.
  • You must be a member of the CSAdministrator security group to run this tool.  This group has rights to export and import contact groups and contacts to all users.
  • You must copy the DBIMPEXP.EXE tool from the \Support folder on the Lync Server 2010 installation media to the same folder where the LyncAddContacts tool will be run.
  • You must have read, write and execute rights to the folder where the LyncAddContacts tool will be run.
Note: This tool must be run under the CScript host due to the amount of output generated.  You will see a syntax pop-up window if the tool runs under WScript.

Usage:

First, you must export the source user’s contact groups and contacts.  The following example exports this information from a user named “Source” on a Lync Standard Edition server:
where source@domain.com is the SIP address of the user you want to export.
CScript LyncAddContacts.vbs source@domain.com
The following example performs the same export on a Lync Enterprise Edition server:
CScript LyncAddContacts.vbs source@domain.com sql.domain.com
where source@domain.com is the SIP address of the user you want to export and sql.domain.com is the SQL server used by the front-end pool.

Second, you import the contact groups and contacts to either a single target user or a target Organizational Unit in your domain.  The following example imports the data to a user named “Target” on a Lync Standard Edition server:
CScript LyncAddContacts.vbs /import target@domain.com
where target@domain.com is the SIP address of the user you want to import the contact info to.  For Lync Server Enterprise Edition you must add the SQL server used by the front-end pool, as shown above.

The following example imports the same contact groups and contacts to all the SIP enabled users in the Users container in Active Directory:
CScript LyncAddContacts.vbs /import CN=Users,DN=domain,DN=com
Again, for Lync Server Enterprise Edition you must add the SQL server used by the front-end pool, as in this example:
CScript LyncAddContacts.vbs /import OU=Lync Users,DN=domain,DN=com” sql.domain.com
A nice benefit of this tool is that contacts will not get a notification that so-and-so has added them to their contact list.  This is really useful in preventing unnecessary pop-ups from the Lync client.


Download LyncAddContacts.  View the source code here.


Disclaimer: I hope that the information in this blog is valuable to you. Your use of the information contained in these pages, however, is at your sole risk. All information on these pages is provided “as -is”, without any warranty, whether express or implied, of its accuracy, completeness, fitness for a particular purpose, title or non-infringement, and none of the third-party products or information mentioned in the work are authored, recommended, supported or guaranteed by The EXPTA {blog}. Further, EXPTA shall not be liable for any damages you may sustain by using this information, whether direct, indirect, special, incidental or consequential, even if it has been advised of the possibility of such damages.

Reporting Database Whitespace for All Exchange Servers

The physical size of an Exchange database normally grows as data is added to it.  When data is removed the amount of data is reduced, but the physical database size (the amount of space taken up on the disk) does not shrink.  This empty space in the database file is called whitespace.

For example, if you move half of the mailboxes from DB01 to DB02, DB01 will remain the same physical size on the disk, but half of it will be whitespace.  Normally this is not a big deal, but it might be important to you if you need to reclaim that unused disk space.  Also, some backup software backs up the entire database, including whitespace.  That means you might be wasting backup tapes and time backing up empty data.

Exchange has always reported the database whitespace in the Application event log as Event ID 1221 during scheduled online maintenance, as shown below:


However with Exchange 2010 and its 24×7 ESE scanning, this event is no longer logged since online database maintenance runs all the time by default.  You can view the amount of whitespace in any given database using the following cmdlet in the Exchange Managment Shell:
Get-MailboxDatabase Database1 -Status | FT Name,AvailableNewMailboxSpace
The output looks like this:
 
 
Unfortunately, this cmdlet doesn’t work on previous versions of Exchange, so I leveraged some code by Shay Levy to write a Powershell script that collects the data from the 1221 events on each server in the Org and exports it to a CSV file.
 
Click here to download the Get-ExchangeWhitespace script.
 
The script must be run from the Exchange Management Shell (EMS).  It creates a collection of all the Exchange servers (except Edge Transport servers) from AD, and connects to each server’s Application log using WMI.  It then collects the data from the 1221 events from the previous day’s online maintenance schedule and exports it to a file called ‘Exchange Whitespace.csv’.  Despite all these steps, it’s really fast to execute.

If you want to reclaim the whitespace in a database, you need to perform an offline defrag.  You will dismount the database and run the Eseutil /D command, as detailed here.  Be aware that this can take quite a long time and you need sufficient free space on the volume to run it.