List every \Device\Harddiskvolume.?
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));
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:
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.