internal/functions/Copy-CFXRedirectedFolders.ps1

function Copy-CFXRedirectedFolders {
    [CmdletBinding()]
    param (
        [Parameter(Mandatory = $true)]
        [string] $FRX ,

        [Parameter(Mandatory = $true)]
        [string] $DiskPath,

        [Parameter(Mandatory = $true)]
        [string] $RedirectedFoldersPath
    )
    Write-PSFMessage -Level Verbose -Message "Mounting VHD using FRX.exe: $Diskpath"
    $mountPoint = Mount-CFXProfile -FRX $FRX -DiskPath $DiskPath
    try{
        $robocopyDestination = (Join-PSFPath $mountPoint.Path 'Profile')
        Write-PSFMessage -Level Verbose -Message "Copying files from $RedirectedFoldersPath to $robocopyDestination"
        $roboCopyError = $null
        $robocopy = & Robocopy $RedirectedFoldersPath $robocopyDestination  /COPYALL /XJ /E /B /MT:10 /W:1 /R:1 /NP /NFL /NDL /NJH /NJS
        <#
            /COPYALL: Copy with timestamp, NTFS permissions, Owner, Audit, etc...
            /XJ: Do not copy junction points (this can cause infinite loops)
            /E: Copy all subfolder and files including empty directories
            /B: Copy in backup mode, requires permission on target system OS. HElps avoid NTFS security blocks.
            /MT:10 Copy 10 files simultaneously (Multi-threaded) Good for network performance.
            /W:1 /R:1: In case of error, retry one time. wait one second.
            /NP /NFL /NJH /NJS: Do not show progress, list of files or directories, header, or summary. So Robocopy should not return any output other than errors.
        #>

        if(-Not ([string]::IsNullOrEmpty($robocopy))){
            throw "Robocopy returned errors:`r`n$robocopy"
        }
    }
    catch {
        $roboCopyError = $_
    }
    finally{
        Write-PSFMessage -Level Verbose -Message "Dismounting VHD using FRX.exe"
        Dismount-CFXProfile -DiskPath $DiskPath -Cookie $mountPoint.Cookie -FRX $FRX
        if($roboCopyError) {throw $roboCopyError}
    }

}