13

I've tried Diskpart commands like "list" "volume" (no it's not that at all), "disk" and "partition"; but it still don't work.

\Device\Harddiskvolume0 seems to not be used, since \Device\Harddiskvolume1 means the first Windows' partition (aka "System Reserved") and \Device\Harddiskvolume2 is for C:.

So the question is: How to list every \Device\Harddiskvolume in Windows' 7 installation disk (for BCD editing) ?

11

I adapted @merle's answer by using the approach documented on MSDN.

It shows drives:

  • without drive letters
  • mounted to a folder
  • with drive letters

Sample output:

DriveLetter                    DevicePath               VolumeName                                       
-----------                    ----------               ----------                                       
                               \Device\HarddiskVolume5  \\?\Volume{a2b4c6d8-0000-0000-00000100000000000}\
E:\                            \Device\HarddiskVolume9  \\?\Volume{a2b4c6d8-1234-1234-1234-123456789abc}\
C:\Mounted\My-Folder-Mount\    \Device\HarddiskVolume13 \\?\Volume{a2b4c6d8-1234-1234-1234-123456789abc}\

PowerShell script:

$signature = @'
[DllImport("kernel32.dll", SetLastError=true)]
[return: MarshalAs(UnmanagedType.Bool)]
public static extern bool GetVolumePathNamesForVolumeNameW([MarshalAs(UnmanagedType.LPWStr)] string lpszVolumeName,
        [MarshalAs(UnmanagedType.LPWStr)] [Out] StringBuilder lpszVolumeNamePaths, uint cchBuferLength, 
        ref UInt32 lpcchReturnLength);

[DllImport("kernel32.dll", SetLastError = true)]
public static extern IntPtr FindFirstVolume([Out] StringBuilder lpszVolumeName,
   uint cchBufferLength);

[DllImport("kernel32.dll", SetLastError = true)]
public static extern bool FindNextVolume(IntPtr hFindVolume, [Out] StringBuilder lpszVolumeName, uint cchBufferLength);

[DllImport("kernel32.dll", SetLastError = true)]
public static extern uint QueryDosDevice(string lpDeviceName, StringBuilder lpTargetPath, int ucchMax);

'@;
Add-Type -MemberDefinition $signature -Name Win32Utils -Namespace PInvoke -Using PInvoke,System.Text;

[UInt32] $lpcchReturnLength = 0;
[UInt32] $Max = 65535
$sbVolumeName = New-Object System.Text.StringBuilder($Max, $Max)
$sbPathName = New-Object System.Text.StringBuilder($Max, $Max)
$sbMountPoint = New-Object System.Text.StringBuilder($Max, $Max)
[IntPtr] $volumeHandle = [PInvoke.Win32Utils]::FindFirstVolume($sbVolumeName, $Max)
do {
    $volume = $sbVolumeName.toString()
    $unused = [PInvoke.Win32Utils]::GetVolumePathNamesForVolumeNameW($volume, $sbMountPoint, $Max, [Ref] $lpcchReturnLength);
    $ReturnLength = [PInvoke.Win32Utils]::QueryDosDevice($volume.Substring(4, $volume.Length - 1 - 4), $sbPathName, [UInt32] $Max);
    if ($ReturnLength) {
           $DriveMapping = @{
               DriveLetter = $sbMountPoint.toString()
               VolumeName = $volume
               DevicePath = $sbPathName.ToString()
           }

           Write-Output (New-Object PSObject -Property $DriveMapping)
       }
       else {
           Write-Output "No mountpoint found for: " + $volume
       } 
} while ([PInvoke.Win32Utils]::FindNextVolume([IntPtr] $volumeHandle, $sbVolumeName, $Max));
1
  • 2
    Nice! A few other useful outputs to add might be the FileSystemLabel (aka FriendlyName), Size, and perhaps the corresponding disk and partition numbers. For my hacky one-off purposes, I just tacked these two lines on to the end of your script, so I could manually match the Volume GUIDs. Get-Volume | Select DriveLetter, FileSystemLabel, FileSystemType, Size, Path | Format-Table -Autosize and with a new line Get-Partition | Select DiskNumber, PartitionNumber, AccessPaths, Size | Sort-Object -Property DiskNumber, PartitionNumber | Format-Table -Autosize – Ryan Feeley Apr 29 '20 at 22:23
