Exchange 2010 bits and pieces

Here are a few bits and pieces for optimizing an Exchange 2010 deployment:

Moving the Transport Database and Queue (e.g. to a fast disk):
cd $exscripts; .\Move-TransportDatabase.ps1 -queueDatabasePath "T:\TransportRoles\Data\Queue\DB" -queueDatabaseLoggingPath "T:\TransportRoles\Data\Queue\Logs"

Note: Do not create the folders! You can create the root folders but NOT the host folders (e.g. In above I mean do NOT create 'DB' or 'Logs' folders)

Configure the Cluster Account environment variables (Local System on Windows 2008 R2) to a dedicated volume:
Set-ItemProperty -path "REGISTRY::\HKEY_USERS\S-1-5-18\Environment" -name TMP -value T:\Temp; Set-ItemProperty -path "REGISTRY::\HKEY_USERS\S-1-5-18\Environment" -name TEMP -value T:\Temp

Notice that the above is using the Set-ItemProperty with the registry and specifically with HKEY_USERS. That wasn’t easy to work out how to target!

Configure Cluster parameters:
Import-module FailoverClusters; (Get-Cluster).SameSubnetThreshold=10; (Get-Cluster).SameSubnetDelay=1000

Configure ClusterLog size:
New-ItemProperty -Path "HKLM:\SYSTEM\CurrentControlSet\Control\Session Manager\Environment" -Name ClusterLogSize -Value 32 -Type DWord



Create mailboxes with EMS

I couldn't find my script for setting up test mailboxes for an Exchange 2010 environment that I am working on, so I had to re-write it. Sometimes it's just quicker to go back to the drawing board!

My scenario is that I have 30 databases and I want to create one mailbox per database. I also want to keep these at the end of the GAL so as not to upset existing users, so I'm naming them 'zztestuser' with a number appended.

So that I can run this quickly without having to input anything, I am first converting a plain text password to a secure string and using it throughout the script. Once it is defined as a variable I can re-use it again and again. So the first two lines do that bit and then it's all quite repetitive. I used Excel with the Concatenate function to put it all together, but the fields in Excel have their limitations, so a mix of Excel and Notepad with the 'replace' feature work well.

Here is my script for creating 30 new mailboxes with one in each database. Copy the code, modify as appropriate and save to a ps1.


