5

I have a Windows 2008R2 server that's reporting the following error:

The file system structure on the disk is corrupt and unusable. Please run the chkdsk utility on the volume \Device\HarddiskVolume2.

Using Powershell and WMI how do I identify which volume this is when querying Win32_Volume.

For example if I do:

Get-WmiObject Win32_Volume

I get a list of all the volumes on the server, however none of the Win32_Volume class properties use (what appears be) this "friendly" name - \Device\HarddiskVolume2. I can see there's a DeviceID property which returns a value like this:

DeviceID    : \\?\Volume{4bc3df2a-65c7-11e0-9c33-806e6f6e6963}\

There's also a Name property but that's just the drive letter assigned to the volume. None of the other properties have a value remotely resembling what is reported in the event log.

I know I could parse the output from fltmc volumes or DISKPART to get this information, but there must be a way to obtain this using WMI in a PowerShell script.

I have also looked at the Win32_DiskDrive, Win32_DiskPartition and Win32_LogicalDisk classes but there is no mention of property values resembling \Device\HarddiskVolume2.

2 Answers 2

3

Take a look at this code: http://poshcode.org/4768 it seems to do the conversions you need to see what you want, you might be able to tweak it to fit your needs, let me know if you need help with that but I think you can figure out on your own.

function Get-DevicePath
{
<#
.SYNOPSIS

    Returns the device paths for each volume.

    Author: Matthew Graeber (@mattifestation)
    License: BSD 3-Clause

.DESCRIPTION

    Get-DevicePath returns the corresponding device path for each drive letter. This is useful for converting device paths to drive letters.

.EXAMPLE

    Get-DevicePath

    DevicePath              DriveLetter
    ----------              -----------
    \Device\HarddiskVolume2 D:
    \Device\HarddiskVolume4 C:

.OUTPUTS

    PSObject[]

    For each mount point, a PSObject is returned representing the drive letter and device path.
#>

    # Utilize P/Invoke in order to call QueryDosDevice. I prefer using 
    # reflection over Add-Type since it doesn't require compiling C# code.
    $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
        }
    }
}
3
  • Messy as hell, but it works
    – Ryan Ries
    Feb 2, 2014 at 19:07
  • Indeed, but it does work a treat. Thanks.
    – Kev
    Feb 2, 2014 at 23:18
  • Glad to help Kev, I wish there was a more elegant way to do it but at least with this function, you can drop it into your code and get the results. Feb 3, 2014 at 5:28
0

Not sure if this is the kind of answer you are looking for, but does not look like this data is listed very well in windows at all from what I can see from the command line. I tried to pull the data out of diskpart to show the information, but did not list the device name. On a side note, looks like more disk commands have been added to 2012 like get-volume, get-disk, and get-physicaldisk but that does not help you with 2008.

A few 3rd party utilities will do it

  1. http://www.chrysocome.net/dd just need to run "dd --list"
  2. http://nirsoft.net/utils/drive_letter_view.html

Both utilities have command line options so should be able to use them with powershell scripts.

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .