So, let’s say you’ve got a few hundred or thousand PST’s sitting in a folder somewhere. Some may be corrupt or password protected. You want to verify which ones are accessible, but it will take hours to open each of them in Outlook to check. What do you do? PowerShell of course. Luckily, automating Outlook via PowerShell is easy. Below you will find a function you can use to check tons of PST files in no time. You just need a machine with PowerShell and Outlook installed. I used Outlook 2013 and PowerShell v3 to write and test this code.

function Test-PSTFile {
  param(
    [Parameter(Position=1, ValueFromPipeline=$true, Mandatory=$true)]
    $FilePath,
    [Parameter(Position=2, Mandatory=$false)]
    $ErrorLog
    )

  process {
         #Create an instance of Outlook
         $null = Add-type -assembly Microsoft.Office.Interop.Outlook 
         $olFolders = 'Microsoft.Office.Interop.Outlook.olDefaultFolders' -as [type]  
         $outlook = new-object -comobject outlook.application

         #Open the MAPI profile
         $namespace = $outlook.GetNameSpace('MAPI')
     try {
         #Try to add the PST file to the profile
         $namespace.AddStore($FilePath)

         #Try to read the root folder name
         $PST = $namespace.Stores | ? {$_.FilePath -eq $FilePath}
         $PSTRoot = $PST.GetRootFolder()         

         if($PSTRoot) {
            New-Object PSObject -Property @{
                FileName = $FilePath
                Valid = $True
            }
         }

         #Disconnect the PST
         $PSTFolder = $namespace.Folders.Item($PSTRoot.Name)
         $namespace.GetType().InvokeMember('RemoveStore',[System.Reflection.BindingFlags]::InvokeMethod,$null,$namespace,($PSTFolder))
     }
     catch {
         #If logging is on, save the error to the log
         if($ErrorLog) {
            Add-Content -Path $ErrorLog -Value ("Ran into a problem with {0} at {1}. The error was {2}" -f $FilePath, (Get-Date).ToString(),$_.Exception.Message)
         }

         #Output a failure record
         New-Object PSObject -Property @{
            FileName = $FilePath
            Valid = $False
         }
     }
  }
}

The way this thing works is it adds the PST to your existing Outlook MAPI profile. If the PST file can be opened and read from you can assume everything is good. Otherwise, this function can optionally record the bad file names and the exception messages to an error log for later review. To run this, add the function to your shell session and you’re ready to go. Here’s a few examples of how you might use it.

First, of course, you could run it one file at a time. Cool, but not really that impressive.

Test-PSTFile c:\emails.pst -ErrorLog c:\errors.txt

The real productivity comes from doing this in bulk, as shown in this one liner that tests all the PST files in a particular directory. This is much cooler.

dir C:\PSTs *.pst | 
	select -ExpandProperty fullname | 
		Test-PSTFile -ErrorLog c:\errors.txt

The output would be similar to the following.

Valid FileName
----- --------
 True C:\PSTs\dave.pst
 True C:\PSTs\joe.pst
False C:\PSTs\sarah.pst
 True C:\PSTs\steve.pst

Other useful and related code samples can be found here and here.