Click here to Skip to main content
15,892,965 members
Please Sign up or sign in to vote.
0.00/5 (No votes)
See more:
Good Evening,

Does anyone know how to get the logical ID(Not Serial Number) of a logical drive? I need to find location number of the drive. Below is a diskpart printout and I am looking to find the number under "volume ###" column. I have searched and searched, and can not find out how to find it. Everything I find is about finding serial number, drive type, drive letter, and so on. Right now, I have been trying to do with string manipulation, and its not exact all the time. There are too many variables.

Let me explain and give a little more detail. I want to create a program that will deploy a Windows 7 image using WinPe 4.0 and Usb Flash Drives. I am trying to use Diskpart to delete existing partitions, but not the USB drive partitions. The diskpart printout below is what I was using to try and get the volume number to do a "Sel Vol" and the disk number, in order to get the partition to delete. But I thought there would be another way to do it rather than output the printout to a textbox and use string manipulations to look for it.



Code:

Volume ###    Ltr    Label        Fs     Type        Size     Status     Info
 ----------   ---    -----------  -----  ----------  -------  ---------  --------
 Volume 0       D                       DVD-ROM         0 B  No Media
 Volume 1       E                       DVD-ROM         0 B  No Media



So I came across the WMI Classes and thought I might be able to get it from there using a function similiar to below to return the value and create a variable. But I have not been able to figure it out.

VB
Private Function GetDriveInfo(ByVal sVolumeName As String) As String
        Dim objMOC As Management.ManagementObjectCollection
        Dim objMOS As Management.ManagementObjectSearcher = New Management.ManagementObjectSearcher("SELECT * FROM Win32_Volume")
        Dim objMO As Management.ManagementObject

        objMOC = objMOS.Get()

        For Each objMO In objMOC
            Dim objDriveLetter As String = objMO("DeviceID")
            Dim objVolumeLabel = objMO("Name")
            MsgBox(objDriveLetter & vbCrLf & objVolumeLabel)
            If UCase(objVolumeLabel) = UCase(sVolumeName) Then
                Return objDriveLetter.ToString
            Else : Return Nothing

            End If
            'Dim objOUT As String = String.Format("{0} - {1}", objVolumeName, objID)
            ' MsgBox(objOUT)
        Next
        Return Nothing
    End Function



Here is what I am currently using to find and delete partitions, but it is not efficient.

VB
Private Sub DelExistingPartitions()
        If Me.InvokeRequired Then
            Me.Invoke(New DelegateDelExistingPartitions(AddressOf DelExistingPartitions))
        Else
            Dim tmp As String
            Dim myprocess As New Process
            Dim StartInfo As New System.Diagnostics.ProcessStartInfo
            StartInfo.FileName = sSystem32 & "\diskpart.exe"
            StartInfo.CreateNoWindow = True
            StartInfo.RedirectStandardInput = True
            StartInfo.RedirectStandardOutput = True
            StartInfo.UseShellExecute = False
            myprocess.StartInfo = StartInfo
            myprocess.Start()
            Dim SR As System.IO.StreamReader = myprocess.StandardOutput
            Dim SW As System.IO.StreamWriter = myprocess.StandardInput
            SW.WriteLine("list vol")
            SW.WriteLine("exit")

            Do While myprocess.HasExited = False
                tmp = SR.ReadLine & vbCrLf
                If tmp <> "" Then
                    Me.txtResults.AppendText(tmp)
                End If
            Loop
            
            For Each line In txtResults.Lines
                If line = "" Then
                ElseIf line.Contains("Microsoft DiskPart version") Then
                ElseIf line.Contains("Copyright (C)") Then
                ElseIf line.Contains("On computer:") Then
                ElseIf line.Contains("DISKPART>") Then
                ElseIf line.Contains("Volume ###") Then
                ElseIf line.Contains("----------") Then
                ElseIf line.Contains(UCase("DVD-ROM")) Then
                ElseIf line.Contains(UCase("FAT32")) Then
                ElseIf line.Contains(UCase("IMAGES")) Then
                ElseIf line.Contains(UCase("X:\Diskpart")) Then
                Else
                    Dim sIndexOfId = line.IndexOf("e")
                    Dim sVolumeID As String = line.Substring(sIndexOfId + 2, 1)
                    sExistingPartition = sVolumeID
                    'MsgBox(sExistingPartition)
                    SW.WriteLine("select vol " & sExistingPartition)
                    SW.WriteLine("Delete vol override")
                    ' SW.WriteLine("exit")
                End If
            Next
            SW.Close()
            SR.Close()
        End If
    End Sub


