SOLVED

Export to PST via Powershell

Deleted
Not applicable

I am continually expanding on my offboarding process within Orchestrator. I decided to add the export of the email so that all that has to be done is go to the Content search and download it (unless someone knows how to do that as well...). My addition works, however, instead of creating a single PST file, I end up getting the actual folders with individual email in message file format. I have tried what is correct per everything I could find (honestly, not a lot of detail on the subject). The current single line in question is:

New-ComplianceSearchAction -SearchName $SearchName -Export -ArchiveFormat PerUserPST -EnableDedupe $true 

I have tried different values for -ArchiveFormat including leaving it completely off since a single pst per user is supposed to be the default.

 

 

I will include the entire part of the script responsible for the full function in case it is supposed to be declared somewhere else (but I haven't found anything).

# Create Compliance Search - Export Email

$SearchName = "Export - " + $term.Name
New-ComplianceSearch -ExchangeLocation $term365.UserPrincipalName -Name $SearchName

# Start Compliance Search and wait to complete

Start-ComplianceSearch $SearchName
do
    {
        Start-Sleep -s 5
        $complianceSearch = Get-ComplianceSearch $SearchName
    }
while ($complianceSearch.Status -ne 'Completed')

# Create Compliance Search in exportable format
New-ComplianceSearchAction -SearchName $SearchName -Export -ArchiveFormat PerUserPST -EnableDedupe $true 
$ExportName = $SearchName + "_Export"

#Wait for Export to complete
do
    {
        Start-Sleep -s 5
        $complete = Get-ComplianceSearchAction -Identity $ExportName
    }
while ($complete.Status -ne 'Completed')

Any help would be appreciated!

 

45 Replies

@JChup 

 

not sure what the issue is but it seems like it doesn't wait for the export to finish before starting the download?

 

CaseId                                :
CaseName                              :
PagingState                           :
Identity                              : e7423609-836a-4438-45eb-08da91ee30bf
ContentURL                            :
ResultInEOP                           : False
AzureBatchFrameworkEnabled            : True
IsValid                               : True
ObjectState                           : New

No se puede llamar a un método en una expresión con valor NULL.
En C:\Temp\test.ps1: 97 Carácter: 1
+ $ExportEstSize = ($ExportDetails[18].TrimStart(" Total estimated byte ...
+ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    + CategoryInfo          : InvalidOperation: (:) [], RuntimeException
    + FullyQualifiedErrorId : InvokeMethodOnNull

No se puede llamar a un método en una expresión con valor NULL.
En C:\Temp\test.ps1: 98 Carácter: 1
+ $ExportTransferred = ($ExportDetails[20].TrimStart(" Total transferre ...
+ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    + CategoryInfo          : InvalidOperation: (:) [], RuntimeException
    + FullyQualifiedErrorId : InvokeMethodOnNull

No se puede llamar a un método en una expresión con valor NULL.
En C:\Temp\test.ps1: 99 Carácter: 1
+ $ExportProgress = $ExportDetails[22].TrimStart(" Progress: ").TrimEnd ...
+ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    + CategoryInfo          : InvalidOperation: (:) [], RuntimeException
    + FullyQualifiedErrorId : InvokeMethodOnNull

No se puede llamar a un método en una expresión con valor NULL.
En C:\Temp\test.ps1: 100 Carácter: 1
+ $ExportStatus = $ExportDetails[25].TrimStart(" Export status: ")
+ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    + CategoryInfo          : InvalidOperation: (:) [], RuntimeException
    + FullyQualifiedErrorId : InvokeMethodOnNull

Initiating download
Saving export to:  + d:\temp
Write-Progress : No se puede validar el argumento del parámetro 'PercentComplete'. El argumento es NULL, está vacío o un elemento de la colección de argumentos contiene un valor NULL.
Proporcione una colección que no contenga ningún valor NULL e intente ejecutar el comando de nuevo.
En C:\Temp\test.ps1: 120 Carácter: 96
+ ... t in Progress" -Status "Complete..." -PercentComplete $ExportProgress
+                                                           ~~~~~~~~~~~~~~~
    + CategoryInfo          : InvalidData: (:) [Write-Progress], ParameterBindingValidationException
    + FullyQualifiedErrorId : ParameterArgumentValidationError,Microsoft.PowerShell.Commands.WriteProgressCommand

Intento de dividir por cero.
En C:\Temp\test.ps1: 121 Carácter: 45
+ ... portStatus){Write-Progress -Id 2 -Activity "Download in Progress" -St ...
+                 ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    + CategoryInfo          : NotSpecified: (:) [], RuntimeException
    + FullyQualifiedErrorId : RuntimeException

No se puede llamar a un método en una expresión con valor NULL.
En C:\Temp\test.ps1: 126 Carácter: 5
+     $ExportEstSize = ($ExportDetails[18].TrimStart(" Total estimated  ...
+     ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    + CategoryInfo          : InvalidOperation: (:) [], RuntimeException
    + FullyQualifiedErrorId : InvokeMethodOnNull

No se puede llamar a un método en una expresión con valor NULL.
En C:\Temp\test.ps1: 127 Carácter: 5
+     $ExportTransferred = ($ExportDetails[20].TrimStart(" Total transf ...
+     ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    + CategoryInfo          : InvalidOperation: (:) [], RuntimeException
    + FullyQualifiedErrorId : InvokeMethodOnNull

No se puede llamar a un método en una expresión con valor NULL.
En C:\Temp\test.ps1: 128 Carácter: 5
+     $ExportProgress = $ExportDetails[22].TrimStart(" Progress: ").Tri ...
+     ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    + CategoryInfo          : InvalidOperation: (:) [], RuntimeException
    + FullyQualifiedErrorId : InvokeMethodOnNull

No se puede llamar a un método en una expresión con valor NULL.
En C:\Temp\test.ps1: 129 Carácter: 5
+     $ExportStatus = $ExportDetails[25].TrimStart(" Export status: ")
+     ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    + CategoryInfo          : InvalidOperation: (:) [], RuntimeException
    + FullyQualifiedErrorId : InvokeMethodOnNull

 .Download Complete!
Presione Entrar para continuar...:

I have built out a pretty extensive offboarding script that performs a lot of these tasks. I wonder if there is a way to download from multiple exports simultaneously. I am going to be looking into start-job to see if I can maybe start 4 or 5 downloads at once. 

@jordanpnnl 

 

Honestly, I think converting to a Shared Mailbox and avoiding PSTs all together is the best idea. However, in the event you can't, the Outlook Interop seems the best alternative for now...

 

 

 

function Add-PSOutlookStore([string]$StoreFilePath) {
    [void]($comOutlookNS.AddStore($StoreFilePath))
}

function Remove-PSOutlookStore([string]$StoreFilePath) {
    [void]($comOutlookNS.RemoveStore($StoreFilePath))
}

function Export-PSOutlookInbox([string]$EmailAddress, [string]$DestinationFilePath) {
    Add-PSOutlookStore($DestinationFilePath)

    $comOutlookRcpt = $null
    try {
        $comOutlookRcpt = $Script:comOutlookNS.CreateRecipient($EmailAddress)
        [void]($comOutlookRcpt.Resolve())
    }
    catch {
        Write-PSFMessage -Level Critical -Message "Failed to resolve recipient $EmailAddress"
        Write-PSFMessage -Level Verbose -Message $Error[0]
    }

    if ($comOutlookRcpt) {
        for ($i = 0; $i -lt $comOutlookFolderTypes.Length; $i++) {
            $comOutlookFolderType = $comOutlookFolderTypes[$i]
    
            Write-PSFMessage -Level VeryVerbose -Message "Iterating through shared folder type $comOutlookFolderType"
            try {
                $comOutlookRctpFolder = $Script:comOutlookNS.GetSharedDefaultFolder($comOutlookRcpt, $comOutlookFolderType)
                if ($comOutlookRctpFolder.DefaultItemType -eq [Microsoft.Office.Interop.Outlook.OlItemType]::olMailItem) {
                    Write-PSFMessage -Level Host -Message "Successfully copied shared folder"
                }
                else {
                    Write-PSFMessage -Level Verbose -Message "Skipping shared folder as it is non-mail"
                }
            }
            catch {
                Write-PSFMessage -Level Warning -Message "Failed to get shared folder $comOutlookFolderType"
                Write-PSFMessage -Level Verbose -Message $Error[0]
            }
        }
    }

    Remove-PSOutlookStore($DestinationFilePath)
}

 

 

This is just a partial from my PS module.

Is there any other method to export Outlook PST files?

Once you get the SAS Token and URL from the export using commands discussed in forum. Ensure you have the download tool installed on the machine you are running the code and then It can be done programmatically using PowerShell-

 

$arguments = "-name ""$exportname""","-source ""$containerURL""","-key ""$sastoken""","-dest ""$exportLocation""","-trace true"

Start-Process -FilePath "$exportExe" -ArgumentList $arguments -wait 

 

You can either use -wait switch to let the script wait until download is completed or you can keep querying the status of the process every minute or so.

@tylermontney_acc ,

Would you be able to share the link for your PS module?