9

Found a powershell script that lists the mounted volumes:

# Biuild System Assembly in order to call Kernel32:QueryDosDevice. 
   $DynAssembly = New-Object System.Reflection.AssemblyName('SysUtils')
   $AssemblyBuilder = [AppDomain]::CurrentDomain.DefineDynamicAssembly($DynAssembly, [Reflection.Emit.AssemblyBuilderAccess]::Run)
   $ModuleBuilder = $AssemblyBuilder.DefineDynamicModule('SysUtils', $False)

   # Define [Kernel32]::QueryDosDevice method
   $TypeBuilder = $ModuleBuilder.DefineType('Kernel32', 'Public, Class')
   $PInvokeMethod = $TypeBuilder.DefinePInvokeMethod('QueryDosDevice', 'kernel32.dll', ([Reflection.MethodAttributes]::Public -bor [Reflection.MethodAttributes]::Static), [Reflection.CallingConventions]::Standard, [UInt32], [Type[]]@([String], [Text.StringBuilder], [UInt32]), [Runtime.InteropServices.CallingConvention]::Winapi, [Runtime.InteropServices.CharSet]::Auto)
   $DllImportConstructor = [Runtime.InteropServices.DllImportAttribute].GetConstructor(@([String]))
   $SetLastError = [Runtime.InteropServices.DllImportAttribute].GetField('SetLastError')
   $SetLastErrorCustomAttribute = New-Object Reflection.Emit.CustomAttributeBuilder($DllImportConstructor, @('kernel32.dll'), [Reflection.FieldInfo[]]@($SetLastError), @($true))
   $PInvokeMethod.SetCustomAttribute($SetLastErrorCustomAttribute)
   $Kernel32 = $TypeBuilder.CreateType()

   $Max = 65536
   $StringBuilder = New-Object System.Text.StringBuilder($Max)

   Get-WmiObject Win32_Volume | ? { $_.DriveLetter } | % {
       $ReturnLength = $Kernel32::QueryDosDevice($_.DriveLetter, $StringBuilder, $Max)

       if ($ReturnLength)
       {
           $DriveMapping = @{
               DriveLetter = $_.DriveLetter
               DevicePath = $StringBuilder.ToString()
           }

           New-Object PSObject -Property $DriveMapping
       }
   }

Source: http://www.morgantechspace.com/2014/11/Get-Volume-Path-from-Drive-Name-using-Powershell.html

Output looks like this:

DevicePath               DriveLetter
----------               -----------
\Device\HarddiskVolume2  F:         
\Device\HarddiskVolume7  J:         
\Device\HarddiskVolume10 D:         
\Device\HarddiskVolume12 E:         
\Device\HarddiskVolume5  C:    
2
  • 1
    Unfortunately, this does not list the volumes that aren't mounted under a drive letter. – phant0m Feb 1 '19 at 15:07
  • Here is my adapted script that shows all drives, no matter whether folder mounted or no drive letter at all: superuser.com/a/1401025/59487 – phant0m Dec 2 '19 at 11:06
5

The easiest way without installing anything and tinkering with Powershell scripts might be System Information Viewer a portable Windows application. This app is great because it provides nearly every information about your machine / hardware. It not only offers a read out of hard drive related data rather nearly everything about your device can be found. Moreover it's very lightweight but TBH a bit confusing structured.

Finally, how do you find drive information? Under Volumes ▼ there is the option Volume List that will give you an overview of all \Device\HarddiskvolumeXX present on your computer. Additionally you get drive letter and GUID of your partitions.

To list all \Device\HarddiskVolumeXX including those that are not mounted under any drive letter per physical driver together with the disk number (like seen in Windows Disk Management). Open the Volumes ▼ dropdown and choose Disk Mapping.