$PlainPassword = "P@ssw0rd"
$SecurePassword = $PlainPassword | ConvertTo-SecureString -AsPlainText –Force
New-Mailbox -Name 'zztestuser01' -Alias 'zztestuser01' -OrganizationalUnit 'domain.com/Users' -UserPrincipalName 'zztestuser01@domain.com' -SamAccountName 'testuser01' -FirstName 'zztestuser' -Initials '' -LastName '01' -Password $SecurePassword -ResetPasswordOnNextLogon $false -Database 'DB01'
New-Mailbox -Name 'zztestuser02' -Alias 'zztestuser02' -OrganizationalUnit 'domain.com/Users' -UserPrincipalName 'zztestuser02@domain.com' -SamAccountName 'testuser02' -FirstName 'zztestuser' -Initials '' -LastName '02' -Password $SecurePassword -ResetPasswordOnNextLogon $false -Database 'DB02'
New-Mailbox -Name 'zztestuser03' -Alias 'zztestuser03' -OrganizationalUnit 'domain.com/Users' -UserPrincipalName 'zztestuser03@domain.com' -SamAccountName 'testuser03' -FirstName 'zztestuser' -Initials '' -LastName '03' -Password $SecurePassword -ResetPasswordOnNextLogon $false -Database 'DB03'
New-Mailbox -Name 'zztestuser04' -Alias 'zztestuser04' -OrganizationalUnit 'domain.com/Users' -UserPrincipalName 'zztestuser04@domain.com' -SamAccountName 'testuser04' -FirstName 'zztestuser' -Initials '' -LastName '04' -Password $SecurePassword -ResetPasswordOnNextLogon $false -Database 'DB04'
New-Mailbox -Name 'zztestuser05' -Alias 'zztestuser05' -OrganizationalUnit 'domain.com/Users' -UserPrincipalName 'zztestuser05@domain.com' -SamAccountName 'testuser05' -FirstName 'zztestuser' -Initials '' -LastName '05' -Password $SecurePassword -ResetPasswordOnNextLogon $false -Database 'DB05'
New-Mailbox -Name 'zztestuser06' -Alias 'zztestuser06' -OrganizationalUnit 'domain.com/Users' -UserPrincipalName 'zztestuser06@domain.com' -SamAccountName 'testuser06' -FirstName 'zztestuser' -Initials '' -LastName '06' -Password $SecurePassword -ResetPasswordOnNextLogon $false -Database 'DB06'
New-Mailbox -Name 'zztestuser07' -Alias 'zztestuser07' -OrganizationalUnit 'domain.com/Users' -UserPrincipalName 'zztestuser07@domain.com' -SamAccountName 'testuser07' -FirstName 'zztestuser' -Initials '' -LastName '07' -Password $SecurePassword -ResetPasswordOnNextLogon $false -Database 'DB07'
New-Mailbox -Name 'zztestuser08' -Alias 'zztestuser08' -OrganizationalUnit 'domain.com/Users' -UserPrincipalName 'zztestuser08@domain.com' -SamAccountName 'testuser08' -FirstName 'zztestuser' -Initials '' -LastName '08' -Password $SecurePassword -ResetPasswordOnNextLogon $false -Database 'DB08'
New-Mailbox -Name 'zztestuser09' -Alias 'zztestuser09' -OrganizationalUnit 'domain.com/Users' -UserPrincipalName 'zztestuser09@domain.com' -SamAccountName 'testuser09' -FirstName 'zztestuser' -Initials '' -LastName '09' -Password $SecurePassword -ResetPasswordOnNextLogon $false -Database 'DB09'
New-Mailbox -Name 'zztestuser10' -Alias 'zztestuser10' -OrganizationalUnit 'domain.com/Users' -UserPrincipalName 'zztestuser10@domain.com' -SamAccountName 'testuser10' -FirstName 'zztestuser' -Initials '' -LastName '10' -Password $SecurePassword -ResetPasswordOnNextLogon $false -Database 'DB10'
New-Mailbox -Name 'zztestuser11' -Alias 'zztestuser11' -OrganizationalUnit 'domain.com/Users' -UserPrincipalName 'zztestuser11@domain.com' -SamAccountName 'testuser11' -FirstName 'zztestuser' -Initials '' -LastName '11' -Password $SecurePassword -ResetPasswordOnNextLogon $false -Database 'DB11'
New-Mailbox -Name 'zztestuser12' -Alias 'zztestuser12' -OrganizationalUnit 'domain.com/Users' -UserPrincipalName 'zztestuser12@domain.com' -SamAccountName 'testuser12' -FirstName 'zztestuser' -Initials '' -LastName '12' -Password $SecurePassword -ResetPasswordOnNextLogon $false -Database 'DB12'
New-Mailbox -Name 'zztestuser13' -Alias 'zztestuser13' -OrganizationalUnit 'domain.com/Users' -UserPrincipalName 'zztestuser13@domain.com' -SamAccountName 'testuser13' -FirstName 'zztestuser' -Initials '' -LastName '13' -Password $SecurePassword -ResetPasswordOnNextLogon $false -Database 'DB13'
New-Mailbox -Name 'zztestuser14' -Alias 'zztestuser14' -OrganizationalUnit 'domain.com/Users' -UserPrincipalName 'zztestuser14@domain.com' -SamAccountName 'testuser14' -FirstName 'zztestuser' -Initials '' -LastName '14' -Password $SecurePassword -ResetPasswordOnNextLogon $false -Database 'DB14'
New-Mailbox -Name 'zztestuser15' -Alias 'zztestuser15' -OrganizationalUnit 'domain.com/Users' -UserPrincipalName 'zztestuser15@domain.com' -SamAccountName 'testuser15' -FirstName 'zztestuser' -Initials '' -LastName '15' -Password $SecurePassword -ResetPasswordOnNextLogon $false -Database 'DB15'
New-Mailbox -Name 'zztestuser16' -Alias 'zztestuser16' -OrganizationalUnit 'domain.com/Users' -UserPrincipalName 'zztestuser16@domain.com' -SamAccountName 'testuser16' -FirstName 'zztestuser' -Initials '' -LastName '16' -Password $SecurePassword -ResetPasswordOnNextLogon $false -Database 'DB16'
New-Mailbox -Name 'zztestuser17' -Alias 'zztestuser17' -OrganizationalUnit 'domain.com/Users' -UserPrincipalName 'zztestuser17@domain.com' -SamAccountName 'testuser17' -FirstName 'zztestuser' -Initials '' -LastName '17' -Password $SecurePassword -ResetPasswordOnNextLogon $false -Database 'DB17'
New-Mailbox -Name 'zztestuser18' -Alias 'zztestuser18' -OrganizationalUnit 'domain.com/Users' -UserPrincipalName 'zztestuser18@domain.com' -SamAccountName 'testuser18' -FirstName 'zztestuser' -Initials '' -LastName '18' -Password $SecurePassword -ResetPasswordOnNextLogon $false -Database 'DB18'
New-Mailbox -Name 'zztestuser19' -Alias 'zztestuser19' -OrganizationalUnit 'domain.com/Users' -UserPrincipalName 'zztestuser19@domain.com' -SamAccountName 'testuser19' -FirstName 'zztestuser' -Initials '' -LastName '19' -Password $SecurePassword -ResetPasswordOnNextLogon $false -Database 'DB19'
New-Mailbox -Name 'zztestuser20' -Alias 'zztestuser20' -OrganizationalUnit 'domain.com/Users' -UserPrincipalName 'zztestuser20@domain.com' -SamAccountName 'testuser20' -FirstName 'zztestuser' -Initials '' -LastName '20' -Password $SecurePassword -ResetPasswordOnNextLogon $false -Database 'DB20'
New-Mailbox -Name 'zztestuser21' -Alias 'zztestuser21' -OrganizationalUnit 'domain.com/Users' -UserPrincipalName 'zztestuser21@domain.com' -SamAccountName 'testuser21' -FirstName 'zztestuser' -Initials '' -LastName '21' -Password $SecurePassword -ResetPasswordOnNextLogon $false -Database 'DB21'
New-Mailbox -Name 'zztestuser22' -Alias 'zztestuser22' -OrganizationalUnit 'domain.com/Users' -UserPrincipalName 'zztestuser22@domain.com' -SamAccountName 'testuser22' -FirstName 'zztestuser' -Initials '' -LastName '22' -Password $SecurePassword -ResetPasswordOnNextLogon $false -Database 'DB22'
New-Mailbox -Name 'zztestuser23' -Alias 'zztestuser23' -OrganizationalUnit 'domain.com/Users' -UserPrincipalName 'zztestuser23@domain.com' -SamAccountName 'testuser23' -FirstName 'zztestuser' -Initials '' -LastName '23' -Password $SecurePassword -ResetPasswordOnNextLogon $false -Database 'DB23'
New-Mailbox -Name 'zztestuser24' -Alias 'zztestuser24' -OrganizationalUnit 'domain.com/Users' -UserPrincipalName 'zztestuser24@domain.com' -SamAccountName 'testuser24' -FirstName 'zztestuser' -Initials '' -LastName '24' -Password $SecurePassword -ResetPasswordOnNextLogon $false -Database 'DB24'
New-Mailbox -Name 'zztestuser25' -Alias 'zztestuser25' -OrganizationalUnit 'domain.com/Users' -UserPrincipalName 'zztestuser25@domain.com' -SamAccountName 'testuser25' -FirstName 'zztestuser' -Initials '' -LastName '25' -Password $SecurePassword -ResetPasswordOnNextLogon $false -Database 'DB25'
New-Mailbox -Name 'zztestuser26' -Alias 'zztestuser26' -OrganizationalUnit 'domain.com/Users' -UserPrincipalName 'zztestuser26@domain.com' -SamAccountName 'testuser26' -FirstName 'zztestuser' -Initials '' -LastName '26' -Password $SecurePassword -ResetPasswordOnNextLogon $false -Database 'DB26'
New-Mailbox -Name 'zztestuser27' -Alias 'zztestuser27' -OrganizationalUnit 'domain.com/Users' -UserPrincipalName 'zztestuser27@domain.com' -SamAccountName 'testuser27' -FirstName 'zztestuser' -Initials '' -LastName '27' -Password $SecurePassword -ResetPasswordOnNextLogon $false -Database 'DB27'
New-Mailbox -Name 'zztestuser28' -Alias 'zztestuser28' -OrganizationalUnit 'domain.com/Users' -UserPrincipalName 'zztestuser28@domain.com' -SamAccountName 'testuser28' -FirstName 'zztestuser' -Initials '' -LastName '28' -Password $SecurePassword -ResetPasswordOnNextLogon $false -Database 'DB28'
New-Mailbox -Name 'zztestuser29' -Alias 'zztestuser29' -OrganizationalUnit 'domain.com/Users' -UserPrincipalName 'zztestuser29@domain.com' -SamAccountName 'testuser29' -FirstName 'zztestuser' -Initials '' -LastName '29' -Password $SecurePassword -ResetPasswordOnNextLogon $false -Database 'DB29'
New-Mailbox -Name 'zztestuser30' -Alias 'zztestuser30' -OrganizationalUnit 'domain.com/Users' -UserPrincipalName 'zztestuser30@domain.com' -SamAccountName 'testuser30' -FirstName 'zztestuser' -Initials '' -LastName '30' -Password $SecurePassword -ResetPasswordOnNextLogon $false -Database 'DB30'


