Public/Invoke-CopyProfileData.ps1
<#
.SYNOPSIS Copies user profile data to a specified drive. .DESCRIPTION This function uses Robocopy to copy user profile data to a specified drive. It supports detailed logging, exclusion of certain directories and files, and use of existing targets. .PARAMETER Drive The destination drive for the profile data. .PARAMETER ProfilePath The source path of the profile data. .PARAMETER LogPath The path to the existing log file where messages will be recorded. .PARAMETER IncludeRobocopyDetail Switch to include detailed Robocopy output. .PARAMETER UseExistingTarget Switch to use the existing target and exclude older files. .EXAMPLE Invoke-CopyProfileData -Drive "D:" -ProfilePath "C:\Users\Profile1" -LogPath "C:\Logs\ProfileCopy.log" # Copying the profile data of the user using Robocopy .EXAMPLE Invoke-CopyProfileData -Drive "D:" -ProfilePath "C:\Users\Profile1" -LogPath "C:\Logs\ProfileCopy.log" -IncludeRobocopyDetail # Includes the detailed results from Robocopy .EXAMPLE Invoke-CopyProfileData -Drive "D:" -ProfilePath "C:\Users\Profile1" -LogPath "C:\Logs\ProfileCopy.log" -UseExistingTarget # Skips the creation of the target location at copy #> function Invoke-CopyProfileData { [Diagnostics.CodeAnalysis.SuppressMessageAttribute( <#Category#>'PSAvoidUsingInvokeExpression', <#CheckId#>'', Scope='Function', Justification = 'Will be replaced with Process .NET class later on' )] [CmdletBinding(SupportsShouldProcess = $True)] Param ( [Parameter(Mandatory = $True)] [string]$Drive, [Parameter(Mandatory = $True)] [string]$ProfilePath, [Parameter(Mandatory = $True)] [string]$LogPath, [Parameter()] [switch]$IncludeRobocopyDetail, [Parameter()] [switch]$UseExistingTarget ) function Get-FolderSize { param ( [string]$FolderPath ) $folderSize = (Get-ChildItem -Path $FolderPath -Recurse | Measure-Object -Property Length -Sum).Sum switch ($folderSize) { { $_ -ge 1TB } { return "{0:N2} TB" -f ($folderSize / 1TB) } { $_ -ge 1GB } { return "{0:N2} GB" -f ($folderSize / 1GB) } { $_ -ge 1MB } { return "{0:N2} MB" -f ($folderSize / 1MB) } default { return "{0:N2} KB" -f ($folderSize / 1KB) } } } # 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 $LogPath)) { New-Item -ItemType File -Path $LogPath | Out-Null } # Calculate the size of the source folder $sourceSize = Get-FolderSize -FolderPath $ProfilePath if ($PSCmdlet.ShouldProcess("$ProfilePath", "Copying to $Drive")) { $destination = Join-Path -Path $Drive -ChildPath "Profile" # Log the start of the copying process Write-Log -Message "Starting the copy process using Robocopy." -LogPath $LogPath Write-Log -Message "Size of source folder: $sourceSize" -LogPath $LogPath # Execute Robocopy and capture output to a temporary file $tempLogPath = [System.IO.Path]::GetTempFileName() $robocopyCommand = "robocopy.exe `"$ProfilePath`" `"$destination`" *.* $robocopyParams $excludeParams /LOG:`"$tempLogPath`"" Invoke-Expression $robocopyCommand # Read and parse the Robocopy log file for summary information $logContent = Get-Content -Path $tempLogPath # Extract the required summary details $dirLine = $logContent | Select-String -Pattern "Dirs\s+:\s+\d+\s+\d+\s+\d+\s+\d+\s+\d+\s+\d+" $fileLine = $logContent | Select-String -Pattern "Files\s+:\s+\d+\s+\d+\s+\d+\s+\d+\s+\d+\s+\d+" $dirValues = ($dirLine -replace 'Dirs\s+:\s+', '').Trim() -split '\s+' $fileValues = ($fileLine -replace 'Files\s+:\s+', '').Trim() -split '\s+' $totalDirs = $dirValues[0] $copiedDirs = $dirValues[1] $totalFiles = $fileValues[0] $copiedFiles = $fileValues[1] # Calculate the size of the copied folder $copiedSize = Get-FolderSize -FolderPath $destination # Log the summary information Write-Log -Message "Total Directories: $totalDirs" -LogPath $LogPath Write-Log -Message "Copied Directories: $copiedDirs" -LogPath $LogPath Write-Log -Message "Total Files: $totalFiles" -LogPath $LogPath Write-Log -Message "Copied Files: $copiedFiles" -LogPath $LogPath Write-Log -Message "Size of copied folder: $copiedSize" -LogPath $LogPath # Check for completion based on Robocopy's exit code if ($LASTEXITCODE -le 7) { Write-Log -Message "Copy completed successfully." -LogPath $LogPath Write-Log "Copy completed successfully. Detailed log available at: $LogPath" } else { Write-Log -Message "Copy encountered issues." -LogPath $LogPath Write-Log "Copy encountered issues. Please check the log at: $LogPath" } # Append the temporary log file to the specified log path if detailed log is included if ($IncludeRobocopyDetail) { Get-Content -Path $tempLogPath | Add-Content -Path $LogPath } # Remove the temporary log file Remove-Item -Path $tempLogPath -Force } Write-Log "Operation completed." } |