Public/Invoke-ProfileCopy.ps1

<#
.SYNOPSIS
    Copies user profiles to a specified drive using Robocopy with detailed logging.
 
.DESCRIPTION
    This function copies user profiles from a specified source path to a target drive. It uses Robocopy for efficient file transfer,
    providing options for detailed logging and handling existing targets.
 
.PARAMETER Drive
    The target drive where the profile should be copied to.
 
.PARAMETER ProfilePath
    The path of the user profile to be copied.
 
.PARAMETER LogDirectory
    The directory where log files should be stored.
 
.PARAMETER IncludeRobocopyDetail
    If set, Robocopy will provide a detailed log of the copy process including file names and statuses.
 
.PARAMETER UseExistingTarget
    If set, the function will not overwrite existing files in the target location.
 
.EXAMPLE
    Invoke-ProfileCopy -Drive "D:" -ProfilePath "\\Server\Profiles\JohnDoe" -LogDirectory "C:\Migration\RobocopyLogs"
    Copies the user profile from "\\Server\Profiles\JohnDoe" to "D:\Profile" and stores the logs in "C:\Migration\RobocopyLogs".
 
.EXAMPLE
    Invoke-ProfileCopy -Drive "D:" -ProfilePath "\\Server\Profiles\JohnDoe" -IncludeRobocopyDetail -UseExistingTarget -LogDirectory "C:\Logs"
    Copies the profile with additional Robocopy logging details and does not overwrite existing files. Logs are stored in "C:\Logs".
 
.NOTES
    Uses Robocopy for file transfer, supports logging, and can handle large profiles with networked sources.
#>


Function Invoke-ProfileCopy {
    [CmdletBinding(SupportsShouldProcess=$True)]
    Param (
        [Parameter(Mandatory=$True)]
        [string]$Drive,
            
        [Parameter(Mandatory=$True)]
        [string]$ProfilePath,

        [Parameter(Mandatory=$True)]
        [string]$LogDirectory,

        [Parameter()]
        [switch]$IncludeRobocopyDetail,
        
        [Parameter()]
        [switch]$UseExistingTarget
    )

    Begin {
        # Setup Robocopy parameters for detailed or minimal output
        $robocopyParams = '/E /Z /COPYALL /R:2 /W:1'
        if ($UseExistingTarget) {
            $robocopyParams += ' /XO'
        }
        if ($IncludeRobocopyDetail) {
            $robocopyParams += ' /V'  # Verbose output
        } else {
            $robocopyParams += ' /NP'  # No progress - number of files copied
        }
        $robocopyParams += ' /MT:16'  # Multithreading for faster copy

        # Define exclusions
        $excludeDirs = @('/XD "System Volume Information"', '/XD "Start Menu"')
        $excludeFiles = @('/XF *.ost', '/XF "*-Autodiscover.xml"')
        $excludeParams = $excludeDirs + $excludeFiles

        if (-not (Test-Path -Path $LogDirectory)) {
            New-Item -ItemType Directory -Path $LogDirectory | Out-Null
        }
        $timestamp = (Get-Date -Format 'yyyy-MM-dd-HH-mm-ss')
        $logPath = Join-Path -Path $LogDirectory -ChildPath "RobocopyLog_$timestamp.txt"
    }
    
    Process {
        if ($PSCmdlet.ShouldProcess("$ProfilePath", "Copying to $Drive")) {
            $destination = Join-Path -Path $Drive -ChildPath "Profile"
            # Execute Robocopy
            $robocopyCommand = "robocopy.exe $ProfilePath $destination *.* $robocopyParams $excludeParams /LOG:$logPath"
            Invoke-Expression $robocopyCommand

            # Check for completion based on Robocopy's exit code
            if ($LASTEXITCODE -le 7) {
                Write-Host "Copy completed successfully. Detailed log available at: $logPath"
            } else {
                Write-Host "Copy encountered issues. Please check the log at: $logPath"
            }
        }
    }

    End {
        Write-Host "Operation completed."
    }
}