Click here to monitor SSC
Av rating:
Total votes: 7
Total comments: 2


James Allison
Importing PSTs into Exchange 2010, The Easy Way
27 August 2010

PST Importing has always been a bit messy. With Exchange 2010’s Personal Archiving feature, it’s become more pertinent, yet still comes with pit-falls, gotchas, and inexplicable errors. James Allison has done some research, and presents an easy way to smoothly tackle the whole problem.

The process of importing multiple users’ PST files into Exchange 2010 is not as simple as perhaps you might expect, and certainly not as simple is probably should be, given how common this particular task is. To try and spread the knowledge about wrestle with this task, this article is aimed at SysAdmins wanting to migrate their users’ personal PST files into their (the users’) main exchange mailboxes. Even better, to make this as easy as possible, I’ll walk through the entire process involved, as well as creating the appropriate PowerShell scripts to semi-automate the process. Finally, to keep everything clear, I’ve split the material into three parts:

  • Importing a single PST File into Exchange 2010 RTM and SP1
  • Finding PST files on your network, and then...
  • ...Importing these into Exchange (i.e. not one-by-one!)

While my solution is not necessarily Best Practice, it’s one of the best solutions I could research, and so it’s likely that many SysAdmins will come up with something similar. What you should bear in mind is that these three components I’ve described are not actually the relative “Easiest Way” of handling this importing process, as they require a non-trivial amount of tweaking, and come with their fair share of pitfalls and gotchas. The Really Easy Way is mentioned later in the article, and is, as far as I’ve found, the most painless way of handing PST imports with Exchange 2010.

Introduction:

Just so we’re all on the same page, this guide has focused on using Windows Management Instrumentation (WMI) to identify files on remote user’s machines, and then import these files into their mailboxes. There are of course several options:

  1. You could ask users to manually drag mails across from within outlook.
  2. You could have group policy enforce a logon script that copies user PST files to a shared network drive and then removes said files from their system (or prevents outlook from mounting it).
    A script running on a server can then poll for new PSTs in this folder and automatically add them with the –IsArchive parameter so that the contents of the users’ local archive PSTs are available in their archive mailboxes (almost) immediately. The advantages of this approach are that you don’t need to worry about locked files (as the files can be copied before outlook has had a chance to start/lock them), or enabling WMI firewall access on client machines. However, it does still require that the user log off and on...
  3. The third (and, I think, easiest) approach is to use WMI to remotely search for files. This can generate a list of PSTs on all machines, and highlight the machines which couldn’t be searched (and which would require further attention). However, it’s highly likely that Outlook will be running on your users’ machines, making this process trickier. Naturally, WMI can be used to terminate the Outlook process remotely, but this is not ideal, and there are other ways around this problem. The advantages of this approach is that it does not require individual users to login and out (useful if a user is on holiday, for instance) – merely that the machine is on (which could be managed via Wake On LAN).

As stated, this guide focuses on the WMI-based solution and just covers the basics – more advanced scripts could be created to deal with a greater variety of error cases and configurations (e.g. shutting down outlook, making separate lists of machines to try again, detailing which PSTs had passwords and could not be imported).

How to import a PST file into Exchange.

Importing a PST file into Exchange 2010 requires the use of the Exchange Management Shell (EMS), although (somewhat confusingly) this functionality was originally included in the Exchange Management Console in the Beta release of Exchange 2010.

A PowerShell cmdlet in the EMS is used to perform the action, and the use of this cmdlet requires that the current user has Import Export roles enabled on their profile. In order to run the import and export cmdlets, Exchange 2010 RTM also requires that Outlook 2010 x64 is installed on the machine being used to run said cmdlets, although this is no longer a requirement of Exchange 2010 SP1.

So, to import a single PST file into an exchange 2010 mailbox:

  1. Install Outlook 2010 x64 on the Exchange server. Bear in mind that, by default, on a machine with no pre-existing Office installation, the DVD’s autorun setup will try to install the x86 applications. Be sure to manually run the installer rom the x64 directory to install the x64 version of Outlook, although this step is not necessary for Exchange 2010 SP1, as this now (re)includes a MAPI provider.
  2. Enable Import Permissions for a security group which your user belongs to - In this case, ‘Mailbox Support’ - with the following command:

    New-ManagementRoleAssignment -Name "Import Export Mailbox Admins" `

                                 -SecurityGroup "Mailbox Support" `

                                 -Role "Mailbox Import Export"



  3. Import the desired PST file into the appropriate user’s mailbox with the following command:

    Import-Mailbox -PSTFolderPath pstfilepath -Identity exchangealias

Exchange 2010 SP1 differs a little, in that you don’t need to install Outlook 2010 x64, and rather than the synchronous Import-Mailbox cmdlet, the asynchronous New-MailBoxImportRequest can be used, which takes the form of:

