Public/New-DataVHD.ps1
function New-DataVHD { <# .Synopsis Create a VHDX Data Drive with GPT partitions .DESCRIPTION This command will create a VHD or VHDX with a GPT partition table formated ReFS(Default) or NTFS. You must supply the path to the VHD/VHDX file Use -Force to overwite existing file (ACLs will be copied to new file) .EXAMPLE New-DataVHD -Path c:\Data.vhdx -Size 20GB -Dynamic Creats a new 20GB Data VHDX that is dynamic, formated ReFS .EXAMPLE New-DataVHD -Path c:\data.vhdx -Size 100GB -DataFormat NTFS Creats a new 100GB Data VHDX formated NTFS #> [CmdletBinding(SupportsShouldProcess = $true, PositionalBinding = $false, ConfirmImpact = 'Medium')] Param ( # Path to the new VHDX file (Must end in .vhdx) [Parameter(Position = 0, Mandatory = $true, HelpMessage = 'Enter the path for the new VHDX file')] [ValidateNotNullorEmpty()] [ValidatePattern(".\.vhdx?$")] [ValidateScript( { if (Get-FullFilePath -Path $_ | Split-Path | Resolve-Path ) { $true } else { Throw "Parent folder for $_ does not exist." } })] [string]$Path, # Format drive as NTFS or ReFS (Only applies when DiskLayout = Data) [string] [ValidateNotNullOrEmpty()] [ValidateSet('NTFS', 'ReFS')] $DataFormat = 'ReFS', # Alocation Unit Size to format the primary partition [int] [ValidateSet(4kb, 8kb, 16kb, 32kb, 64kb, 128kb, 256kb, 512kb, 1024kb, 2048kb)] $AllocationUnitSize, # Size in Bytes (Default 40B) [ValidateRange(100mb, 64TB)] [long]$Size = 40GB, # MS Reserved Partition Size (Default : 128MB) [int]$ReservedSize, # Create Dynamic disk [switch]$Dynamic, # Force the overwrite of existing files [switch]$force ) $Path = $Path | Get-FullFilePath $VhdxFileName = Split-Path -Leaf -Path $Path if ($pscmdlet.ShouldProcess("[$($MyInvocation.MyCommand)] : Overwrite partitions inside [$Path] with GPT Data Partitions", "Overwrite partitions inside [$Path] with GPT Data Partitions ? ", 'Overwrite WARNING!')) { if ((-not (Test-Path $Path)) -Or $force -Or $pscmdlet.ShouldContinue('Are you sure? Any existin data will be lost!', 'Warning')) { $ParametersToPass = @{ } foreach ($key in ('Whatif', 'Verbose', 'Debug')) { if ($PSBoundParameters.ContainsKey($key)) { $ParametersToPass[$key] = $PSBoundParameters[$key] } } $InitializeVHDPartitionParam = @{ 'Size' = $Size 'Path' = $Path 'force' = $true 'DiskLayout' = 'Data' 'DataFormat' = $DataFormat } if ($Dynamic) { $InitializeVHDPartitionParam.add('Dynamic', $true) } if ($ReservedSize) { $InitializeVHDPartitionParam.add('ReservedSize', $ReservedSize) } if ($AllocationUnitSize) { $InitializeVHDPartitionParam.add('AllocationUnitSize', $AllocationUnitSize) } Write-Verbose -Message "[$($MyInvocation.MyCommand)] : InitializeVHDPartitionParam" Write-Verbose -Message ($InitializeVHDPartitionParam | Out-String) Write-Verbose -Message "[$($MyInvocation.MyCommand)] : ParametersToPass" Write-Verbose -Message ($ParametersToPass | Out-String) Try { Initialize-VHDPartition @InitializeVHDPartitionParam @ParametersToPass } Catch { throw "$($_.Exception.Message) at $($_.Exception.InvocationInfo.ScriptLineNumber)" } #region mount the VHDX file try { Write-Verbose -Message "[$($MyInvocation.MyCommand)] [$VhdxFileName] : Mounting disk image [$Path]" $disk = Mount-DiskImage -ImagePath $Path -PassThru | Get-DiskImage | Get-Disk $DiskNumber = $disk.Number } catch { throw $_.Exception.Message } #endregion try { #! Workarround for new drive letters in script modules $null = Get-PSDrive #region Assign Drive Letters (disable explorer popup and reset afterwords) $DisableAutoPlayOldValue = (Get-ItemProperty -path hkcu:\Software\Microsoft\Windows\CurrentVersion\Explorer\AutoplayHandlers -name DisableAutoplay).DisableAutoplay Set-ItemProperty -Path hkcu:\Software\Microsoft\Windows\CurrentVersion\Explorer\AutoplayHandlers -Name DisableAutoplay -Value 1 foreach ($partition in (Get-Partition -DiskNumber $DiskNumber | where-object -FilterScript { $_.Type -eq 'IFS' -or $_.type -eq 'basic' })) { $partition | Add-PartitionAccessPath -AssignDriveLetter -ErrorAction Stop } #! Workarround for new drive letters in script modules $null = Get-PSDrive Set-ItemProperty -Path hkcu:\Software\Microsoft\Windows\CurrentVersion\Explorer\AutoplayHandlers -Name DisableAutoplay -Value $DisableAutoPlayOldValue } catch { Write-Error -Message "[$($MyInvocation.MyCommand)] [$VhdxFileName] : Error Adding Drive Letter " throw $_.Exception.Message } finally { #dismount Write-Verbose -Message "[$($MyInvocation.MyCommand)] [$VhdxFileName] : Dismounting" $null = Dismount-DiskImage -ImagePath $Path if ($isoPath -and (Get-DiskImage $isoPath).Attached) { $null = Dismount-DiskImage -ImagePath $isoPath [System.GC]::Collect() } Write-Verbose -Message "[$($MyInvocation.MyCommand)] [$VhdxFileName] : Finished" } } } } |