Backup-EvidenceLock.ps1

function New-DesktopIni {
    param (
        [string]
        $Path,
        [string]
        $LocalizedResourceName
    )
    $filePath = Join-Path -Path $Path -ChildPath desktop.ini
    $content = "[.ShellClassInfo]
ConfirmFileOp=0
LocalizedResourceName=$LocalizedResourceName"

    Set-ItemProperty $Path -Name Attributes -Value "ReadOnly,System"
    New-Item -Path $filePath -ItemType file -Value $content | Out-Null
}

<#
    .SYNOPSIS
        Backs up Evidence Locked data as an XProtect Database video export.
 
    .DESCRIPTION
        Evidence Locked video usually represents data of critical importance. Important data should be backed
        up such that it exists in at least three places, one of which should be offsite whenever possible. This
        cmdlet is intended to help achieve this end in a small but critical way - automate exports of evidence
        locked data.
 
        This cmdlet takes a list of Evidence Lock entries, and performs the following tasks:
 
        1. Check $Path to see if a folder named after the Id <Guid> of the Evidence Lock MarkedData entry exists
        2. If $Path/$Id doesn't exist, create a new folder at $Path/$Id
        3. Create a Desktop.ini file in $Path/$Id and set LocalizedResourceName to the Header property of the Evidence Lock entry
        4. Call 'Start-Export -Path $Path -Name $Id -Format DB [-Force]' passing the Evidence Lock entry to define the devices and start/end time for the export
        5. If the export does not succeed, or only partially succeeds for any reason, the directory $Path/$Id is deleted to ensure the export is tried again on the next execution
         
 
    .PARAMETER EvidenceLocks
        Specifies the Evidence Lock entry or entries to backup.
 
    .PARAMETER Path
        Specifies the path to the directory where the video exports should be stored. This is also where the transcript log will be saved.
 
    .PARAMETER Force
        Perform the export as long as at least one device is reachable and has data to export, even if one or more devices are unreachable due to communication errors or media database errors on a Recording Server.
 
    .EXAMPLE
        Get-EvidenceLock | Backup-EvidenceLock -Path \\storageserver\backups\evidence -Force
 
        Sends all existing evidence locks into the Backup-EvidenceLock cmdlet where only entries that have not been successfully exported will be exported in Media Database format under a folder named for the GUID of the entry, but displaying in Windows Explorer using a friendly name.
 
    .EXAMPLE
        Get-EvidenceLock -SearchText 'AutoExport' | Backup-EvidenceLock -Path \\storageserver\backups\evidence -Force
 
        Only backup evidence locks with "AutoExport" present in the Header or Description.
#>

function Backup-EvidenceLock {
    Param(
        [Parameter(ValueFromPipeline = $true)]
        [VideoOS.Common.Proxy.Server.WCF.MarkedData[]]
        $EvidenceLocks,
        [Parameter()]
        [string]
        $Path = '.\',
        [Parameter()]
        [switch]
        $Force
    )

    process {
        $date = Get-Date -Format yyyy-MM-dd
        Start-Transcript -Path (Join-Path -Path $Path -ChildPath "Backup-EvidenceLock_$date.txt") -IncludeInvocationHeader -Append
        $status = @{ 
            Total = 0
            Skipped = 0
            Succeeded = 0
            Failed = 0
        }
        foreach ($markedData in $EvidenceLocks) {
            $status.Total++
            Write-Information "Processing Evidence Lock '$($markedData.Header)' with ID '$($markedData.Id)'"
            $exportPath = Join-Path -Path $Path -ChildPath $markedData.Id
            if (Test-Path -Path $exportPath) {
                Write-Information "Export already exists at path '$exportPath'"
                $status.Skipped++
                continue 
            }
            try {
                Write-Information "Creating export directory and setting LocalizedResourceName in desktop.ini"
                New-Item -Path $exportPath -ItemType Directory | Out-Null
                New-DesktopIni -Path $exportPath -LocalizedResourceName $markedData.Header.Trim()
                Write-Information "Starting export. . ."
                $markedData | Start-Export -Path $Path -Name $markedData.Id -Format DB -Force:$Force -ErrorAction Stop
                $status.Succeeded++
                Write-Information "Export completed for Evidence Lock with ID '$($markedData.Id)'"
            }
            catch {
                $status.Failed++
                Write-Warning "Export failed for Evidence Lock with ID '$($markedData.Id)', Error: $($_.Exception.Message)"
                Write-Information "Cleaning up directory of failed export. . ."
                Remove-item -Path $exportPath -Recurse -ErrorAction Stop -Force
            }
        }
        Write-Information "Evidence Locks Total: $($status.Total), Succeeded: $($status.Succeeded), Failed: $($status.Failed), Skipped: $($status.Skipped)"
        Stop-Transcript
    }
}