Exchange and Adobe iFilters

*N.B. this is an old article and may no longer be relevant*

(Note: This article refers to Exchange 2007 and Exchange 2010)

The full set of IFilters installed with Exchange out of the box include Microsoft Office documents (e.g. doc/docx, xls/xlsx, ppt/pptx), Email message formats (e.g. msg, eml), HTML and text formats. These are used on Hub Transport servers (when filtering attachments using Transport Rules) and Mailbox servers (for indexing attachments).
Third Party iFilters can be added and as per http://blogs.technet.com/b/exchange/archive/2009/05/11/3407435.aspx, Adobe PDF is one of the most common.
Adobe provide the iFilters as a downloadable, installable package: http://www.adobe.com/support/downloads/detail.jsp?ftpID=4025
which also needs registering. The following article summarizes how to do that: http:// marksmith.netrends.com/Lists/Posts/Post.aspx?List=d0ef1a62%2D8e97%2D484a%2D9053%2D7acda05534cb&ID=93&Web=2dee96c1%2D5fed%2D439e%2Db530%2D37626608d03e. However, it doesn’t quite go far enough. There are some steps to do afterwards and two of them involve modifying registry permissions.

I decided that these were two steps that could be automated by Powershell, so set about doing that. The method used is straight off of Technet; that is, using get-acl to ingest the current permissions and then set-acl to add to them. The code for setting Read access for the Network Service on the two relevant keys for the Adobe iFilters is as follows:

