Powershell: Initialise and mount VHD disks
Using Powershell and VBoxManage (VirtualBox), I can create and mount a VHD disk, as follows:
$vhdpath="c:\myvhd.vhd"
vboxmanage createmedium disk --filename $vhdpath --sizebyte 200 --format VHD --variant Fixed
$vhd = Mount-DiskImage -PassThru $vhdpath -StorageType VHD
if(-not $vhd) {
Write-Host "Error mounting VHD"
exit
}
$vhd=Get-DiskImage -ImagePath $vhd.ImagePath
Initialize-Disk -Number $vhd.Number -PartitionStyle MBR
$partition = New-Partition -AssignDriveLetter -UseMaximumSize -DiskNumber $vhd.Number
$volume = Format-Volume -FileSystem FAT32 -Confirm:$false -Force -Partition $partition
Of course it is possible to replace vboxmanage ... with Hyper-V equivalent commands.
Two questions:
When the VHD disk is visible to PS, so is to the OS and, before the PS script formats it, an annoying Windows pop-up appears proposing to format the disk. How can I get rid of it?
In general, it is possible to mount a VHD disk as a removable disk. Is it possible to do so with PS too?
I am primarily (but not necessarily) looking for commands that do not require Hyper-V being installed.
Related
I am building some servers using Terraform and on these servers, I am assigning multiple volumes, for example:
F:\ 100GB
G:\ 50GB
H:\ 200GB
When the server is built, I see all the volumes in diskmgmt but all uninitialized so I have created a Cloudinit script with the following as a starter, which initialises the disks and is all good
Get-Disk | Where-Object {$_.PartitionStyle -eq 'Raw'} | Initialize-Disk -PartitionStyle MBR
If I then run this powershell, it formats the disks and assigns the drive letter
New-Partition -DiskNumber 1 -DriveLetter 'F' -UseMaximumSize | Format-Volume -FileSystem NTFS -NewFileSystemLabel "Data F" -Confirm:$false
New-Partition -DiskNumber 2 -DriveLetter 'G' -UseMaximumSize | Format-Volume -FileSystem NTFS -NewFileSystemLabel "Data G" -Confirm:$false
New-Partition -DiskNumber 3 -DriveLetter 'H' -UseMaximumSize | Format-Volume -FileSystem NTFS -NewFileSystemLabel "Data H" -Confirm:$false
The issue I have is that every server build assigns a different Disk number against a volume. So the first build might have this, in which case my drive letters and volumes are all good
Disk 1 - 100GB
Disk 2 - 50GB
Disk 3 - 200GB
The next build would have these disk numbers assigned which then means the drive letters and names are incorrect
Disk 1 - 50GB
Disk 2 - 200GB
Disk 3 - 100GB
I think I need to have the Powershell with some logic to do something like
Get-Disk | Where-Object {$_.'Total Size' -eq '100 GB'} | New-Partition -DriveLetter 'F' -UseMaximumSize | Format-Volume -FileSystem NTFS -NewFileSystemLabel "Data F" -Confirm:$false
I run this but nothing happens, no error, just seems to run and suggest it may have done something but hasn't. I think the issue might be with my rookie Powershell.
Any tips ?
Thanks
I have a dps script that does this
create vdisk file="C:\Image.vhd" maximum=10000 type=expandable
attach vdisk
create partition primary
format fs=ntfs quick
rescan
assign letter=I
How can I do this in PS 5.1?
You would have to install Hyper-V and the associated PowerShell Module and then you could create the disk:
New-VHD -Path "C:\Image.vhd" -Dynamic -SizeBytes 10485760000
Mount, or attach, the disk then initialize it (assuming there is only one extra disk, if there are more than one disk you'd need to get the number using get-disk).
Mount-VHD -Path "C:\Image.vhd"
Initialize-Disk -Number 1 -PartitionStyle GPT
Then create the partition, set the drive letter and quickly format with NTFS
New-Partition -DiskNumber 1 -DriveLetter I | Format-Volume -FileSystem NTFS -Quick
normally to take a disk offline I use the windows disk partition manager. now i would need to do it with a power shell using the drive letter.
I tried with the command:
Set-Partition -DriveLetter E -IsOffline $True
i get this error from powershell:
Set-Partition : The volume still has access path to it.
Any suggestions?
I solved it like this:
set-disk (get-partition -DriveLetter E | get-disk | select number -ExpandProperty number) -isOffline $true
I am trying to automate someone taking a ISO and making that into a bootable USB. I need help with that last command in the script which is xcopy. How can I copy all the files from the user imputed $ISO to the USB drive X:? I am having issues using "$ISO" and ":" in a path. The last command needs work cause currently it errors out.
Write-Host "Please mount your ISO and insert your USB stick"
$ISO = Read-Host -Prompt 'Please enter your mounted ISO drive letter'
Write-Host "Your mounted drive letter is seleted as $ISO"
Get-Disk
$USBDisk = Read-Host -Prompt 'Please enter your USB Disk Number from above'
Get-Disk $USBDisk | Clear-Disk -RemoveData
New-Partition -DiskNumber $USBDisk -Size 30000 MB -IsActive -DriveLetter X | Format-Volume -FileSystem FAT32 -NewFileSystemLabel Win10
xcopy $ISO:\* X:\ /S
Try:
xcopy ${ISO}:\* X:\ /S
This is an alternate method of referencing a variable and is useful when you need a trailing colon and don't want to confuse the parser with looking for a variable namespace.
I'm having a problem when unmounting an image:
Dismount-WindowsImage : The specified image is invalid.
Unmount the image or clean up the Vhd and then try again.
A day ago, I broke something, and the script stopped working. Using a script I importing a virtual machine. I mount the image, add the data to the image, unmount it and run. Error occurs when unmounting:
#PS C:\build-grom-git> .\_start-VM.ps1 -name_of_image "w7" -installer "TGTeDataAVCS+ADPonly" -path_to_vmcx "C:\imageOS\win7x64\w7.vhdx\Virtual Machines\47A23F4B-A8EB-4AAC-A745-4AC28FB66FAE.vmcx"
Param(
[Parameter(Mandatory=$True,Position=1)]
[string]$name_of_image, # path to image of virtual machine
[Parameter(Mandatory=$True,Position=2)]
[string]$installer, # name of the folder with install-file
[Parameter(Mandatory=$True,Position=3)]
[string]$path_to_vmcx # path to vmcx file (file for import VM)
)
# static variables
$vhdx_path="Temp\vhdx" # path to image of virtual machine
$mount_dir="Temp\mount_folder" # folder of mounting image
# Run As Administrator
if (!([Security.Principal.WindowsPrincipal][Security.Principal.WindowsIdentity]::GetCurrent()).IsInRole([Security.Principal.WindowsBuiltInRole] "Administrator")) { Start-Process powershell.exe "-NoProfile -ExecutionPolicy Bypass -File `"$PSCommandPath`"" -Verb RunAs; exit }
# 1. Creating folder
# create temporary folders in local machine
New-Item -ItemType directory -Path $vhdx_path
# 2. Work with vhdx files
#copying image to temporary folder in local machine
Import-VM -Path "$path_to_vmcx" -Copy -VhdDestinationPath "Temp\vhdx" -VirtualMachinePath "Temp\vhdx"
# mounting image
MD $mount_dir -Force
Mount-WindowsImage -ImagePath "$vhdx_path\$name_of_image.vhdx" -Path $mount_dir -Index 1
# copying files in the image (virtual machine)
Copy-Item -Path "C:\keys" -Destination "$mount_dir\keys" -Recurse -force # keys for TGTe-Data
Copy-Item -Path "Temp\$installer" -Destination "$mount_dir\Temp\$installer" -Recurse -force # installer for TGTe-Data
Copy-Item -Path "Temp\DB" -Destination "$mount_dir\DB" -Recurse -force # copy database
# unmount image
Dismount-WindowsImage -Path $mount_dir -Save
RD $mount_dir -Force
#3. Run VM
Start-VM $name_of_image
# enough time to run
Start-Sleep -s 30
How can I correct the error with unmount?
I could not fix it, but I found another solution. Sorry, but i can't correctly added my code. Stack has very stupid design.
# mount the vhdx image
$MountedDisk = Mount-VHD -Path "Virtual Hard Disks\windows7x64.vhdx" -Passthru
# get count of the disk in image (i have got 2 disk in image: system-disk and work-disk)
$diskNo=$MountedDisk.DiskNumber
# get letters for this disks
$driveLetter=(Get-Disk $diskNo | Get-Partition).DriveLetter
# Creating path to need disk (i need work-disk)
$path_to_mount_vhdx = $driveLetter[1] + ":"
# Copying files into work-disk
Copy-Item -Path "C:\keys" -Destination "$path_to_mount_vhdx\keys" -Recurse -force
# unmount
Dismount-VHD $MountedDisk.Path