I also want to highlight the option Drives which displays \.\PhysicalDriveXX, path, unit and controller IDs. The listing under Drive Mapping might also be quite useful.

2
  • @phant0m I took your proposed edit and integrated it to some degree into the post even as it was rejected by the mods. I find the information added useful, however I kept the original structuring and just added new paragraph instead. – thex Feb 5 '19 at 11:27
  • @phant0m "This edit was intended to address the author of the post and makes no sense as an edit. It should have been written as a comment or an answer." – thex Mar 23 '19 at 10:30
4

The reason I couldn't get things done is that HarddiskVolume doesn't reflect Diskpart volumes -which only lists every Windows readable volumes-.

In fact, it works with every partitions available on the disk -even the non-Windows ones-, by order they appear like in Linux's Gparted.

E.g, if you have an sda4 before sda3, this latter will show as is -sda4 then sda3- (HarddiskVolume4 then HarddiskVolume3).

So, it means that HarddiskVolume0 mainly don't exist in BCD.

The commands that helped me to understand that are:

mountvol /L

bootsect /nt60 all /force   ->   Be careful with that one !!!

These links also helped me:

Finally, if you have a spare Windows, just run DriveLetterView to see how Windows works with HarddiskVolume.

Note: The HarddiskVolume is a WMI/COM notation

1
  • If you can install 3rd party tools, DriveLetterView from the venerable Nirsoft, as mentioned here, is by far the easiest, in this humble tech's opinion. Gives you disk numbers and volume numbers, volume drive letters, and everything else (vendor, disk name, volume name, disk space, etc) all in one nice easy view, saveable to disk. – john v kumpf Dec 23 '20 at 4:17
2

How do I list every Harddiskvolume in Windows?

This can be done using diskpart.

Solution 1:

  1. Run diskpart.

  2. Type list volume to list all of the attached disk volumes

  3. Type exit

Example output:

F:\test>diskpart

Microsoft DiskPart version 6.1.7601
Copyright (C) 1999-2008 Microsoft Corporation.
On computer: HAL

DISKPART> list volume

  Volume ###  Ltr  Label        Fs     Type        Size     Status     Info
  ----------  ---  -----------  -----  ----------  -------  ---------  --------
  Volume 0     D                       DVD-ROM         0 B  No Media
  Volume 1         System Rese  NTFS   Partition    100 MB  Healthy    System
  Volume 2     C                NTFS   Partition    449 GB  Healthy    Boot
  Volume 3         Recovery     NTFS   Partition     16 GB  Healthy    Hidden
  Volume 4     E   SANDISK      FAT32  Removable     59 GB  Healthy
  Volume 5     F   Expansion    NTFS   Partition   2794 GB  Healthy

DISKPART> exit

Leaving DiskPart...

F:\test>

Solution 2:

  1. Run diskpart.

  2. Type list disk to list all of the attached disks.

  3. Type select disk # where # is the number of the disk.

  4. Type detail disk

  5. Repeat steps 3 and 4 for each disk.

  6. Type exit

The example output below shows that I currently have 3 disks with 5 volumes.

Example output:

F:\test>diskpart

Microsoft DiskPart version 6.1.7601
Copyright (C) 1999-2008 Microsoft Corporation.
On computer: HAL

DISKPART> list disk

  Disk ###  Status         Size     Free     Dyn  Gpt
  --------  -------------  -------  -------  ---  ---
  Disk 0    Online          465 GB      0 B
  Disk 1    Online           59 GB      0 B
  Disk 2    Online         2794 GB  7168 KB

DISKPART> select disk 0

Disk 0 is now the selected disk.

DISKPART> detail disk