$rule = New-Object System.Security.AccessControl.RegistryAccessRule ("NT AUTHORITY\NETWORK SERVICE","ReadKey","Allow")
$acl1 = Get-Acl "HKLM:\SOFTWARE\Microsoft\ExchangeServer\V14\MSSearch\CLSID\{E8978DA6-047F-4E3D-9C78-CDBE46041603}"
$acl1.SetAccessRule($rule)
$acl1 |Set-Acl -Path "HKLM:\SOFTWARE\Microsoft\ExchangeServer\V14\MSSearch\CLSID\{E8978DA6-047F-4E3D-9C78-CDBE46041603}"
$acl2 = Get-Acl "HKLM:\SOFTWARE\Microsoft\ExchangeServer\v14\MSSearch\Filters\.pdf"
$acl2.SetAccessRule($rule)
$acl2 |Set-Acl -Path "HKLM:\SOFTWARE\Microsoft\ExchangeServer\v14\MSSearch\Filters\.pdf"


You can save the above to a script and run it after registering the Adobe iFilters or you can incorporate it into one script (enhancing the one by Mark E. Smith) so that the full script looks like this:



# save as Register-Adobe-PDF-filter.ps1
#
# Download installation from: http://www.adobe.com/support/downloads/detail.jsp?ftpID=4025

# Refer to: http://blogs.technet.com/b/exchange/archive/2009/05/11/3407435.aspx

# Adobe iFilter Directory Path
$iFilterDirName = "C:\Program Files\Adobe\Adobe PDF IFilter 9 for 64-bit platforms\bin"

# Get the original path environment variable
$original = (Get-ItemProperty "HKLM:SYSTEM\CurrentControlSet\Control\Session Manager\Environment" Path).Path
# Add the ifilter path
Set-ItemProperty "HKLM:SYSTEM\CurrentControlSet\Control\Session Manager\Environment" Path -value ( $original + ";" + $iFilterDirName )

