Backing up Outlook .pst files while in use
Microsoft Outlook is a very popular e-mail client nowadays.
Though cloud based services are becoming more popular, it’s still the case that i.e. e-mail storage at service providers is very limited. Therefore, there are a lot of people out there who are forced to download their e-mail and archive it in their e-mail client, i.e. in Microsoft Outlook .pst files.
Now we all know the problem of ransomware or physical disk damage that can kill the data storage location of the outlook .pst files.
For performance reasons, it’s better to keep the files locally on a possibly fast SSD drive and not to store them on a slow network drive.
Even though when files are stored on a network drive, there still is a problem that files are in an inconsistent state when being backed up from that location.
There are tools like SafePST that address this problem and promise to offer functions to do a background backup of a .pst file while the file is open and in use by the e-mail application.
Even though, they backup works, it is still not working well, as the destination file grows significally without getting compacted, as it seems (i.e. I had 20GB of Outlook .pst files which grw to 1TB in Size at the backup location – ridiculous).
There are plugins for outlook like Personal folder backup from Microsoft, that copy the .pst files on Outlook exit, but this also isn’t a solution for very large files, as it would take far too long and maybe ppl don’t close their Outlook for weeks.
So, why not use a simple backup strategy and do what all these disk imaging applications do:
Make a Volume shadow copy snapshot of the drive that contains the Outlook data files, so that the .pst file is in an at least somewhat consitant state and then copy it to the backup location?
It turns out that this can be accomplished very easily with the tools that are already shipped with Windows 7 or above. Therefore we can create a simple batch file in order to do this job.
First, Outlook profiles of the current user are collected, then volume snapshots are taken for all local drives that contain Outlook data files, next files are copied from the snapshot and finally the snapshot gets released. When copying from the snapshot to the Backup destination, we have to ensure that file is first copied completely before the old file gets overwritten, therefore taking up at least twice the size of the largest .pst file on the backup drive.
From the backup drive, you then can have a backup routine like rsnapshot which pulls off the files from the drive and stores it at a safe location.
Here is my batch file that does exactly that with descriptive comments, I hope you find it as useful as I do:
@echo off REM REM Outlook .pst file backup script for Outlook 2007 or above and Windows 7 or above REM (c) leecher@dose.0wnz.at 12/2018 REM REM ---------- Configuration REM REM Set this to the Microsoft office internal version number you are using REM Works with Outlook 2007 or above: REM REM Outlook 2007 12.0 REM Outlook 2010 14.0 REM Outlook 2013 15.0 REM Outlook 2016 16.0 REM Outlook 2019 16.0 set OFFICEVER=12.0 REM If you want logging to a file, set logfile here, otherwise leave it blank set LOG= REM Temporary file that records the volume shadow copied created. REM Needed for removal on next run, if there is no clean exit. REM Normally, you should keep it as it is set SHADOWSF=%TEMP%\backup_pst.lst REM Destination directory.. Taken as cmdline arg, modify if needed set DEST=%1 REM REM ---------- Implementation REM setlocal ENABLEDELAYEDEXPANSION if "%DEST%"=="" ( echo Usage: %0 [Backup Destination directory] exit /b ) REM REM 1) Check for admin rights, we need them to run properly REM net session >nul 2>&1 if errorlevel 2 ( call :tee "ERROR: This script has to be run with administrative rights for VSS copying." exit /b 1 ) REM REM 2) Collect .pst files we need to process preserving spaces into PSTS REM call :log ".pst file backup started" set LW= set PSTS= for /f "tokens=1 delims=*" %%s in ('reg query HKCU\Software\Microsoft\Office\%OFFICEVER%\Outlook\Catalog /s ^| findstr "REG_BINARY"') do ( set KEY=%%s set KEY=!KEY:REG_BINARY=^|! for /F "tokens=1 delims=^|" %%t in ("!KEY!") do ( set KEY=%%t for /L %%a in (1,1,260) do ( if "!KEY:~-1!"==" " set KEY=!KEY:~0,-1! if "!KEY:~0,1!"==" " set KEY=!KEY:~1! ) set PSTS=!PSTS! "!KEY!" ) ) REM REM 3) Collect local drives we need to make a snapshot for REM for %%s in (!PSTS!) do ( set FOUND= for %%i in (!LW!) do if "%%i"=="%%~ds" set FOUND=1 if not !FOUND!==1 ( for /F "delims=" %%L in (' 2^>^&1 ^> nul wmic LogicalDisk where ^(DeviceID^="%%~ds" AND DriveType^=3^) ') do set FOUND=1 if not !FOUND!==1 set LW=!LW! %%~ds ) ) REM REM 4) If there are already volume shadow copies available, delete them first REM if exist %SHADOWSF% ( for /f "tokens=2 delims= " %%s in (%SHADOWSF%) do ( call :log "Removing stale volume shadow copy %%s" vssadmin delete Shadows /Shadow=%%s /quiet >nul ) ) REM REM 5) Create shadow copy of local drives to work with and collect GUIDs REM del %SHADOWSF% 2>nul for %%s in (%LW%) do ( for /f "tokens=3" %%i in ('"Wmic shadowcopy call create ClientAccessible,"%%s\""^|Findstr ShadowID') Do ( call :log "Created volume shadow copy %%i for drive %%s" set VSSID=%%i echo %%s !VSSID:~1,-2! >>%SHADOWSF% ) ) REM REM 6) Backup files from snapshot to backup location REM for %%s in (!PSTS!) do ( set FOUND= for /f "tokens=*" %%i in (%SHADOWSF%) do ( set VSS=%%i For /f "tokens=2 delims=:" %%j in ('"vssadmin list shadows /Shadow=!VSS:~3!"^|FindStr GLOBALROOT') Do Set VSSVOL=%%j if "!VSS:~0,2!"=="%%~ds" ( call :tee "Saving %%~ns%%~xs" copy /y !VSSVOL!%%~ps%%~ns%%~xs %DEST%\%%~ns.xxx if errorlevel 0 move /y %DEST%\%%~ns.xxx %DEST%\%%~ns%%~xs >nul set FOUND=1 ) ) if "%%~ds"=="\\" set FOUND=1 if not !FOUND! == 1 ( call :tee "echo Saving %%~ns%%~xs" copy /y %%s %DEST%\%%~ns.xxx if errorlevel 0 move /y %DEST%\%%~ns.xxx %DEST%\%%~ns%%~xs >nul ) ) REM REM 7) Delete shadow copies again, no longer needed REM for /f "tokens=2 delims= " %%s in (%SHADOWSF%) do ( vssadmin delete Shadows /Shadow=%%s /quiet >nul call :log "Removed shadow copy %%s" ) del %SHADOWSF% call :log ".pst file Backup finished" EXIT /B 0 :log IF NOT "%LOG%"=="" ECHO !DATE! !TIME! %* >>!LOG! EXIT /B 0 :tee ECHO %* CALL :log %* EXIT /B 0