New-MailboxImportRequest -FilePath pstfilepath -Mailbox mailbox

The status of current requests can be viewed with the Get-MailboxImportRequest cmdlet, and completed requests can be cleared (or pending/In-progress requests cancelled) with the Remove-MailboxImportRequest cmdlet. One of the advantages of this new cmdlet, other than it being asynchronous, is that you can specify an additional –IsArchive parameter, which will import the PST directly into the users archive mailbox.

I did experience a few problems using these cmdlets during the brief time I spent doing research for this guide. The Exchange 2010 RTM Import-Mailbox on one system simply refused to play nicely, and kept throwing the following error:

Error:
Error was found for <Mailbox Name> because: Error occurred in the step: Approving object. An unknown error
has occurred., error code: -2147221219
    + CategoryInfo          : InvalidOperation: (0:Int32) [Import-Mailbox], RecipientTaskException
    + FullyQualifiedErrorId : CFFD629B,Microsoft.Exchange.Management.RecipientTasks.ImportMailbox

Not a lot of help in itself, although a little Googling and experimentation revealed four main potential causes for this error:

  1. The appropriate role permissions has not been added to the users security profile.
  2. The version of MAPI being used has somehow got confused, which could be fixed by running the fixmapi command from the command prompt.
  3. The PST file is password protected.
  4. There is a bug in exchange.

In my case, I’d unfortunately hit the forth problem, and the workaround proved to be pretty horrific - it may simply be worth waiting for a fix from Microsoft. To complete my task, I had to temporarily add a new domain controller to my network to host a new Exchange 2010 server. I then moved the target mailboxes (i.e. the ones for which I had PSTs to import) across to this new server, performed the import, and then moved the mailboxes back to their original Exchange server and removed the temporary server from the network (Like I said, pretty horrific).

Upgrading the system to 2010 SP1 and using the New-MailBoxImportRequest cmdlet on the same system yielded the following error:

Couldn't connect to the target mailbox.

    + CategoryInfo          : NotSpecified: (0:Int32) [New-MailboxImportRequest], RemoteTransientException

    + FullyQualifiedErrorId : 1B0DDEBA,Microsoft.Exchange.Management.RecipientTasks.NewMailboxImportRequest

Again, this appears to be a known issue, and apparently one which is scheduled to be fixed before the final release of SP1.

Finding PST files on the network

So, we’ve seen the process for importing a local PST file into Exchange server, however, in reality, it’s likely that these PST files are scattered liberally around your network on the hard-drives of your users’ machines as a result of Outlook’s new personal archiving functionality. Ideally, so that this mass-import process is transparent to your users, you’d like some way of finding all of these PST files, pairing them up with their users, and then simply importing them into the appropriate mailbox.

There are a few steps required to set up something like that. First, we can query Active Directory for a list of all the machines attached to your domain. We can then use WMI to search each of these machines for PST files, and the file paths for these PSTs should hopefully give us a clue as to which user they belong to (by default, they will be created in a directory path containing the username.) We can also grab the file owner file attribute, which should correlate with the details in the file path.

Naturally, this technique requires that all of the machines in your network are switched on and accessible by WMI, although a list of the machines which could not be queried can be provided as an output.

Notes about WMI

By default, WMI is blocked by the windows firewall in Windows 7 and 2008 R2, so you’ll probably need to open up the ports on all of your users’ machines. This can be done with the netsh command, or through a change to group policy.

You might quite rightly be asking yourself “What are the implications of this?” WMI is a powerful beast which allows remote access to many aspects of a user’s machine. As such, it could be considered a significant security vulnerability. In addition, it’s typically accessed though port 135, which not only permits access to WMI, but also to any other DCOM components which may be installed on a machine, thus opening the way for exploitation by Trojans and the like. Needless to say, the ports are blocked by default for a reason, so carefully consider all of the implications when opening them.

WMI will also not help you if the machines you wish to tinker with are subject to NAT (Network Address Translation) - You’ll simply be unable to reach these machines.

Nevertheless, let’s assume a situation without any NAT, and where the security risks have been minimised. The following script generates a txt file (the filename defined on line 2) of all the computers on your domain to be searched. This file can then be manually edited with notepad to remove any machines you don’t wish to search:

$strCategory = "computer"

$strOutput = "c:\computernames.txt"

$objDomain = New-Object System.DirectoryServices.DirectoryEntry

 

$objSearcher = New-Object System.DirectoryServices.DirectorySearcher

$objSearcher.SearchRoot = $objDomain

$objSearcher.Filter = ("(objectCategory=$strCategory)")

 

$colProplist = "name"

