locked
using diskpart from vb - any API or alternative? and how to get the Disk ID RRS feed

  • Question

  • Hi

    I need to partition a disk from within VB.NET and then copy files to it

    I can run diskpart using Process class and pass it a text file containing my commands - this is no problem

    But how can I retrieve the "ID" of the selected USB drive

    e.g. I can easily list all USB devices and select by drive letter, but I need the "ID" of the drive to do "select disk ?" in disk part

    OR

    Is there some API or alternative way of doing same as diskpart from within VB framework?

    Many thanks


    Darren Rose

    Wednesday, December 27, 2017 9:46 PM

Answers

  • ... but no way to correlate the drive letter (G: in this case) to the above

    If you want to get the Device Number from a Volume letter, you can do it with DeviceIoControl() and IOCTL_STORAGE_GET_DEVICE_NUMBER (string format "\\.\letter:" for CreateFile())

    I just tested it, with the declarations :

    <DllImport("Kernel32.dll", SetLastError:=True, CharSet:=CharSet.Auto)>
    Public Shared Function DeviceIoControl(hDevice As IntPtr,
                                            dwIoControlCode As Integer,
                                            lpInBuffer As IntPtr,
                                            nInBufferSize As Integer,
                                            lpOutBuffer As IntPtr,
                                            nOutBufferSize As Integer,
                                            ByRef lpBytesReturned As Integer,
                                            ByRef lpOverlapped As System.Threading.NativeOverlapped) As Boolean
    End Function
    
    <StructLayout(LayoutKind.Sequential)>
    Public Structure STORAGE_DEVICE_NUMBER
        Public DeviceType As Integer
        Public DeviceNumber As Integer
        Public PartitionNumber As Integer
    End Structure
    
    Public Const IOCTL_STORAGE_GET_DEVICE_NUMBER As Integer = &H2D1080
    
    <DllImport("Kernel32.dll", SetLastError:=True, CharSet:=CharSet.Unicode)>
    Friend Shared Function CreateFile(ByVal lpFileName As String, ByVal dwDesiredAccess As Integer, ByVal dwShareMode As Integer, ByVal lpSECURITY_ATTRIBUTES As IntPtr, ByVal dwCreationDisposition As Integer, ByVal dwFlagsAndAttributes As Integer, ByVal hTemplateFile As IntPtr) As IntPtr
    End Function
    
    Public Const FILE_SHARE_READ As Integer = 1
    Public Const FILE_SHARE_WRITE As Integer = 2
    Public Const FILE_SHARE_DELETE As Integer = 4
    Public Const FILE_ATTRIBUTE_NORMAL As Integer = &H80
    
    Public Const CREATE_NEW As Integer = 1
    Public Const CREATE_ALWAYS As Integer = 2
    Public Const OPEN_EXISTING As Integer = 3
    Public Const OPEN_ALWAYS As Integer = 4
    Public Const TRUNCATE_EXISTING As Integer = 5



    • Edited by Castorix31 Thursday, December 28, 2017 3:49 PM
    • Marked as answer by wingers Saturday, December 30, 2017 12:28 PM
    Thursday, December 28, 2017 12:33 PM
  • This code seems to work fine:-

                Dim logicalDiskId As String = "H:"
                Dim deviceId As String = String.Empty
                Dim query As String = ("ASSOCIATORS OF {Win32_LogicalDisk.DeviceID='" _
                             + (logicalDiskId + "'} WHERE AssocClass = Win32_LogicalDiskToPartition"))
                Dim queryResults = New ManagementObjectSearcher(query)
                Dim partitions = queryResults.Get
                For Each x In partitions
                    query = ("ASSOCIATORS OF {Win32_DiskPartition.DeviceID='" _
                                + (x("DeviceID") + "'} WHERE AssocClass = Win32_DiskDriveToDiskPartition"))
                    queryResults = New ManagementObjectSearcher(query)
                    Dim drives = queryResults.Get
                    For Each drive In drives
                        deviceId = drive("DeviceID").ToString ' or use Index to just show number
                    Next
                Next
                Console.WriteLine(deviceId)

    Thank you all very much for your help :)

    Happy new year to you all


    Darren Rose

    • Marked as answer by wingers Saturday, December 30, 2017 12:29 PM
    Saturday, December 30, 2017 12:29 PM
  •  @ wingers,  i am getting off here for the night but,  if you explain if it is a Disk or Partition id/index you are after,  or maybe both,  i will see if i can make up an example tomorrow if you don't get or find one by then.  8)


    If you say it can`t be done then i`ll try it

    Thanks IR, much appreciated

    It is a Disk ID/Index I need


    Darren Rose

     Well,  unfortunately,  i don't see any way right off hand to do this without using native methods.  Here is an example i threw together that basically does and uses what Castorix31 was mentioning.  If you don't filter out the hard drive that your OS is installed on it seems to fail getting the info from it unless you do the old right click "Run as administrator".  8)

    Imports System.Runtime.InteropServices
    
    Public Class Form1
        Private Const IOCTL_STORAGE_GET_DEVICE_NUMBER As Integer = &H2D1080
        Private Const OPEN_EXISTING As Integer = &H3
        Private Const GENERIC_READ As Integer = &H80000000
        Private Const FILE_SHARE_READ As Integer = &H1
        Private Const FILE_SHARE_WRITE As Integer = &H2
    
        <DllImport("kernel32.dll", SetLastError:=True)>
        Private Shared Function DeviceIoControl(ByVal hDevice As IntPtr, ByVal dwIoControlCode As Integer, ByVal lpInBuffer As IntPtr, ByVal nInBufferSize As Integer, ByRef lpOutBuffer As STORAGE_DEVICE_NUMBER, ByVal nOutBufferSize As Integer, ByRef lpBytesReturned As Integer, ByVal lpOverlapped As IntPtr) As <MarshalAs(UnmanagedType.Bool)> Boolean
        End Function
    
        <DllImport("kernel32.dll", EntryPoint:="CreateFileW")>
        Private Shared Function CreateFileW(<MarshalAs(UnmanagedType.LPWStr)> ByVal lpFileName As String, ByVal dwDesiredAccess As Integer, ByVal dwShareMode As Integer, ByVal lpSecurityAttributes As IntPtr, ByVal dwCreationDisposition As Integer, ByVal dwFlagsAndAttributes As Integer, ByVal hTemplateFile As IntPtr) As IntPtr
        End Function
    
        <DllImport("kernel32.dll")> Private Shared Function CloseHandle(ByVal hObject As IntPtr) As <MarshalAs(UnmanagedType.Bool)> Boolean
        End Function
    
        <StructLayout(LayoutKind.Sequential)>
        Private Structure STORAGE_DEVICE_NUMBER
            Public DeviceType As Integer
            Public DeviceNumber As Integer
            Public PartitionNumber As Integer
        End Structure
    
        Private sdn As New STORAGE_DEVICE_NUMBER
    
        Private Sub Button1_Click(sender As Object, e As EventArgs) Handles Button1.Click
            For Each di As IO.DriveInfo In IO.DriveInfo.GetDrives
                If di.IsReady Then
                    Dim sdn As STORAGE_DEVICE_NUMBER = GetDriveNumber(di.Name)
                    If Not sdn.DeviceNumber = -1 Then
                        Dim sb As New System.Text.StringBuilder
                        sb.AppendLine("Drive Letter: " & di.Name)
                        sb.AppendLine("Drive Type: " & di.DriveType.ToString)
                        sb.AppendLine("Drive #: " & sdn.DeviceNumber.ToString)
                        sb.AppendLine("Partition #: " & sdn.PartitionNumber.ToString)
                        sb.AppendLine("===========================================")
                        RichTextBox1.AppendText(sb.ToString)
                    End If
                End If
            Next
        End Sub
    
        'must be run by right click "Run as administrator" in order to get info from the drive that the OS is installed on.
        Private Function GetDriveNumber(DrvName As String) As STORAGE_DEVICE_NUMBER
            Dim hDev As IntPtr = CreateFileW("\\.\" & DrvName.Replace("\", ""), GENERIC_READ, FILE_SHARE_READ Or FILE_SHARE_WRITE, IntPtr.Zero, OPEN_EXISTING, 0, IntPtr.Zero)
            If hDev = IntPtr.Zero Then
                MessageBox.Show("Failed to open the device.")
            Else
                Dim btsret As Integer = 0
                If Not DeviceIoControl(hDev, IOCTL_STORAGE_GET_DEVICE_NUMBER, IntPtr.Zero, 0, sdn, Marshal.SizeOf(sdn), btsret, IntPtr.Zero) Then
                    MessageBox.Show("Failed to get device number for: " & DrvName & Environment.NewLine & "WINAPI Error code: 0x" & Marshal.GetLastWin32Error.ToString("X"))
                    sdn.DeviceNumber = -1
                End If
                CloseHandle(hDev)
            End If
            Return sdn
        End Function
    End Class
     

     


    If you say it can`t be done then i`ll try it

    • Edited by IronRazerz Thursday, December 28, 2017 8:30 PM
    • Marked as answer by wingers Saturday, December 30, 2017 12:28 PM
    Thursday, December 28, 2017 8:27 PM
  •  Cool,  i did see a C++ example of using that same method in the Win32_LogicalDiskToPartition class documents the other day but,  did not feel like trying to convert it over to Vb.Net because i was not sure if it did what you needed or not.  8)

     I would consider using some Using Statements to do that so you are sure the ManagementObjectSearcher classes are Disposed.  I threw this function together that i have implemented that and fixed it so it will not show late binding errors for people like me that like keeping Option Strict turned on at all times.  I also made it to return the Id or Index just for the heck of it.

    Imports System.Management

    Public Class Form1
        Private Sub Button1_Click(sender As Object, e As EventArgs) Handles Button1.Click
            MessageBox.Show(GetPhysicalDriveId("E:"))
            MessageBox.Show(GetPhysicalDriveId("E:", True))
        End Sub

        Private Function GetPhysicalDriveId(drvName As String, Optional ReturnIndex As Boolean = False) As String
            Dim devId As String = ""
            Using LogicalDiskQueryResults As New ManagementObjectSearcher("ASSOCIATORS OF {Win32_LogicalDisk.DeviceID='" & (drvName & "'} WHERE AssocClass = Win32_LogicalDiskToPartition"))
                For Each mo As ManagementObject In LogicalDiskQueryResults.Get
                    Using DiskPartitionQueryResults As New ManagementObjectSearcher("ASSOCIATORS OF {Win32_DiskPartition.DeviceID='" & (mo("DeviceID").ToString & "'} WHERE AssocClass = Win32_DiskDriveToDiskPartition"))
                        For Each partition As ManagementObject In DiskPartitionQueryResults.Get
                            devId = partition(If(ReturnIndex, "Index", "DeviceID")).ToString
                        Next
                    End Using
                Next
            End Using
            Return devId
        End Function
    End Class


    If you say it can`t be done then i`ll try it

    • Edited by IronRazerz Saturday, December 30, 2017 6:10 PM
    • Marked as answer by wingers Sunday, December 31, 2017 1:22 AM
    Saturday, December 30, 2017 5:27 PM

