Writing Powershell scripts that target Exchange 2007 and 2010
If you’re planning a migration to Exchange 2010 that won’t be completed overnight, you may want to be able to run Exchange Powershell scripts that execute both Exchange 2007 and 2010 cmdlets from the same script. There’s a few reasons for doing this, including:
- If you use logic to determine where to place new user mailboxes, and some mailboxes will be on 2007 and some on 2010.
- If you create new mailboxes on Exchange 2007 and then add the new mailbox to a Exchange 2010 distribution group (for example, if you use moderated distribution groups).
- If you’re using Outlook Live (Live@EDU hosted Exchange 2010) and create MailUsers on-premise and Mailboxes in the hosted environment.
- You are using the Transporter suite to migrate mail and need to create mailboxes on a temporary Exchange 2007 server, migrate mail, and then move mailboxes to Exchange 2010.
OK – so my examples are mostly about provisioning and these are real-life examples of where I’ve used this method, but I’m sure you can think of other examples where it might be useful to you. So – what do you need?
- Exchange 2007 SP2 management tools on any OS that supports them.
- Powershell 2.0
- Remote Powershell enabled on the account you run the script as (using Set-User username –RemotePowerShellEnabled:$true)
You can use this on Windows Server 2003 R2, x86; no Exchange 2010 management tools are required. Enough of what you need – here’s what you need to put in your Powershell scripts to do Exchange 2007/2010:
# Add Exchange 2007. If you'll always run from the Exchange Management Shell, you don't need the next line.Add-PSSnapin Microsoft.Exchange.Management.PowerShell.Admin# Exchange 2007 Commands Go Here - i.e.Get-MailboxDatabase# Unload Exchange 2007Remove-PSSnapin Microsoft.Exchange.Management.PowerShell.Admin# Create Remote Powershell session with Exchange 2010 - edit the server name in ConnetionUri$Session = New-PSSession -ConfigurationName Microsoft.Exchange -ConnectionUri http://exchange.contoso.com/powershell/ -Authentication KerberosImport-PSSession $Session# Exchange 2010 Commands Go Here - i.e.Get-MailboxDatabase# Unload Exchange 2010Remove-PSSession $Session
If you’re looking to connect to Outlook Live instead of Exchange 2010, simply replace the line beginning “$Session =” with a couple of lines similar to this:
$LiveCred = New-Object System.Management.Automation.PSCredential "yourliveadmin@contoso.edu", (ConvertTo-SecureString "password" -AsPlainText -Force)$Session = New-PSSession -ConfigurationName Microsoft.Exchange -ConnectionUri https://ps.outlook.com/powershell/ -Credential $LiveCred -Authentication Basic -AllowRedirection -WarningAction SilentlyContinue
Hope this helps!
Steve
Scripted Shared Mailbox Creation on Exchange 2007/2010
I thought I’d share one of the scripts we use for automating creation of Shared Mailboxes within our organisation. One of the more laborious parts of creating shared mailboxes after creation of the actual Mailbox, is setting the manager, department, and granting a (possibly long) list of users permissions and send-as rights.
This script is a simple Powershell script that takes some of the pain out of the process. The assumption is that you want to achieve the following:
- Create a shared mailbox with a common alias, email address and username, checking input values before attempting to create the mailbox.
- You would like to specify the Department at creation and use the Department AD attribute to generate Address Lists
- You would like to attach a user as Manager for the Shared Mailbox so it is clear who manages it
You can use the script with Parameters – e.g:
.\New-SharedMailbox.ps1 -Department "Human Resources" -Alias hr_test -DisplayName "HR Test" -Manager managerusername -Usernames "username1,username2"
–Department is the text to use for the department attribute
–Alias is the Email Alias & Username
–DisplayName is the friendly textual name shown to users and recipients
–Manager is the username, UPN or email address of the Manager (who will have full access + send as rights along with being set as Manager)
–Usernames is a comma separated list of usernames of people who should also have full access and send-as rights.
Or - if that isn’t your thing, then you can just run the script without any options, and it will prompt you as you go along for the parameters. If you are using the Department attribute for Address List generation, you can hit enter when prompted for the department to get a list of in-use departments. As you go along values will be checked, to ensure the Alias and Display Name aren’t in use by Mailboxes or Mail Users and that the Manager and Usernames are attached to valid Mailboxes.
Before you get started with script it does need a little setup.
The setup is fairly straightforward, though. Open the script in a text editor, and change the values for $DomainController, $OU, $UPNDomain and $MailboxDatabase to values appropriate for your organisation. It goes without saying you should test this out on something not connected to your production environment. I won’t take any responsibility for any damage you do with this!
I’ve obviously taken some stuff out that is specific to our organisation (for example, we have a switch statement to determine the mailbox database and exchange server; and also generate Unix information) and if this almost does what you want let me know and I’ll be happy to help you customise it.
Download New-SharedMailbox.ps1
Enabling the Exchange 2010 ECP Performance Console
If you’ve been testing or even running Exchange 2010 in production, you will most certainly be aware of the Exchange Control Panel – which is now not only the user’s Options panel but provides access to a number of Administrative tools, such as basic user management and reporting/mailbox searches.
However one feature contained in the ECP but isn’t visible immediately is the ECP Performance Console.
The ECP Performance Console is ECP-specific in that it provides a whole wealth of information about how your Exchange Control Panel is performing – from how long client requests are taking, RPC latency down to what’s happening on the Powershell side. Although it is totally ECP specific the information can help you diagnose areas in which your client access server isn’t performing as it should and verifying improvements are working as they should.
The fields available in the ECP Performance console are as follows:
Request URL
Client Request Time (ms)
Server Request Time (ms)
RBAC Session
RBAC Session Latency (ms)
RPC Requests
RPC Latency (ms)
LDAP Requests
LDAP Latency (ms)
Serialization
Serialization Time (ms)
Runspace
Runspace Latency (ms)
Runspace Activations
Runspace Active Time (ms)
Windows PowerShell Invoke Count
Windows PowerShell Invoke Time (ms)
Cmdlets Instantiated
Cmdlet Time (ms)
Cmdlets Invoked
BeginProcessing Time (ms)
ProcessRecord Count
Process Record Time (ms)
EndProcessing Time (ms)
Authentication (ms)
Authorization (ms)
Resolve Cache (ms)
Map Request (ms)
Acquire State (ms)
Execute Handler (ms)
Release State (ms)
Update Cache (ms)
Log Request (ms)
Client Network Time (ms)
UI Response (ms)
To enable the ECP Performance Console, edit the ECP root directory’s web.config file on each Client Access server you wish to use this on. This is located at the following location:
C:\Program Files\Microsoft\Exchange Server\V14\ClientAccess\ecp\web.config
Look int he file for the following section:
<!-- Set ShowPerformanceConsole to "true" to show ECP's Perf Console: --><add key="ShowPerformanceConsole" value="false" />
Change the value for ShowPerformanceConsole to false to true as described in the preceding comment, and save the file.
Once you’ve made the change, run the customary iisreset /noforce to reset IIS then as normal login at your ECP URL (i.e. https://mail.contoso.com/ecp) and after login, click the drop-down to the right of the help icon:
You should see Performance Console now listed. Click it and voila – it should appear.
If you want to export the data - simply press the Copy button in the top left corner. The data can then be pasted into Excel.
Hope you find this useful, at some point!
Steve
Exchange 2010 MCITP: EMA now available – my comments
As of today, exam 70-663 is now available to take at your local Prometic test centre. After passing 70-662, TS: Exchange 2010, Configuring this is the only exam you need to pass to become MCITP on Exchange 2010.
As someone lucky enough to take and pass the beta exam (they cancelled a LOT of places - thankfully I booked mine for Dec 1st) I can say it's certainly no harder than the Exchange 2007 MCITP exams. If you have already passed those, although there is not a specific upgrade path you won't be too dissapointed as much of the same ground is covered apart from new features, like DAG, RBAC etc.
One area where I am disappointed with the MCITP in general is that they aren't hard enough. I'm not likely to win any friends by saying that, but personally I want to feel really satified after passing the exam. With exams like the VCP getting harder I think Microsoft should follow this example and make the MCITP something that is hard to achieve; there simply is too much of a gap between MCITP and MCM/MCA and too little of a difference in skill level between MCTS and MCITP.
Solving iPhone and Exchange 2010/2007 coexistence issues
During my testing of our Exchange 2010 implementation I came across a rather annoying issue - iPhones users with Exchange 2007 mailboxes no longer can connect after moving the client access across to 2010.
So - what is supposed to happen? Well - as iPhone is supposed to implement EAS protocol version 12.1 (i.e. it supports AutoDiscover), it should be redirected to the legacy Exchange 2007 Client Access array. Problem is, it doesn't work.
Of course not all ActiveSync clients support AutoDiscover and those that implement EAS protocol 12.0 or lower are automatically proxied by the Exchange 2010 Client Access array back to Exchange 2007 client access servers.
This is all explained in more detail (including an acknoledgement not all clients implement EAS protocol 12.1 correctly!) over at the Microsoft Exchange Team blog in their article, Upgrading Exchange ActiveSync to Exchange 2010.
Whilst looking for solutions, I've unfortunately only came across verification this is a known issue, with the solution to simply wait for Apple to fix the iPhone. However I have a deadline to meet and getting IT staff to visit hundreds of iPhone users to change EAS settings isn't an option, it's not an option to move all those mailboxes at the same time, and we can't wait for a fix from Apple.
The most simple solution, as it stands - is to force all ActiveSync clients to be proxied. As noted in the MS Exchange Team blog article above, all non-internet facing site mailbox ActiveSync access is proxied anyway, so it will work. And thankfully, the proxying isn't based on AD sites. It's simply based on the ExternalURL on the ActiveSync virtual directory - if it's set to $null on the Client Access servers in the site of the user's Mailbox it will proxy instead of redirect.
If you want to do this via the Exchange Management Shell - it's simple - do this for each Internet facing client access server during the switchover:
Get-ActiveSyncVirtualDirectory -Server E2007CA | Set-ActiveSyncVirtualDirectory -ExternalURL:$null
The implication of this is that there will be extra overhead associated with proxying Exchange 2007 ActiveSync users, so this would need to be factored into your plans should you implement my solution.
Setup Multiple Exchange Accounts on your iPhone
If like me you've got a work Exchange account, and another Exchange account somewhere else (or even a Gmail account which can use the same protocol) and sync these to your iPhone you'll share my frustration in that Apple only allow you to sync a single account. Thankfully those days are numbered as now it's possible to connect more than one account.
You'll have to Jailbreak you phone if you want to do this, but it's now pretty easy to add a second Exchange push email account to your iPhone.
First things first, Jailbreaking can be achieved fairly easily and safely using something like Blackra1n. Once Jailbroken you need Cydia (an Apt repositary/gui for the iPhone) installed and using Cydia, search for AddExchange and install.
After you've installed AddExchange, fire it up and press the button to add your second account. A second account should appear with some default settings ready for you to change to your own.
Now you're up and running with the second account you can safely remove (via Cydia) AddExchange.
Another option is an app called MultiExchange which claims to do this in a much cleaner way - however it has to be purchased from the Cydia store for $0.99. As I've been happy with AddExchange I've not tried this but from what I've read it doesn't suffer from a two account limit.
More details over at AppAdvice
Exchange – Bulk-add forwarding addresses
There's not many circumstances where you'd want to set forwarding on lots of mailboxes at once - but if you're in that situation (perhaps you're moving mailboxes to a Cloud mail provider) it's useful to know that it's fairly straightforward and can be accomplished with a little PowerShell.
In the example below, we're assuming that your on-premise Exchange 2007/2010 domain is contoso.com and all your mailboxes are in the Staff OU.
The Cloud provider you're moving your mail to will eventually take over the MX record for your domain, but will also accept mail to each user's Username@cloud.contoso.com. We'll keep mail contacts used for the forwarding in the OU CloudContacts.
To accomplish this, we quite simply need to get the mailboxes in the specific OU, create a mail contact for each one (with the external email address they will use on the cloud provider's domain) and then set the forwarding address on the mailbox:
# Loop though the object returned by Get-Mailbox with each element represented by $mailbox
foreach ($mailbox in (Get-MailBox -ResultSize Unlimited -OrganizationalUnit contoso.com/Staff)
{
# Create the forwarding address string $ForwardingAddress= $mailbox.SamAccountName + "@cloud.contoso.com"
# Check there isn't a contact, then add one
If (!(Get-MailContact $ForwardingAddress -ErrorAction SilentlyContinue))
{
New-MailContact $ForwardingAddress-ExternalEmailAddress $ForwardingAddress- OrganizationalUnit contoso.com/CloudContacts }
# Set the forwarding address Set-Mailbox $mailbox -ForwardingAddress $ForwardingAddress
}
Of course, that's a fairly simple example. What if the email addresses at the cloud provider don't match the Windows Logon ID or anything else that is an attribute of the Mailbox? Well the simple solution is to use something like a CSV file containing a mapping between an attribute on each Mailbox and the external email address for that user:
SamAccountName,ForwardingAddress jamesw,jimbo@cloud.contoso.com philipg,phil@cloud.contoso.com
In this example, we'll save that file as input.csv and use that as are input to the foreach loop. Again CloudContacts OU will contain our new mail contact objects:
# Loop through the object returned by Import-Csv with each element represented by $person
foreach ($person in (Import-Csv .\input.csv))
{
# Check the Mailbox for the person exists
If ((Get-Mailbox $person.SamAccountName))
{
# Check the mail contact doesn't exist and if not add it
If (!(Get-MailContact $person.ForwardingAddress))
{
New-MailContact $person.ForwardingAddress -OrganizationalUnit contoso.com/CloudContacts }
# Set the Forwarding Address on the Mailbox Set-Mailbox $person.SamAccountName -ForwardingAddress $person.ForwardingAddress }
}
Word of caution - it's worth (as always) running these commands in your test environment first - and of course consider appending -WhatIf to the New-MailContact and Set-Mailbox commands to check they'll do what you want in your production environment.
Hope this helps,
Steve