If you need anything further, please let me know.
Posted
Updated 3-Apr-13 7:00am
v2
Comments
Sergey Alexandrovich Kryukov 2-Apr-13 23:26pm    
Win32 logical disk has the property "DeviceID". Is it the one you need? Another one is PNPDeviceID.
—SA
iismoove 2-Apr-13 23:34pm    
I have tried both. I use the DeviceID to get the drive letter. The PNPDeviceID comes up blank.
Sergey Alexandrovich Kryukov 2-Apr-13 23:57pm    
Correct. I just experimented with the code and found it's wrong. And Logical disk is also a wrong class. You need another one: Win32_Volume (quite logically).
You got the result of my search. Please see my answer; you got all you need.
—SA
iismoove 3-Apr-13 0:12am    
Great! I will try it out. Thanks!
Sergey Alexandrovich Kryukov 3-Apr-13 0:53am    
Don't forget to accept the answer formally (even if you need something a bit different), as I explained the Method...
(Green button.)
—SA

You can do it using WMI: http://en.wikipedia.org/wiki/Windows_Management_Instrumentation[^].

First of all, you need to figure out where to get the documentation. For Win32_LogicalDisk, please see:
http://msdn.microsoft.com/en-us/library/windows/desktop/aa394173%28v=vs.85%29.aspx[^].

As you can see, there is no such thing as "logical ID". Besides, when I run the code, I cannot see "*volume*" ID which you probably want (please see the code below). No, wrong way. Further search shows that you can use Win32_Volume, not "logical ID":
http://msdn.microsoft.com/en-us/library/windows/desktop/aa394515%28v=vs.85%29.aspx[^].

Using this information via .NET WMI (Management) is more tricky. You don't have the fully-mapped API for all properties and methods. Instead, everything should be found by the queries using type names and property (in your case) names which you can find from the documentation referenced above. Besides, there is a reflective type of API which allows your to list all the properties and methods.

Take a look at my code sample:
C#
using System;
using System.Management;

//...

            ManagementObjectSearcher searcher = new ManagementObjectSearcher("SELECT * FROM Win32_Volume");
            ManagementObjectCollection collection = searcher.Get();
            foreach (ManagementObject item in collection)
                System.Console.WriteLine(
                    "Name: {0}, Device ID: {1}",
                     item["Name"], item["DeviceID"]);


Please see:
http://msdn.microsoft.com/en-us/library/system.management.aspx[^],
http://msdn.microsoft.com/en-us/library/system.management.managementobjectcollection.aspx[^],
http://msdn.microsoft.com/en-us/library/system.management.managementobject.aspx[^].

If you need to find out something else, learn all the concrete WMI queries, classes and their members. This CodeProject article provides comprehensive help in search for them:
CIMTool for Windows Management Instrumentation - Part 3[^].

This is a really powerful interactive tool.

Another way to learn WMI and quickly prototype queries is Microsoft PowerShell:
http://en.wikipedia.org/wiki/Powershell[^],
http://www.microsoft.com/powershell[^].

—SA
 
Share this answer
 
v6
Comments
iismoove 3-Apr-13 10:19am    
The DeviceID in Win32_Volume does not give the volume numbers that is used in diskpart. It gives more of a long GUID like number. I have looked through so many of the WMI classes and cannot seem to find it. Any ideas?
Sergey Alexandrovich Kryukov 3-Apr-13 12:42pm    
Maybe, this is just because you did not explain what exactly did you expect and because I don't know all the detail; I just search those features in WMI.

Could you give me a couple of exact examples of the strings you expected?

Or you could also try to find it by yourself. There are several different ManagementObject "classes" (from the point of view of ManagementObjects, there are some kind of meta-type known by names, such as "Win32_Volume" or "Win32_LogicalDisk", but there are more) related to the file system.
You can also use Espen's system to explore...

—SA
iismoove 3-Apr-13 13:01pm    
I updated my question with a little more details.
Sergey Alexandrovich Kryukov 3-Apr-13 13:12pm    
OK, thank you, how about the example of the string you are still missing?
—SA
iismoove 3-Apr-13 13:44pm    
I just want to get that number after where it says "Volume" in my top Diskpart printout. ex. 0, 1.
One way to find the system volume is this:

First, use the method Environment.GetFolderPath(Environment.SpecialFolder):
http://msdn.microsoft.com/en-us/library/14tx8hby.aspx[^],
http://msdn.microsoft.com/en-us/library/system.environment.specialfolder.aspx[^].

As you can see, two of the enumeration members are System and Windows, so you can find a volume letter where the system is, and compare it with the results you got using the WMI object Win32_Volume, as shown in Solution 1. This way, you can find the corresponding volume and its properties.

However, it does not guarantee that the boot volume is the same. Boot is a pretty complex process. It starts from the boot order of physical drives specified in BIOS or UEFI (successor of BIOS), and on a physical drive is further defined by Master Boot Record, and then it can be a multu-boot system with different ways to proceed with the OS loading, and so on.

I found the information on how to find out boot information from WMI: http://stackoverflow.com/questions/9337354/access-the-windows-7-boot-configuration-data-using-c-sharp[^].

I did not try it yet, so please try. I would be interested in your feedback.

—SA
 
Share this answer
 
