Question

I'm having issues scripting the creation of a new VHD (A tool for the creation of network optimised packages). The script below basically pulls the total size of the input directory and passes that as a variable to the $intval function, which converts the size in bytes to a string, $size (nGB).

The problem I'm having is that the cmdlet NEW-VHD requires the -SizeBytes parameter to be in the format Uint64. If you enter the parameter manually, e.g.

NEW-VHD -path $vhdpath -fixed -SizeBytes 10GB

the cmdlet functions as intended and creates the VHD as it accepts the 10GB as a Uint64. What I need is the variable $size to be somehow converted to a Uint64 whilst retaining the trailing GB. Is there any way of imitating user input in this scenario?

I understand the below script isn't optimised or the nicest looking as it is only a proof of concept. Any suggestions regarding the above issue would be welcomed!

Code

$dir = Read-Host 'What is the directory you are wishing to store inside a VHD?'
$objFSO = New-Object -com Scripting.FileSystemObject
$intval = $objFSO.GetFolder($dir).Size / 1GB
$size = "{0:N0}GB" -f $intval
$vhd = Read-Host 'What volume name do you wish to call your VHD (no spaces)?'
$vhdname = ($vhd + ".vhdx")
$vhdpath = ("C:\VHD\" + $vhdname)
NEW-VHD -fixed -path $vhdpath -SizeBytes $size

I've had a look at a few Microsoft resources but have come up empty

Modified Code

$dir = Read-Host 'What is the directory you are wishing to store inside a VHD?'
$objFSO = New-Object -com Scripting.FileSystemObject
$intval = $objFSO.GetFolder($dir).Size
$size = $intval / 1GB
$vhd = Read-Host 'What volume name do you wish to call your VHD (no spaces)?'
$vhdname = ($vhd + ".vhdx")
$vhdpath = ("C:\VHD\" + $vhdname)
NEW-VHD -fixed -path $vhdpath -SizeBytes $size
Was it helpful?

Solution 2

Here is the code I wrote in order to get around the odd little bug.

#-------------------------------VHD CREATION-------------------------------------#

#Create a VHD with a size of 3MB to get around variable bug
        New-VHD -Path $vhdpath -SizeBytes 3MB -Fixed
#Resize to target dir + extra
        Resize-VHD -Path $vhdpath -SizeBytes $size
#Mount/Format and Recursively Copy Items
        Mount-VHD $vhdpath -Passthru | Initialize-Disk -Passthru | New-Partition -UseMaximumSize | 
        Format-Volume -FileSystem NTFS -NewFileSystemLabel $volumename -Confirm:$false
            $drive = gwmi win32_volume -Filter "DriveLetter = null"
            $drive.DriveLetter = "B:"
            $drive.Put()
        Copy-Item -Force -Recurse -Verbose $dir -Destination "B:\" -ea SilentlyContinue
#Dismount
Dismount-VHD $vhdpath

OTHER TIPS

Just use this:

$size = $intval / 1G

PowerShell has a built-in constant (GB) for converting values to gigabytes. Also see here.

Edit: reading your comment, I misunderstood your question it seems. New-vhd requires a size in bytes. If you want 10 GB, you cast the value like this:

$size = [bigint] 10GB

What's unclear in your question is this: "What I need is the variable $size to be somehow converted to a Uint64 whilst retaining the trailing GB".

Little late, but I am just working on this same issue. here is what I found works.

#Get the size of the folder
$FolderSize = (Get-ChildItem $ExportFolder -recurse | Measure-Object -property length -sum)
#Round it and convert it to GBs
[uint64]$Size = "{0:N0}" -f ($FolderSize.sum / 1GB)
#Add 1GB to make sure there is enough space
$Size = ($Size * 1GB) + 1GB
#Create the VHD
New-VHD -Path $VHDXFile -Dynamic -SizeBytes $Size

hope it helps someone out there

This is how I solved this issue as I'm using config files for server builds:

# Get a string of the desired size (#KB, #MB, #GB, etc...)
$size_as_string = "4GB"

# Force PowerShell to evaluate the string
$size_as_bytes = Invoke-Expression $size_as_string

Write-Host "The string '$size_as_string' converts to '$size_as_bytes' bytes"
Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top