WDC WD5000LPVX-08V0TT5
Disk ID: D831FAA5
Type   : ATA
Status : Online
Path   : 0
Target : 0
LUN ID : 0
Location Path : PCIROOT(0)#ATA(C00T00L00)
Current Read-only State : No
Read-only  : No
Boot Disk  : Yes
Pagefile Disk  : Yes
Hibernation File Disk  : No
Crashdump Disk  : Yes
Clustered Disk  : No

  Volume ###  Ltr  Label        Fs     Type        Size     Status     Info
  ----------  ---  -----------  -----  ----------  -------  ---------  --------
  Volume 1         System Rese  NTFS   Partition    100 MB  Healthy    System
  Volume 2     C                NTFS   Partition    449 GB  Healthy    Boot
  Volume 3         Recovery     NTFS   Partition     16 GB  Healthy    Hidden

DISKPART> select disk 1

Disk 1 is now the selected disk.

DISKPART> detail disk

SanDisk Cruzer USB Device
Disk ID: 00000000
Type   : USB
Status : Online
Path   : 0
Target : 0
LUN ID : 0
Location Path : UNAVAILABLE
Current Read-only State : No
Read-only  : No
Boot Disk  : No
Pagefile Disk  : No
Hibernation File Disk  : No
Crashdump Disk  : No
Clustered Disk  : No

  Volume ###  Ltr  Label        Fs     Type        Size     Status     Info
  ----------  ---  -----------  -----  ----------  -------  ---------  --------
  Volume 4     E   SANDISK      FAT32  Removable     59 GB  Healthy

DISKPART> select disk 2

Disk 2 is now the selected disk.

DISKPART> detail disk

Seagate Expansion Desk USB Device
Disk ID: 75447009
Type   : USB
Status : Online
Path   : 0
Target : 0
LUN ID : 0
Location Path : UNAVAILABLE
Current Read-only State : No
Read-only  : No
Boot Disk  : No
Pagefile Disk  : No
Hibernation File Disk  : No
Crashdump Disk  : No
Clustered Disk  : No

  Volume ###  Ltr  Label        Fs     Type        Size     Status     Info
  ----------  ---  -----------  -----  ----------  -------  ---------  --------
  Volume 5     F   Expansion    NTFS   Partition   2794 GB  Healthy

DISKPART> exit

Leaving DiskPart...

F:\test>

Further Reading

4
  • 4
    Thanks for the detailed reply, but this still doesn't work since it has depsite correctly showing up the correct number of Windows' readable volumes from the correct disk; but didn't gave me the \Device\HarddiskVolume list. Is there any way to completely list the \Device tree from Windows' 7 installation disk ? – X.LINK Mar 28 '16 at 14:50
  • It's the same thing named differently. Volume 0 == \Device\Harddiskvolume0, Volume 1 == \Device\Harddiskvolume1, etc – DavidPostill Mar 28 '16 at 14:59
  • 2
    I've found the solution. In fact, HarddiskVolume doesn't reflect the detected Windows' partitions, but every partitions (even non-windows) that are in the disk. – X.LINK Mar 28 '16 at 17:40
  • 8
    @DavidPostill Unfortunately the numbers shown by these diskpart commands do not necessarily match up with device numbers. For instance, in my system the first NTFS volume on Disk 0 is Volume 7 and \\?\Device\HarddiskVolume4 – rakslice Mar 25 '17 at 1:10
0

An easier way to do it is as written below. I've also customized a couple of the columns.

Please run the below in PowerShell:

Get-CimInstance win32_volume -ComputerName "Enter Your Computer Name, or Multiple Computer Names" | select @{n="ComputerName";e={$_.PSComputerName}},DriveLetter,@{n="Capacity(GB)";e={$_.Capacity / 1gb -as [int]}},@{n="Free(GB)";e={$_.FreeSpace / 1gb -as [int]}} | ft -AutoSize
1
  • This is for PowerShell v3 only, user specified for Windows 7 which doesn't come with v3 by default. – JasonXA Mar 29 '19 at 4:38
-2

If you want just to find out where your system BCD store is take a look at \REGISTRY\MACHINE\BCD00000000 value in HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Control\hivelist registry key. Yes, its location can differ from \Device\HardDiskVolume1 even if it is on the 1st partition of the 1st physical disk.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.