functions/Convert-CFXUser.ps1

function Convert-CFXUser {
    [CmdletBinding()]
    param (
        # Username used for logon (SAMAccountName)
        [Parameter(Mandatory = $true, ValueFromPipelineByPropertyName = $true)]
        [string[]] $Username,

        # Location of Citrix Profile for all users e.g. \\FileServer\CTXProfiles\%username%\Win2016\UPM_Profile
        [Parameter(Mandatory = $true)]
        [string] $CitrixUPMProfilePath,

        # Location of Citrix Profile for all users e.g. \\FileServer\RedirectedFolders\%username%
        [Parameter(Mandatory = $true)]
        [string] $RedirectedFoldersPath,

        # Location of FSLogix Profile e.g. \\FileServer\FSLogixProfileContainers\ - accepts multiple entries.
        [Parameter(Mandatory = $true)]
        [ValidateScript( { Test-Path -Path $_ -PathType Container })]
        [string[]] $FSLogixProviderPath,

        # Allow overwrite of existing VHDs when copying to FSLogix providers.
        [Parameter(Mandatory = $false)]
        [Switch] $OverwriteFSLogix,

        # FSLogix Folder Name Pattern. You can use %SID% or %username%. Default is: "%Username%_%SID%"
        [Parameter(Mandatory = $false)]
        [string] $FSLogixFolderPattern = "%Username%_%SID%",

        # FSLogix virtual disk default size in GB.
        [Parameter(Mandatory = $false)]
        [int] $FSLogixVHDSizeGB = 30,

        # FSLogix VHDX Name Pattern. You can use %SID% or %username%. Default is: "Profile_%Username%.VHDX"
        [Parameter(Mandatory = $false)]
        [ValidatePattern('\.VHDX{0,1}$')] # ErrorMessage = 'FSLogix VHD name must end with VHD or VHDX'
        [string] $FSLogixVHDXPattern = "Profile_%Username%.VHDX",

        # FSLogix command line tool path
        [Parameter(Mandatory = $false)]
        [ValidateScript( { Test-Path -Path $_ -PathType Container })]
        [string] $FRXPath = 'C:\Program Files\FSLogix\Apps\frx.exe',

        # Log Folder Path
        [Parameter(Mandatory = $false)]
        [ValidateScript( { Test-Path -Path $_ -PathType Container })]
        [string] $LogFolderPath,

        # Temporary Disk Location - Default is user temp folder $env:Temp
        [Parameter(Mandatory = $false)]
        [ValidateScript( { Test-Path -Path $_ -PathType Container })]
        [string] $TempFolderPath = $env:Temp
    )
    begin {
        if ($Username.count -gt 1 -and $CitrixUPMProfilePath -NotLike "*%username%*") {
            throw "When providing multiple usernames, you must use %username% in parameter CitrixUPMProfilePath.`r`nFor example: \\FileServer\CTXProfiles\%username%\Win2016\UPM_Profile"
        }
    }

    process {
        foreach ($user in $Username) {
            try {
                # Confirm username is correct and retrieve SID
                $sid = Get-CFXADUserSID -Username $user -ErrorAction Stop

                #region: Calculate variables

                # Calculate name for FSLogix Folder and File - Check if FSLogix folder already exists, fail if so.
                $fsLogixPathParams = @{
                    FSLogixProfileRootPath = $FSLogixProviderPath
                    FSLogixFolderPattern   = $FSLogixFolderPattern
                    FSLogixVHDXPattern     = $FSLogixVHDXPattern
                    Username               = $user
                    SID                    = $sid
                    Overwrite              = $OverwriteFSLogix
                }
                $fslogixFilePath = Get-CFXFSLogixPath @fsLogixPathParams -ErrorAction Stop

                # Calculate path for Citrix profile location
                $citrixProfilePath = Get-CFXProfilePath -Username $user -ProfilePath $CitrixUPMProfilePath -ErrorAction Stop
                #If profile not found, fail

                # Calculate path for Redirected folder profile location
                if ($Username.count -gt 1 -and $CitrixUPMProfilePath -NotLike "*%username%*") {
                    throw "When providing multiple usernames, you must use %username% in parameter RedirectedFoldersPath.`r`nFor example: \\FileServer\RedirectedFolders\%username%"
                }
                $redirectedFoldersPath = Get-CFXProfilePath -Username $user -ProfilePath $RedirectedFoldersPath -ErrorAction Stop
                #If folder not found, fail

                # Calculate path for log file and confirm access.
                if ($LogFolderPath) {
                    $logFilePath = Get-CFXLogFilePath -LogFolderPath $LogFolderPath -ErrorAction Stop
                }

                #endregion: Calculate variables

                # Create disk using FSLogix copy-profile
                $tempDiskPath = Join-PSFPath $TempFolderPath ($fslogixFilePath[0] | Split-Path -Leaf)
                Write-PSFMessage -Level Verbose -Message "Copying Citrix profile to new VHD: $tempDiskPath"
                New-CFXFSLogixVHD -citrixProfilePath $citrixProfilePath -Path $tempDiskPath -Username $user -FRX $FRXPath -ErrorAction Stop

                # Copy redirected folders to disk using robocopy
                Write-PSFMessage -Level Verbose -Message "Copying Redirected folders to VHD."
                Copy-CFXRedirectedFolders -DiskPath $tempDiskPath -RedirectedFoldersPath $redirectedFoldersPath -FRX $FRXPath -ErrorAction Stop

                # Copy disk to profile location(s)
                $diskItem = Get-Item -Path $tempDiskPath
                Write-PSFMessage -Level Verbose -Message "Copying VHD to FSLogix Providers."
                $copyResult = Copy-CFXFSLogixProvider -DiskPath $tempDiskPath -ProviderPath $fslogixFilePath

                $success = $true
            }
            catch {
                $errorMessage = $_.Exception.Message
                $success = $false
                #Stop-PSFfunction -Message $_ -EnableException $true -SilentlyContinue -Cmdlet $PSCmdlet
                Write-Error -Message $_.Exception.Message
            }


            [PSCustomObject]@{
                username              = $UserName
                Success               = $success
                SID                   = $sid
                CitrixProfilePath     = $citrixProfilePath
                RedirectedFoldersPath = $redirectedFoldersPath
                VHDSizeGB             = ($diskItem.length / 1GB)
                CopyResults           = $copyResult
                ErrorMessage          = $errorMessage
            }
        }
    }
}