How to Programmatically Retrieve Physical Path of Mounted VHD Files in Windows Server 2008 R2


4 views

When managing multiple virtual hard disks (VHDs) on Windows Server 2008 R2, administrators often need to determine the physical storage location of mounted VHD files. This becomes particularly important when:

  • Performing system migrations
  • Troubleshooting storage issues
  • Implementing backup strategies
  • Auditing storage allocations

While Windows doesn't provide a direct GUI method to view mounted VHD paths, we can use these approaches:

Using DiskPart Utility

The command-line disk partitioning tool can reveal VHD information:

diskpart
list disk
select disk X (where X is your VHD disk number)
detail disk

PowerShell Method

For servers with PowerShell 2.0 or later, this script extracts VHD paths:

Get-WmiObject -Query "SELECT * FROM Win32_DiskDrive" | 
Where-Object { $_.MediaType -eq 'External hard disk media' } | 
Select-Object DeviceID, Caption, Size, MediaType

For developers needing to integrate this functionality into applications, consider these API-based solutions:

WMI Query Example

strComputer = "."
Set objWMIService = GetObject("winmgmts:\\" & strComputer & "\root\cimv2")
Set colItems = objWMIService.ExecQuery("Select * from Win32_DiskDrive")

For Each objItem in colItems
    If objItem.MediaType = "External hard disk media" Then
        WScript.Echo "Device ID: " & objItem.DeviceID
        WScript.Echo "VHD Path: " & objItem.Caption
    End If
Next

C# .NET Implementation

For .NET applications, use the Windows API Code Pack:

using Microsoft.WindowsAPICodePack.Shell;
using Microsoft.WindowsAPICodePack.Shell.PropertySystem;

public static string GetVhdPath(string driveLetter)
{
    ShellObject shellObj = ShellObject.FromParsingName(driveLetter);
    string path = shellObj.Properties.System.Volume.FileSystem.GetValue().ToString();
    return path;
}

The Windows registry stores VHD mount information at:

HKEY_LOCAL_MACHINE\SYSTEM\MountedDevices

Look for values containing "VhdMount" in their data for mounted VHD references.

When VHDs are stored on network shares, additional steps may be required:

  • Check SMB client connections (net use)
  • Review DFS mappings if applicable
  • Inspect iSCSI initiator configuration

If the above methods don't yield results:

  1. Verify you have administrative privileges
  2. Check if the VHD was mounted using differencing disks
  3. Consider third-party tools like Sysinternals DiskView
  4. Review Hyper-V configuration if applicable

When working with virtual hard disks (VHDs) in Windows Server environments, administrators often need to trace back mounted VHDs to their physical storage locations. This becomes particularly important when managing multiple VHDs or troubleshooting storage-related issues.

Here are several reliable approaches to find this information:

1. PowerShell with WMI

The most robust method uses Windows Management Instrumentation (WMI):

Get-WmiObject -Namespace "root\virtualization" -Query "SELECT * FROM Msvm_ComputerSystem" | 
ForEach-Object {
    $vm = $_
    Get-WmiObject -Namespace "root\virtualization" -Query "ASSOCIATORS OF {$vm} WHERE ResultClass = Msvm_VirtualSystemSettingData" |
    ForEach-Object {
        Get-WmiObject -Namespace "root\virtualization" -Query "ASSOCIATORS OF {$($_.__PATH)} WHERE ResultClass = Msvm_StorageAllocationSettingData" |
        Where-Object { $_.HostResource -match "\.vhd" } |
        Select-Object @{Name="VMName";Expression={$vm.ElementName}},
                      @{Name="VHDPath";Expression={$_.HostResource}}
    }
}

2. DiskPart Utility

For a quick CLI solution:

diskpart
list volume
select volume X (where X is your mounted VHD volume number)
detail volume

3. Registry Inspection

The Windows Registry stores mount point information at:

HKEY_LOCAL_MACHINE\SYSTEM\MountedDevices

Let's examine a real-world scenario where we have two mounted VHDs but only know the location of one. Here's how to use PowerShell to identify both:

$vhdInfo = Get-WmiObject -Namespace "root\virtualization" -Class Msvm_StorageAllocationSettingData | 
           Where-Object { $_.HostResource -match "\.vhd$" } |
           Select-Object HostResource

foreach ($vhd in $vhdInfo) {
    $path = $vhd.HostResource -replace '\\\\\?\\',''
    Write-Host "VHD Location: $path"
}

When VHDs are stored on network shares, you might need additional steps:

$mountedVHDs = Get-WmiObject -Class Win32_Volume | 
               Where-Object { $_.DriveType -eq 5 } |
               Select-Object Name, DeviceID

foreach ($vhd in $mountedVHDs) {
    if ($vhd.DeviceID -match "VHD") {
        $uncPath = Convert-Path -Path $vhd.Name
        Write-Host "Network VHD Path: $uncPath"
    }
}
  • Run PowerShell as Administrator for full access
  • Check Windows Event Logs for mount operations (Event ID 20499)
  • Verify Hyper-V integration services are up-to-date
  • For clustered environments, check CSV paths