How to Programmatically Convert a Folder to a VHD Virtual Disk Image Using Command Line and .NET


9 views

Virtual Hard Disks (VHDs) are essential for virtualization, testing, and deployment scenarios. Converting existing folders to VHD format allows you to:

  • Create portable development environments
  • Package application deployments
  • Maintain file system structure in virtual machines

Windows provides built-in tools for VHD creation through Disk Management and PowerShell:

# PowerShell example (requires admin rights)
New-VHD -Path C:\my.vhd -SizeBytes 10GB -Dynamic
Mount-VHD -Path C:\my.vhd
Initialize-Disk -Number X -PartitionStyle MBR
New-Partition -DiskNumber X -UseMaximumSize -AssignDriveLetter Y
Format-Volume -DriveLetter Y -FileSystem NTFS -Confirm:$false
# Then copy files manually to the new drive

For programmatic control, the Microsoft.VHD.PowerShell module provides extensive capabilities:

using Microsoft.Vhd.PowerShell;
using System.IO;

public void CreateVhdFromFolder(string vhdPath, string sourceFolder, long sizeInGB)
{
    // Create dynamic VHD
    NewVhd -Path vhdPath -SizeBytes (sizeInGB * 1GB) -Dynamic;
    
    // Mount and format
    MountVhd -Path vhdPath;
    var disk = GetDisk -Number (GetVhd -Path vhdPath).DiskNumber;
    InitializeDisk -DiskNumber disk.Number -PartitionStyle MBR;
    var partition = NewPartition -DiskNumber disk.Number -UseMaximumSize -AssignDriveLetter;
    FormatVolume -DriveLetter partition.DriveLetter -FileSystem NTFS;
    
    // Copy files
    var destPath = $"{partition.DriveLetter}:\\";
    DirectoryCopy(sourceFolder, destPath, true);
}

Several open-source utilities simplify this process:

  1. VHDTool: vhdtool create -s 10G -f my.vhd -d c:\my
  2. Disk2vhd: While primarily for physical-to-virtual, can be adapted
  3. WinImage: GUI tool with batch processing capabilities

For production environments, consider these enhancements:

# Compression example
$vhd = Get-VHD -Path "C:\my.vhd"
Optimize-VHD -Path $vhd.Path -Mode Full

# Differential VHD creation
New-VHD -ParentPath "C:\base.vhd" -Path "C:\diff.vhd" -Differencing

Remember to handle error cases and verify disk space before operations. For large folders, consider splitting into multiple VHDs or using compression.


Virtual Hard Disk (VHD) files are useful for creating portable file systems that can be mounted as drives. Converting an existing folder to VHD allows you to:

  • Package application dependencies
  • Create test environments
  • Backup directory structures
  • Share complex file hierarchies

Windows includes built-in tools for VHD creation through DiskPart and PowerShell:

Using DiskPart

diskpart
create vdisk file="C:\my.vhd" maximum=1024 type=expandable
select vdisk file="C:\my.vhd"
attach vdisk
create partition primary
format quick fs=ntfs label="MyVHD"
assign letter=Z
exit

Then copy files using command line:

robocopy C:\my Z:\ /mir

PowerShell Alternative

$folder = "C:\my"
$vhdPath = "C:\my.vhd"
$size = (Get-ChildItem $folder -Recurse | Measure-Object -Property Length -Sum).Sum + 1MB

New-VHD -Path $vhdPath -SizeBytes $size -Dynamic
$disk = Mount-VHD $vhdPath -Passthru
Initialize-Disk -Number $disk.Number -PartitionStyle MBR
$partition = New-Partition -DiskNumber $disk.Number -UseMaximumSize -IsActive
Format-Volume -Partition $partition -FileSystem NTFS -NewFileSystemLabel "MyVHD" -Confirm:$false
$driveLetter = ($partition | Get-Volume).DriveLetter

robocopy $folder "$($driveLetter):\" /mir

For simpler one-line solutions, consider these tools:

WinImage

winimage.exe /convert C:\my /convertto:VHD /output:C:\my.vhd

OSFMount

Provides GUI and command line options for folder-to-VHD conversion.

For programmatic solutions using .NET:

using System;
using System.IO;
using Microsoft.Vhd.PowerShell;

class VhdCreator {
    static void CreateFromFolder(string source, string destination) {
        long size = DirectorySize(new DirectoryInfo(source)) + 1048576; // +1MB buffer
        
        NewVhdCmdlet vhdCreator = new NewVhdCmdlet();
        vhdCreator.Path = destination;
        vhdCreator.SizeBytes = size;
        vhdCreator.Dynamic = true;
        vhdCreator.Execute();
        
        // Mount and copy logic would follow
    }
    
    static long DirectorySize(DirectoryInfo dir) {
        long size = 0;
        foreach (FileInfo fi in dir.GetFiles("*", SearchOption.AllDirectories))
            size += fi.Length;
        return size;
    }
}
  • Always calculate required space with buffer
  • Dynamic VHDs grow as needed while fixed offer better performance
  • Consider compression for large folders
  • NTFS is recommended for Windows compatibility