All replies

  • Diskpart uses IVdsSwProvider interface

    But in VB, you can use WMI with MSFT_Disk class to enumerate disks

    Wednesday, December 27, 2017 10:26 PM
  • I have looked through all the WMI providers I could find e.g. Win32_DiskDrive, win32_logicaldisk, win32_physicaldisk etc - but they either show drive letter OR device ID / index - NOT both, so hard to correlate the two things - hence asking

    Darren Rose

    Wednesday, December 27, 2017 10:29 PM
  • Hi wingers,

    Would you explain what is "device ID / index"?
    It would be helpful if you provide a sample value of it.

    Regards,

    Ashidacchi


    • Edited by Ashidacchi Thursday, December 28, 2017 2:35 AM
    Thursday, December 28, 2017 2:33 AM
  • Hi wingers,

    Would you explain what is "device ID / index"?
    It would be helpful if you provide a sample value of it.

    Regards,

    Ashidacchi


     When you run diskpart you need to know the Id or in other words, the index of the disk such as (Disk 1,  Disk 2, ....) so you can Select the correct disk drive.  Then you need to use the correct Id or Index of the Partition such as (Partition 1,  Partition 2, ....) so you can Select that.  However,  it is not entirely clear if wingers wants the Disk id/index or the Partition id/index.

     

     @ wingers,  i am getting off here for the night but,  if you explain if it is a Disk or Partition id/index you are after,  or maybe both,  i will see if i can make up an example tomorrow if you don't get or find one by then.  8)


    If you say it can`t be done then i`ll try it

    • Edited by IronRazerz Thursday, December 28, 2017 3:48 AM
    Thursday, December 28, 2017 3:47 AM
  • As it has been said, MSFT_Disk returns the index

    • Edited by valat Thursday, December 28, 2017 7:45 AM
    Thursday, December 28, 2017 7:45 AM
  • Hi

    See screenshot below showing what I mean

    It is the Disk ID I need, so I can then run Select Disk x


    Darren Rose

    Thursday, December 28, 2017 9:53 AM
  • As it has been said, MSFT_Disk returns the index

    Diskpart uses IVdsSwProvider interface

    But in VB, you can use WMI with MSFT_Disk class to enumerate disks

    Below is result from WMI Explorer for MSFT_Disk

    The drive letter of my USB pen is G: and I am trying to find the ID/INDEX of it

    The result below shows me that drive, but no way of knowing it is drive G: to then get ID/INDEX of it

    Hence original question..

    AdapterSerialNumber:  
    AllocatedSize: 15514730496
    BootFromDisk: False
    BusType: 7
    FirmwareVersion: PMAP
    FriendlyName:  USB DISK 3.0
    Guid: {919d57c4-7888-4c70-a4fc-7bcde6f31d25}
    HealthStatus: 0
    IsBoot: False
    IsClustered: False
    IsHighlyAvailable: False
    IsOffline: False
    IsReadOnly: False
    IsScaleOut: False
    IsSystem: False
    LargestFreeExtent: 0
    Location: Integrated : Adapter 0 : Port 0
    LogicalSectorSize: 512
    Manufacturer:         
    Model: USB DISK 3.0    
    Number: 3
    NumberOfPartitions: 1
    ObjectId: {1}\\XPSDESKTOP\root/Microsoft/Windows/Storage/Providers_v2\WSP_Disk.ObjectId="{be8523b9-df33-11e6-8848-806e6f6e6963}:DI:\\?\usbstor#disk&ven_&prod_usb_disk_3.0&rev_pmap#070b788e976e9241&0#{53f56307-b6bf-11d0-94f2-00a0c91efb8b}"
    OfflineReason: 0
    OperationalStatus: 53264
    PartitionStyle: 2
    PassThroughClass:  
    PassThroughIds:  
    PassThroughNamespace:  
    PassThroughServer:  
    Path: \\?\usbstor#disk&ven_&prod_usb_disk_3.0&rev_pmap#070b788e976e9241&0#{53f56307-b6bf-11d0-94f2-00a0c91efb8b}
    PhysicalSectorSize: 512
    ProvisioningType: 2
    SerialNumber: 097204B17080
    Signature:  
    Size: 15514730496
    UniqueId: USBSTOR\DISK&VEN_&PROD_USB_DISK_3.0&REV_PMAP\070B788E976E9241&0:XPSDESKTOP
    UniqueIdFormat: 0
    


    Darren Rose

    Thursday, December 28, 2017 10:05 AM
  • Code generated by WMI Code Creator

    with FriendlyName and Number for testing =>

     Try
                Dim searcher As New ManagementObjectSearcher(
                        "root\Microsoft\Windows\Storage",
                        "SELECT * FROM MSFT_Disk")
    
                For Each queryObj As ManagementObject In searcher.Get()
    
                    Console.WriteLine("-----------------------------------")
                    Console.WriteLine("MSFT_Disk instance")
                    Console.WriteLine("-----------------------------------")
                    Console.WriteLine("FriendlyName: {0}", queryObj("FriendlyName"))
                    Console.WriteLine("Number: {0}", queryObj("Number"))
                Next
            Catch err As ManagementException
                MessageBox.Show("An error occurred while querying for WMI data: " & err.Message)
            End Try

    Thursday, December 28, 2017 10:06 AM
  • Code generated by WMI Code Creator

    with FriendlyName and Number for testing =>

     Try
                Dim searcher As New ManagementObjectSearcher(
                        "root\Microsoft\Windows\Storage",
                        "SELECT * FROM MSFT_Disk")
    
                For Each queryObj As ManagementObject In searcher.Get()
    
                    Console.WriteLine("-----------------------------------")
                    Console.WriteLine("MSFT_Disk instance")
                    Console.WriteLine("-----------------------------------")
                    Console.WriteLine("FriendlyName: {0}", queryObj("FriendlyName"))
                    Console.WriteLine("Number: {0}", queryObj("Number"))
                Next
            Catch err As ManagementException
                MessageBox.Show("An error occurred while querying for WMI data: " & err.Message)
            End Try


    As my reply above - FriendlyName shows USB Disk 3.0 and Number shows 3 - so yes Number is the ID/Index I need, but no way to correlate the drive letter (G: in this case) to the above

    Darren Rose

    Thursday, December 28, 2017 10:10 AM
  • ... but no way to correlate the drive letter (G: in this case) to the above

    If you want to get the Device Number from a Volume letter, you can do it with DeviceIoControl() and IOCTL_STORAGE_GET_DEVICE_NUMBER (string format "\\.\letter:" for CreateFile())

    I just tested it, with the declarations :

    <DllImport("Kernel32.dll", SetLastError:=True, CharSet:=CharSet.Auto)>
    Public Shared Function DeviceIoControl(hDevice As IntPtr,
                                            dwIoControlCode As Integer,
                                            lpInBuffer As IntPtr,
                                            nInBufferSize As Integer,
                                            lpOutBuffer As IntPtr,
                                            nOutBufferSize As Integer,
                                            ByRef lpBytesReturned As Integer,
                                            ByRef lpOverlapped As System.Threading.NativeOverlapped) As Boolean
    End Function
    
    <StructLayout(LayoutKind.Sequential)>
    Public Structure STORAGE_DEVICE_NUMBER
        Public DeviceType As Integer
        Public DeviceNumber As Integer
        Public PartitionNumber As Integer
    End Structure
    
    Public Const IOCTL_STORAGE_GET_DEVICE_NUMBER As Integer = &H2D1080
    
    <DllImport("Kernel32.dll", SetLastError:=True, CharSet:=CharSet.Unicode)>
    Friend Shared Function CreateFile(ByVal lpFileName As String, ByVal dwDesiredAccess As Integer, ByVal dwShareMode As Integer, ByVal lpSECURITY_ATTRIBUTES As IntPtr, ByVal dwCreationDisposition As Integer, ByVal dwFlagsAndAttributes As Integer, ByVal hTemplateFile As IntPtr) As IntPtr
    End Function
    
    Public Const FILE_SHARE_READ As Integer = 1
    Public Const FILE_SHARE_WRITE As Integer = 2
    Public Const FILE_SHARE_DELETE As Integer = 4
    Public Const FILE_ATTRIBUTE_NORMAL As Integer = &H80
    
    Public Const CREATE_NEW As Integer = 1
    Public Const CREATE_ALWAYS As Integer = 2
    Public Const OPEN_EXISTING As Integer = 3
    Public Const OPEN_ALWAYS As Integer = 4
    Public Const TRUNCATE_EXISTING As Integer = 5



    • Edited by Castorix31 Thursday, December 28, 2017 3:49 PM
    • Marked as answer by wingers Saturday, December 30, 2017 12:28 PM
    Thursday, December 28, 2017 12:33 PM
  •  @ wingers,  i am getting off here for the night but,  if you explain if it is a Disk or Partition id/index you are after,  or maybe both,  i will see if i can make up an example tomorrow if you don't get or find one by then.  8)


    If you say it can`t be done then i`ll try it

    Thanks IR, much appreciated

    It is a Disk ID/Index I need


    Darren Rose

    Thursday, December 28, 2017 8:01 PM
  • @Castorix31

    Thanks for that - would prefer to find a solution that doesn't involve having to use DllImport etc if at all possible, - but will certainly give it a try :)


    Darren Rose

    Thursday, December 28, 2017 8:02 PM
  •  @ wingers,  i am getting off here for the night but,  if you explain if it is a Disk or Partition id/index you are after,  or maybe both,  i will see if i can make up an example tomorrow if you don't get or find one by then.  8)


    If you say it can`t be done then i`ll try it

    Thanks IR, much appreciated

    It is a Disk ID/Index I need


    Darren Rose

     Well,  unfortunately,  i don't see any way right off hand to do this without using native methods.  Here is an example i threw together that basically does and uses what Castorix31 was mentioning.  If you don't filter out the hard drive that your OS is installed on it seems to fail getting the info from it unless you do the old right click "Run as administrator".  8)

    Imports System.Runtime.InteropServices
    
    Public Class Form1
        Private Const IOCTL_STORAGE_GET_DEVICE_NUMBER As Integer = &H2D1080
        Private Const OPEN_EXISTING As Integer = &H3
        Private Const GENERIC_READ As Integer = &H80000000
        Private Const FILE_SHARE_READ As Integer = &H1
        Private Const FILE_SHARE_WRITE As Integer = &H2
    
        <DllImport("kernel32.dll", SetLastError:=True)>
        Private Shared Function DeviceIoControl(ByVal hDevice As IntPtr, ByVal dwIoControlCode As Integer, ByVal lpInBuffer As IntPtr, ByVal nInBufferSize As Integer, ByRef lpOutBuffer As STORAGE_DEVICE_NUMBER, ByVal nOutBufferSize As Integer, ByRef lpBytesReturned As Integer, ByVal lpOverlapped As IntPtr) As <MarshalAs(UnmanagedType.Bool)> Boolean
        End Function
    
        <DllImport("kernel32.dll", EntryPoint:="CreateFileW")>
        Private Shared Function CreateFileW(<MarshalAs(UnmanagedType.LPWStr)> ByVal lpFileName As String, ByVal dwDesiredAccess As Integer, ByVal dwShareMode As Integer, ByVal lpSecurityAttributes As IntPtr, ByVal dwCreationDisposition As Integer, ByVal dwFlagsAndAttributes As Integer, ByVal hTemplateFile As IntPtr) As IntPtr
        End Function
    
        <DllImport("kernel32.dll")> Private Shared Function CloseHandle(ByVal hObject As IntPtr) As <MarshalAs(UnmanagedType.Bool)> Boolean
        End Function
    
        <StructLayout(LayoutKind.Sequential)>
        Private Structure STORAGE_DEVICE_NUMBER
            Public DeviceType As Integer
            Public DeviceNumber As Integer
            Public PartitionNumber As Integer
        End Structure
    
        Private sdn As New STORAGE_DEVICE_NUMBER
    
        Private Sub Button1_Click(sender As Object, e As EventArgs) Handles Button1.Click
            For Each di As IO.DriveInfo In IO.DriveInfo.GetDrives
                If di.IsReady Then
                    Dim sdn As STORAGE_DEVICE_NUMBER = GetDriveNumber(di.Name)
                    If Not sdn.DeviceNumber = -1 Then
                        Dim sb As New System.Text.StringBuilder
                        sb.AppendLine("Drive Letter: " & di.Name)
                        sb.AppendLine("Drive Type: " & di.DriveType.ToString)
                        sb.AppendLine("Drive #: " & sdn.DeviceNumber.ToString)
                        sb.AppendLine("Partition #: " & sdn.PartitionNumber.ToString)
                        sb.AppendLine("===========================================")
                        RichTextBox1.AppendText(sb.ToString)
                    End If
                End If
            Next
        End Sub
    
        'must be run by right click "Run as administrator" in order to get info from the drive that the OS is installed on.
        Private Function GetDriveNumber(DrvName As String) As STORAGE_DEVICE_NUMBER
            Dim hDev As IntPtr = CreateFileW("\\.\" & DrvName.Replace("\", ""), GENERIC_READ, FILE_SHARE_READ Or FILE_SHARE_WRITE, IntPtr.Zero, OPEN_EXISTING, 0, IntPtr.Zero)
            If hDev = IntPtr.Zero Then
                MessageBox.Show("Failed to open the device.")
            Else
                Dim btsret As Integer = 0
                If Not DeviceIoControl(hDev, IOCTL_STORAGE_GET_DEVICE_NUMBER, IntPtr.Zero, 0, sdn, Marshal.SizeOf(sdn), btsret, IntPtr.Zero) Then
                    MessageBox.Show("Failed to get device number for: " & DrvName & Environment.NewLine & "WINAPI Error code: 0x" & Marshal.GetLastWin32Error.ToString("X"))
                    sdn.DeviceNumber = -1
                End If
                CloseHandle(hDev)
            End If
            Return sdn
        End Function
    End Class
     

     


    If you say it can`t be done then i`ll try it

    • Edited by IronRazerz Thursday, December 28, 2017 8:30 PM
    • Marked as answer by wingers Saturday, December 30, 2017 12:28 PM
    Thursday, December 28, 2017 8:27 PM
  • Okay, thanks for having a look for me

    I was wondering if someway of doing it using WMI perhaps - will research some more, but at least this method works if not :)


    Darren Rose

    Thursday, December 28, 2017 8:56 PM
  • e.g. these vbscripts can match drive letters to drive number, so perhaps this sort of method may work in VB.net as well

    https://msdn.microsoft.com/en-us/library/aa394592(v=vs.85).aspx   - bottom of page

    https://blogs.technet.microsoft.com/heyscriptingguy/2005/05/23/how-can-i-correlate-logical-drives-and-physical-disks/


    Darren Rose

    Thursday, December 28, 2017 9:05 PM
  • update:

    found a C# sample which looks like it might do what I want

    https://vbvyas.wordpress.com/2011/10/08/c-get-physical-device-id-from-drive-letter-or-logical-disk-id/


    Darren Rose

    Thursday, December 28, 2017 11:27 PM
  • This code seems to work fine:-

                Dim logicalDiskId As String = "H:"
                Dim deviceId As String = String.Empty
                Dim query As String = ("ASSOCIATORS OF {Win32_LogicalDisk.DeviceID='" _
                             + (logicalDiskId + "'} WHERE AssocClass = Win32_LogicalDiskToPartition"))
                Dim queryResults = New ManagementObjectSearcher(query)
                Dim partitions = queryResults.Get
                For Each x In partitions
                    query = ("ASSOCIATORS OF {Win32_DiskPartition.DeviceID='" _
                                + (x("DeviceID") + "'} WHERE AssocClass = Win32_DiskDriveToDiskPartition"))
                    queryResults = New ManagementObjectSearcher(query)
                    Dim drives = queryResults.Get
                    For Each drive In drives
                        deviceId = drive("DeviceID").ToString ' or use Index to just show number
                    Next
                Next
                Console.WriteLine(deviceId)

    Thank you all very much for your help :)

    Happy new year to you all


    Darren Rose

    • Marked as answer by wingers Saturday, December 30, 2017 12:29 PM
    Saturday, December 30, 2017 12:29 PM
  •  Cool,  i did see a C++ example of using that same method in the Win32_LogicalDiskToPartition class documents the other day but,  did not feel like trying to convert it over to Vb.Net because i was not sure if it did what you needed or not.  8)

     I would consider using some Using Statements to do that so you are sure the ManagementObjectSearcher classes are Disposed.  I threw this function together that i have implemented that and fixed it so it will not show late binding errors for people like me that like keeping Option Strict turned on at all times.  I also made it to return the Id or Index just for the heck of it.

    Imports System.Management

    Public Class Form1
        Private Sub Button1_Click(sender As Object, e As EventArgs) Handles Button1.Click
            MessageBox.Show(GetPhysicalDriveId("E:"))
            MessageBox.Show(GetPhysicalDriveId("E:", True))
        End Sub

        Private Function GetPhysicalDriveId(drvName As String, Optional ReturnIndex As Boolean = False) As String
            Dim devId As String = ""
            Using LogicalDiskQueryResults As New ManagementObjectSearcher("ASSOCIATORS OF {Win32_LogicalDisk.DeviceID='" & (drvName & "'} WHERE AssocClass = Win32_LogicalDiskToPartition"))
                For Each mo As ManagementObject In LogicalDiskQueryResults.Get
                    Using DiskPartitionQueryResults As New ManagementObjectSearcher("ASSOCIATORS OF {Win32_DiskPartition.DeviceID='" & (mo("DeviceID").ToString & "'} WHERE AssocClass = Win32_DiskDriveToDiskPartition"))
                        For Each partition As ManagementObject In DiskPartitionQueryResults.Get
                            devId = partition(If(ReturnIndex, "Index", "DeviceID")).ToString
                        Next
                    End Using
                Next
            End Using
            Return devId
        End Function
    End Class


    If you say it can`t be done then i`ll try it

    • Edited by IronRazerz Saturday, December 30, 2017 6:10 PM
    • Marked as answer by wingers Sunday, December 31, 2017 1:22 AM
    Saturday, December 30, 2017 5:27 PM
  • Thanks IR - much appreciated :)

    Darren Rose

    Sunday, December 31, 2017 1:22 AM