Public/New-UserProfileDisk.ps1
<#
.SYNOPSIS Creates and manages a VHD for a user profile. .DESCRIPTION This function creates a new VHD for a user profile, formats it, assigns a drive letter, and manages the permissions for the specified user. It can also mount an existing VHD. .PARAMETER Target The target path for the VHD. .PARAMETER ProfilePath The profile path for the VHD (optional). .PARAMETER Username The username for which the VHD will be created or managed. .PARAMETER Size The size of the VHD in GB. .PARAMETER SectorSize The sector size for the VHD (optional). Valid values are '4K' or '512'. .PARAMETER PrimarySearchRoot The primary Active Directory search root. .PARAMETER SecondarySearchRoot The secondary Active Directory search root. .PARAMETER LogPath The path to the log file where messages will be recorded. .EXAMPLE New-UserProfileDisk -Target "C:\VHDs\UserProfile.vhdx" -Username "jdoe" -Size 50 -SectorSize '4K' -PrimarySearchRoot "GC://dc=test,dc=LOCAL" -SecondarySearchRoot "GC://dc=corp,dc=test,dc=com" -LogPath "C:\Logs\ProfileDisk.log" #> function New-UserProfileDisk { [CmdletBinding(SupportsShouldProcess = $True)] Param ( [Parameter(ValueFromPipelineByPropertyName, Mandatory = $True)] [string]$Target, [Parameter(ValueFromPipelineByPropertyName, Mandatory = $False)] [string]$ProfilePath, [Parameter(ValueFromPipelineByPropertyName, Mandatory = $True)] [string]$Username, [Parameter(ValueFromPipelineByPropertyName, Mandatory = $True)] [uint64]$Size, [Parameter(ValueFromPipelineByPropertyName, Mandatory = $False)] [ValidateSet('4K', '512')] [string]$SectorSize, [Parameter(Mandatory = $False)] [string]$LogPath ) function Write-Log { param ( [string] $Message, [string] $LogPath ) Add-Content -Path $LogPath -Value "$(Get-Date -Format 'yyyy-MM-dd HH:mm:ss') - $Message" } $OutputObject = @() if ($SectorSize -eq '4K'){ $SectorSizeBytes = 4096 } if ($SectorSize -eq '512'){ $SectorSizeBytes = 512 } function New-FSLogixVHD ($Target,$Size,$SectorSizeBytes){ Write-Output "Creating, formatting, and mounting VHD." Write-Log -Message "Creating, formatting, and mounting VHD." -LogPath $LogPath $Size = ($Size * 1GB) New-VHD -path $Target -SizeBytes $Size -Dynamic -LogicalSectorSizeBytes $SectorSizeBytes | Mount-VHD -Passthru | ` get-disk -number {$_.DiskNumber} | ` Initialize-Disk -PartitionStyle GPT -PassThru | ` New-Partition -UseMaximumSize -AssignDriveLetter:$False | ` Format-Volume -Confirm:$false -FileSystem NTFS -NewFileSystemLabel "Profile-$($Username)" -force | ` get-partition | ` Add-PartitionAccessPath -AssignDriveLetter -PassThru | ` Dismount-VHD $Target -ErrorAction SilentlyContinue } function Mount-FSLogixVHD ($Target){ Write-Output "Mounting VHD." Write-Log -Message "Mounting VHD." -LogPath $LogPath Mount-VHD $Target (Get-DiskImage -ImagePath $Target | ` Get-Disk | ` Get-Partition).DriveLetter Get-PSDrive | Out-Null } if ($pscmdlet.ShouldProcess($Name, 'Action')){ if ($Target -ne "Cannot Copy"){ if (!(Test-Path ($Target.Substring(0, $Target.LastIndexOf('.')) + "*"))) { New-FSLogixVHD -Target $Target -Size $Size -SectorSizeBytes $SectorSizeBytes icacls "$Target" /grant $Username`:f /t Write-Output "Mounting VHD $Target" Write-Log -Message "Mounting VHD $Target" -LogPath $LogPath Mount-VHD $Target -ErrorAction SilentlyContinue $drive = (Get-DiskImage -ImagePath $Target | Get-Disk | Get-Partition).DriveLetter Start-Sleep 6 if (($Drive | Measure-Object).count -gt 1){ $Drive = $drive[1]} $Item = New-Object system.object $Item | Add-Member -Type NoteProperty -Name Drive -Value "$drive`:\" $Item | Add-Member -Type NoteProperty -Name Target -Value $Target $OutputObject += $Item } else { Write-Output "$($Target.Substring(0, $Target.LastIndexOf('.'))) already exists- Updating." Write-Log -Message "$($Target.Substring(0, $Target.LastIndexOf('.'))) already exists- Updating." icacls "$Target" /grant $Username`:f /t Write-Output "Mounting VHD $Target" Write-Log -Message "Mounting VHD $Target" -LogPath $LogPath Mount-VHD $Target -ErrorAction SilentlyContinue $drive = (Get-DiskImage -ImagePath $Target | Get-Disk | Get-Partition).DriveLetter Start-Sleep 6 if (($Drive | Measure-Object).count -gt 1){ $Drive = $drive[1]} $Item = New-Object system.object $Item | Add-Member -Type NoteProperty -Name Drive -Value "$drive`:\" $Item | Add-Member -Type NoteProperty -Name Target -Value $Target $OutputObject += $Item } } } $OutputObject } |