Comments
iismoove 4-Apr-13 9:51am    
I will give it a try and let you know. It may not be until later today, but I will give it a whirl.
Sergey Alexandrovich Kryukov 4-Apr-13 9:57am    
Great.
—SA
iismoove 4-Apr-13 10:06am    
Are you always on here? LOL. It seems like no matter when I post, you post right back.
Sergey Alexandrovich Kryukov 4-Apr-13 10:11am    
Just a coincidence... :-)
—SA
First I declared the follwing variables:

VB
Public sTotalVolumes As Integer = 0
    Public iRemovable As Integer = 0
    Public sLocalDisks As Integer = 0
    Public iDvd As Integer = 0
    Public sLastDvdVolumeNumber As Integer = 0
    Public sFirstLocalDiskVolumeNumber As Integer = 0


Then I got the machine's volumes' information:

VB
Private Sub GetVolumeInfo()
        Dim objMOC As Management.ManagementObjectCollection
        Dim objMOS As Management.ManagementObjectSearcher = New Management.ManagementObjectSearcher("SELECT * FROM Win32_Volume")
        Dim objMO As Management.ManagementObject

        objMOC = objMOS.Get()
        sTotalVolumes = CInt(objMOC.Count)

        For Each objMO In objMOC
            Dim sDriveName As String = objMO("Name")
            Dim sDriveType As Integer = CInt(objMO("DriveType"))
            ' MsgBox(sDriveName & vbNewLine & sDriveType)
            If sDriveType = 5 Then
                iDvd = iDvd + 1
            ElseIf sDriveType = 2 Then
                iRemovable = iRemovable + 1
            ElseIf sDriveType = 3 Then
                sLocalDisks = sLocalDisks + 1
            End If
        Next
     End Sub



Then last I used this Sub to delete the existing partitions:


VB
Private Sub DelExistingPartitions()
        If Me.InvokeRequired Then
            Me.Invoke(New DelegateDelExistingPartitions(AddressOf DelExistingPartitions))
        Else
            GetVolumeInfo()
            Dim tmp As String
            Dim p As New Process
            p.StartInfo.FileName = sSystem32 & "\diskpart.exe"
            p.StartInfo.UseShellExecute = False
            p.StartInfo.RedirectStandardOutput = True
            p.StartInfo.RedirectStandardInput = True
            p.StartInfo.CreateNoWindow = True
            p.Start()
            Dim SR As System.IO.StreamReader = p.StandardOutput
            Dim SW As System.IO.StreamWriter = p.StandardInput

            'Insert Commands Here
            'SW.WriteLine("list vol")
            sFirstLocalDiskVolumeNumber = iDvd - 1

            For i As Integer = 1 To sLocalDisks - 1 Step 1
                sFirstLocalDiskVolumeNumber = sFirstLocalDiskVolumeNumber + 1
                'MsgBox(sFirstLocalDiskVolumeNumber)
                SW.WriteLine("sel vol " & sFirstLocalDiskVolumeNumber)
                SW.WriteLine("Delete vol override")
            Next
            SW.WriteLine("exit")
            Do While p.HasExited = False
                tmp = SR.ReadLine()
                If tmp <> "" Then
                    Me.txtResults.AppendText(tmp & vbCrLf)
                End If
            Loop
            SR.Close()
            SW.Close()
            p.Dispose()
        End If
    End Sub
 
Share this answer
 
'This will produce disk information as used in diskpart, disk number, partition 'number and drive letters. visit malvastyle.com for more (i wrote an application 'that uses diskpart that will be free for download on the site in a day or 2.

'Get Disk Number
Dim query
Dim objWMI
Dim diskDrives
Dim diskDrive
Dim partitions
Dim partition ' will contain the drive & partition numbers
Dim logicalDisks
Dim logicalDisk ' will contain the drive letter
Dim stroutput As New StringBuilder

objWMI = GetObject("winmgmts:\\.\root\cimv2")
diskDrives = objWMI.ExecQuery("SELECT * FROM Win32_DiskDrive") ' First get out the physical drives
For Each diskDrive In diskDrives
query = "ASSOCIATORS OF {Win32_DiskDrive.DeviceID='" + diskDrive.DeviceID + "'} WHERE AssocClass = Win32_DiskDriveToDiskPartition" ' link the physical drives to the partitions
partitions = objWMI.ExecQuery(query)
For Each partition In partitions
query = "ASSOCIATORS OF {Win32_DiskPartition.DeviceID='" + partition.DeviceID + "'} WHERE AssocClass = Win32_LogicalDiskToPartition" ' link the partitions to the logical disks
logicalDisks = objWMI.ExecQuery(query)
For Each logicalDisk In logicalDisks
stroutput.Append(logicalDisk.DeviceID & " - " & partition.Caption)
' Wscript.Echo(logicalDisk.DeviceID & " - " & partition.Caption)
Next
Next
Next
MessageBox.Show(stroutput.ToString)
 
Share this answer
 

This content, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)



CodeProject, 20 Bay Street, 11th Floor Toronto, Ontario, Canada M5J 2N8 +1 (416) 849-8900