foreach ($i in $colPropList){$objSearcher.PropertiesToLoad.Add($i)}

 

$colResults = $objSearcher.FindAll()

[bool]$firstOutput = $true

foreach ($objResult in $colResults)

{

      $objComputer = $objResult.Properties;

      if($firstOutput)

      {

            Write-output $objComputer.name | Out-File -filepath $strOutput

            $firstOutput = $false;

      }

      else

      {

            Write-output $objComputer.name | Out-File -filepath $strOutput `

                                                       -append

      }

}

Listing 1 - A PowerShell script to generate a list of all machines on your domain which are to be searched for PST files.

The next script will generate a CSV (Comma separated values) file detailing the network paths of the PST files you need to import:

$strComputers = Get-Content -Path "c:\computernames.txt"

[bool]$firstOutput = $true

foreach($strComputer in $strComputers)

{

   $colFiles = Get-Wmiobject -namespace "root\CIMV2" `

                             -computername $strComputer `

                             -Query "Select * from CIM_DataFile `

                                              Where Extension = 'pst'"

   foreach ($objFile in $colFiles)

   {

      if($objFile.FileName -ne $null)

      {

         $filepath = $objFile.Drive + $objFile.Path + $objFile.FileName + "." `

                    + $objFile.Extension;

         $query = "ASSOCIATORS OF {Win32_LogicalFileSecuritySetting='" `

                 + $filepath `

                 + "'} WHERE AssocClass=Win32_LogicalFileOwner ResultRole=Owner"

          $colOwners = Get-Wmiobject -namespace "root\CIMV2" `

                                     -computername $strComputer `

                                     -Query $query

          $objOwner = $ colOwners[0]

          $user = $objOwner.ReferencedDomainName + "\" + $objOwner.AccountName

          $output = $strComputer + "," + $filepath + "," + $user

          if($firstOutput)

          {

              Write-output $output | Out-File -filepath c:\pstdetails.csv

             $firstOutput = $false

          }

          else

          {

              Write-output $output | Out-File -filepath c:\pstdetails.csv -append

          }

       }         

   }

}

Listing 2 – A PowerShell script to find and list network paths for PST files to be imported.

This script will take as input a text file containing a list of machine names, which is, conveniently, the output of the first script. It will then generate a .csv file of all the PST files found on those machines, and the owners associated with them. So far, so painless.

Importing the remote PSTs into Exchange

Now that we’ve seen how to gain a list of machines and their respective PST files, we now need to import these files into Exchange. The following script does just that:

# Read in pst file locations and users

$strPSTFiles = Get-Content -Path "c:\pstdetails.csv"

foreach($strPSTFile in $strPSTFiles)

{

      $strMachine = $strPSTFile.Split(',')[0]

      $strPath = $strPSTFile.Split(',')[1]

      $strOwner = $strPSTFile.Split(',')[2]

     

      # Get network path for pst file

      $source = "\\" + $strMachine + "\" + $strPath.Replace(':','$')

 

      # import pst to mail box.

      Import-Mailbox -PSTFolderPath $source -Identity $strOwner

      New-MailboxImportRequest -FilePath $source -Mailbox $strOwner

}

Listing 3 – PowerShell to import a list of PST files into Exchange from their respective machines.

The yellow highlighted text shows the Exchange 2010 RTM Cmdlet, and the red shops the Exchange 2010 SP1 (delete as appropriate).

The Exchange 2010 SP1 version of the script will execute in far less time than the original RTM version due to the asynchronous nature of the ImportRequest cmdlet. These requests are processed in the background and can be monitored with the Get-MailboxImportRequest cmdlet to observe their status. Once these have completed, as mentioned earlier, it’s necessary to actively clear the requests with the Remove-MailboxImportRequest cmdlet. As easy as this all sounds, there are quite a few potential pitfalls here:

  • The users’ machines must be on,
  • File sharing must be on to allow for the file to be transferred,
  • Outlook must not be running on the remote users’ machines – If outlook is running and has the PST file attached, then the file will be locked and unavailable for importing,
  • Passwords are not supported – The PowerShell cmdlet used by exchange to import PST files simply doesn’t handle passwords.
  • There’s a limit on concurrent requests - With the SP1 asynchronous requests, no more than 10 concurrent requests can be handled per mailbox without manually specifying a unique name for each request (this makes the script a little more complicated, but is not a showstopper, particularly given that most users will only have a single errant PST file to be imported.)

That being said, there are various things you could to augment this script; some suggestions include:

  • Having WMI shut down Outlook on remote users’ machines before attempting import.
  • Generating a further output file detailing a list of all the PSTs which failed to import, with reasons why. It would be useful to know if these files were password protected, or the machine hosting them was shut down or had disconnected since they were identified.
  • In the SP1 case, you could automate the polling of the requests statuses, and the removal of those which have completed.

Summary

So, although it’s possible to search for an import your users’ PST files into Exchange from across the network, it’s not an easy or particularly well-documented process. Frustratingly, there are also elements of the process which are directly hampered by errors and glitches.

Although none of these problems are show-stoppers, they’ll raise your blood pressure if you don’t know about them! Hopefully this guide will set you on the right track and steer you around all but the most well-concealed pitfalls.

The Really Easy Way

As I mentioned at the start, although I’ve broken down the whole process into easy-to-follow steps and pointed out where you’ll need to pay extra attention, this is not, in fact, the easiest way of handling the PST Import process. If you’d rather negate the whole problem in one fell swoop, then there are 3rd party tools which will handle the whole import process for you in a quickly and smoothly, and which will allow you to manage every aspect the import at your convenience.

Resources:

Whilst I was investigating the background facts for this article, I found the following resources on the internet to be of interest:

At first I was Googling for ‘Importing PST files into Exchange’, the following pages on Experts Exchange and HowExchangeWorks.com proved to be an interesting read.

However, as stated in part 1 of this guide, one of the systems I was testing these processes on kept throwing errors when I was trying to execute the import-mailbox cmdlet. This page proved very helpful in identifying the issue I’d hit and suggesting a workaround.

I was then faced with the problem of actually locating the PST files on the network; I found a handy page on the MSExchangeTips blog, detailing how to query WMI for network.

Finally, as I was pretty new to Powershell – the following pages all proved quite useful in getting me up to speed:



This article has been viewed 14214 times.
James Allison

Author profile: James Allison

James Allison is a software developer at Red-Gate Software, currently tasked with the development of tools to ease the workload of system administrators using Microsoft Exchange. He holds a MEng. degree in Computer Systems and Software Engineering, and has previous experience in the (fairly disjointed) fields of ‘Geographical Information Systems’, ‘Super-Resolution Video Up scaling’ and ‘Collision and Physics Simulation’.

Search for other articles by James Allison

Rate this article:   Avg rating: from a total of 7 votes.


Poor

OK

Good

Great

Must read
 
Have Your Say
Do you have an opinion on this article? Then add your comment below:
You must be logged in to post to this forum

Click here to log in.


Subject: Installing Outlook on Exchange Server?
Posted by: andublin (view profile)
Posted on: Tuesday, September 14, 2010 at 3:25 AM
Message: "1.Install Outlook 2010 x64 on the Exchange server". Microsoft always strongly recommended against installing Outlook on the Exchange server, has that changed in 2010?

Subject: in theory :)
Posted by: kejs (view profile)
Posted on: Wednesday, September 29, 2010 at 7:35 AM
Message: All sounds very nice in theory, great article, but....first, the basics don't work for me...

Testing with UNC share located on exch srv itself produced 4/5 failed statuses and only one imported file.
Cant find why the other 4 failed as their status was "InProgress" and then it just simply "Failed".

Needless to say it imports without error through outlook installed on that same server.

 





How to Kill a Company in One Step or Save it in Three
 The majority of companies that suffer a major data loss subsequently go out of business. Wesley David... Read more...

Migrating to Microsoft BPOS - Part II
 In his last article, Johan gave us a crystal clear guide to preparing to migrate from an on-premises... Read more...

Monitoring Mailbox Moves
 Mailboxes moves happen all the time, and given how precious the data in mailboxes can be, you should... Read more...

Emulating the Exchange 2003 RUS for Out-of-Band Mailbox Provisioning in Exchange 2007
 Exchange's Recipient Update Service was important in Exchange 2000 or 2003 in order to complete the... Read more...

The Postmasters
 The Exchange Team introduces themselves, and keeps you up-to-date Read more...

Upgrade Exchange 2003 to Exchange 2010
  In this article, the first of two in which Jaap describes how to move from Exchange Server 2003... Read more...

Upgrade Exchange 2003 to Exchange 2010 - Part II
 In Jaap's second article on upgrading straight from Exchange Server 2003 to 2010, he explains how to... Read more...

Goodbye Exchange ExMerge, Hello Export-Mailbox
 ExMerge was a great way of exporting a mailbox to an Exchange PST file, or for removing all occurences... Read more...

Using Exchange 2007 for Resource Booking
 The process of booking various resources to go with a meeting room just got a whole lot easier with... Read more...

Managing Exchange 2007 Mailbox Quotas with Windows PowerShell
 The use of PowerShell with Exchange Server 2007 can do a great deal to ease the task of managing... Read more...

Over 400,000 Microsoft professionals subscribe to the Simple-Talk technical journal. Join today, it's fast, simple, free and secure.

Join Simple Talk