$CLSIDKey = "HKLM:\SOFTWARE\Microsoft\ExchangeServer\V14\MSSearch\CLSID"
$FiltersKey = "HKLM:\SOFTWARE\Microsoft\ExchangeServer\v14\MSSearch\Filters"

# Filter DLL Locations
$pdfFilterLocation = “PDFFilter.dll"

# Filter GUIDs
$PDFGuid ="{E8978DA6-047F-4E3D-9C78-CDBE46041603}"

# Create CLSIDs
Write-Host "Creating CLSIDs..."

New-Item -Path $CLSIDKey -Name $PDFGuid -Value $pdfFilterLocation -Type String

# Set Threading model
Write-Host "Setting threading model..."

New-ItemProperty -Path "$CLSIDKey\$PDFGuid" -Name "ThreadingModel" -Value "Both" -Type String

# Set Flags
Write-Host "Setting Flags..."
New-ItemProperty -Path "$CLSIDKey\$PDFGuid" -Name "Flags" -Value "1" -Type Dword

# Create Filter Entries
Write-Host "Creating Filter Entries..."

# These are the entries for commonly exchange formats
New-Item -Path $FiltersKey -Name ".pdf" -Value $PDFGuid -Type String

$rule = New-Object System.Security.AccessControl.RegistryAccessRule ("NT AUTHORITY\NETWORK SERVICE","ReadKey","Allow")
$acl1 = Get-Acl "HKLM:\SOFTWARE\Microsoft\ExchangeServer\V14\MSSearch\CLSID\{E8978DA6-047F-4E3D-9C78-CDBE46041603}"
$acl1.SetAccessRule($rule)
$acl1 |Set-Acl -Path "HKLM:\SOFTWARE\Microsoft\ExchangeServer\V14\MSSearch\CLSID\{E8978DA6-047F-4E3D-9C78-CDBE46041603}"
$acl2 = Get-Acl "HKLM:\SOFTWARE\Microsoft\ExchangeServer\v14\MSSearch\Filters\.pdf"
$acl2.SetAccessRule($rule)
$acl2 |Set-Acl -Path "HKLM:\SOFTWARE\Microsoft\ExchangeServer\v14\MSSearch\Filters\.pdf"

Write-Host -foregroundcolor Green "The NETWORK SERVICE has been granted read access to the following registry keys:`n$CLSIDKey\$PDFGuid`n$FiltersKey\.pdf"
Write-Host " "
Write-Host -foregroundcolor Yellow "Next, reboot the Exchange Server
- after which you need to rebuild the search indexes using the precanned script:"
Write-Host " "
Write-Host -foregroundcolor White "cd $exscripts; .\ResetSearchIndex.ps1 –Force –All"
Write-Host " "
Write-Host -foregroundcolor Green "Then wait for the indexes to be rebuilt before initiating a search.
Repeat this process on each Mailbox Server and Hub Transport in the organization"
Write-Host " "
Write-Host -foregroundcolor Yellow "Note: The permissions on the keys above for NETWORK SERVICE are required on the Hub Transport role (or multi-roled server that hosts the Hub role) so that transport rules can do PDF attachment filtering"




Windows Disk Timeouts (Ex2010)

*N.B. this is an old article and may no longer be relevant*

As per the following article, MS make recommendations regarding storage for the Exchange 2010 MBX role:

http://technet.microsoft.com/en-us/library/ee832792(v=exchg.141).aspx

This post pertains specifically to the recommendation for the disk timeout value. By default this is set at 60 seconds. For DAS or SAN this should be modified to 20 seconds. I have created a one liner to do this:

Set-ItemProperty -path HKLM:\SYSTEM\CurrentControlSet\services\Disk -name TimeOutValue -value 20

More info on the topic can be found here:
http://blogs.msdn.com/b/san/archive/2011/09/01/the-windows-disk-timeout-value-understanding-why-this-should-be-set-to-a-small-value.aspx

Note that the information is omitted from the Exchange 2013 version of the Technet article:

http://technet.microsoft.com/en-us/library/ee832792.aspx

Don't ask me why. I can't see that it wouldn't still be relevant. If you're looking at this in reference to Exchange 2013, read the blog and make up your own mind. Personally, I would still set it to 20 seconds in the absence of specific advice.

Wow. Is it only five to four? I've got another five minutes of work. Time for a coffee...