twbradio

Get disk number from drive letter

17 posts in this topic

I have an external program that requires the disk number (0, 1, 2 ... ) and I am looking to wrap it with an AutoIt script. Is there a way to get the disk number from the drive letter of a partition?

Tom Brown


Anyone have a TRS 80 Model III for sale?

Share this post


Link to post
Share on other sites



Maybe this:

$sDriveLetter = "c"

$iDriveNumber = Asc(StringUpper($sDriveLetter)) - 65

ConsoleWrite($iDriveNumber & @CRLF)

♡♡♡

.

eMyvnE

Share this post


Link to post
Share on other sites

#3 ·  Posted (edited)

I have an external program that requires the disk number (0, 1, 2 ... ) and I am looking to wrap it with an AutoIt script. Is there a way to get the disk number from the drive letter of a partition?

Tom Brown

Too vague:

Logical disk? Physical disk? Partition number on the physical disk? Include mount points? What about mapped network drives? Removable drives? Removable media?

What, in your context, is a "disk number"?

:P

I like trancexx's idea!

:unsure:

Edited by PsaltyDS

Valuater's AutoIt 1-2-3, Class... Is now in Session!For those who want somebody to write the script for them: RentACoder"Any technology distinguishable from magic is insufficiently advanced." -- Geek's corollary to Clarke's law

Share this post


Link to post
Share on other sites

Because physical disks can have more than one partiton, this doesn't always equate properly. Thanks you for the reply.

Tom

Maybe this:

$sDriveLetter = "c"

$iDriveNumber = Asc(StringUpper($sDriveLetter)) - 65

ConsoleWrite($iDriveNumber & @CRLF)

Anyone have a TRS 80 Model III for sale?

Share this post


Link to post
Share on other sites

Because physical disks can have more than one partiton, this doesn't always equate properly. Thanks you for the reply.

Tom

...ermm... :unsure:

...tracexx was just kidding with you. That just shows the ASCII code of the drive letter. :P

You need to provide more info on what you want, as I posted earlier.

:D


Valuater's AutoIt 1-2-3, Class... Is now in Session!For those who want somebody to write the script for them: RentACoder"Any technology distinguishable from magic is insufficiently advanced." -- Geek's corollary to Clarke's law

Share this post


Link to post
Share on other sites

Too vague:

Logical disk? Physical disk? Partition number on the physical disk? Include mount points? What about mapped network drives? Removable drives? Removable media?

What, in your context, is a "disk number"?

:P

I like trancexx's idea!

:unsure:

Thanks for the catch on this ... I am looking for the windows physical disk number (similar to what is seen in Disk Management) with the Logical partition name (c:, d: ... ) as the input ... I don't need the partition number or any other data.

Tom Brown


Anyone have a TRS 80 Model III for sale?

Share this post


Link to post
Share on other sites

#7 ·  Posted (edited)

...ermm... :unsure:

...tracexx was just kidding with you. That just shows the ASCII code of the drive letter. :P

You need to provide more info on what you want, as I posted earlier.

:D

It's not obvious to me trancexx was kidding. His script doesn't return the ascii code it returns the drive number doesn't it?

What difference does it make if the drive is mounted in whatever way? Isn't the drive number still given by tracexx' code?

EDIT. No, I see that I am wrong. (Not about the ascii code) The disc number for C: and D: is given as 0 on my laptop. I am obviously confusing this with some other number. When I used to write C programs the drives really were referred to as Ascii(DriveLetter) - Ascii('A') so Drive J: was 9. I'm out of touch again!

Here is a link which has some useful information.

It is not possible to detrmine the disc number from the drive letter alone because it is determined by the bios and simply changing drives or adding a drive can change numbers around without changing the drive letters.

In Drive manager on my pc there is nothing shown for virtual drives or network drives. So I suppose the question to twbradio is, what do you mean by the disk number because I can't see that it is very useful to many applications?

Edited by martin

Serial port communications UDF Includes functions for binary transmission and reception.printing UDF Useful for graphs, forms, labels, reports etc.Add User Call Tips to SciTE for functions in UDFs not included with AutoIt and for your own scripts.Functions with parameters in OnEvent mode and for Hot Keys One function replaces GuiSetOnEvent, GuiCtrlSetOnEvent and HotKeySet.UDF IsConnected2 for notification of status of connected state of many urls or IPs, without slowing the script.

Share this post


Link to post
Share on other sites

You can work your way around to it, but it's not trivial (to me, anyway):

$oWMISvc = ObjGet("winmgmts:\\" & @ComputerName & "\root\cimv2")
$colDiskDrives = $oWMISvc.ExecQuery("SELECT * FROM Win32_DiskDrive")
For $oDiskDrive In $colDiskDrives
    ConsoleWrite("DiskDrive = " & $oDiskDrive.DeviceId & "  Caption = " & $oDiskDrive.Caption & @LF)
    
    $sQuery = "ASSOCIATORS OF {Win32_DiskDrive.DeviceID='" & $oDiskDrive.DeviceId & "'} WHERE AssocClass = Win32_DiskDriveToDiskPartition"  
    $colPartitions = $oWMISvc.ExecQuery($sQuery)

    For $oPartition In $colPartitions
        ConsoleWrite(@TAB & "Partition = " & $oPartition.DeviceId & @LF)
        
        $sQuery = "ASSOCIATORS OF {Win32_DiskPartition.DeviceID='" & $oPartition.DeviceId & "'} WHERE AssocClass = Win32_LogicalDiskToPartition"
        $colLogicalDisks = $oWMISvc.ExecQuery($sQuery) 

        For $oLogicalDisk In $colLogicalDisks
            ConsoleWrite(@TAB & @TAB & "LogicalDisk = " & $oLogicalDisk.DeviceId & @LF)
        Next      
    Next
Next

:P

1 person likes this

Valuater's AutoIt 1-2-3, Class... Is now in Session!For those who want somebody to write the script for them: RentACoder"Any technology distinguishable from magic is insufficiently advanced." -- Geek's corollary to Clarke's law

Share this post


Link to post
Share on other sites

#9 ·  Posted (edited)

That's cool.

Going to my special folder of special folders of... special things.

edit:

I did some thinking ( :D ) and I'm confused by the return values of the duck's code. For me it returns something like this:

DiskDrive = \\.\PHYSICALDRIVE0  Caption = WDC WD1200JS-00MVB1
    Partition = Disk #0, Partition #0
        LogicalDisk = C:
    Partition = Disk #0, Partition #1
        LogicalDisk = F:
    Partition = Disk #0, Partition #2
        LogicalDisk = G:
        LogicalDisk = H:
    Partition = Disk #0, Partition #3
        LogicalDisk = E:

What confuses me is that I never heard of partition #0 and that code returned drive C to be partition #0. I did some searching too and thing is that there shouldn't be partition 0 with windows (better say, partition(0) refers to the entire disk <- link, this too).

Further more, my mum (what?) told me that I should try to do something with DeviceIoControl function found in kernel32.dll.

I got this:

Local $aCall = DllCall("kernel32.dll", "dword", "GetLogicalDrives")

Local $iMask = $aCall[0]

Local $tIOCTL_STORAGE_GET_DEVICE_NUMBER = DllStructCreate("dword DeviceType;" & _
        "dword DeviceNumber;" & _
        "int PartitionNumber")

Local $hDevice
Local $a_hCall, $a_iCall

For $i = 0 To 25; alphabet (A = 0)

    If BitAND(BitShift($iMask, $i), 1) Then; drive exists

        $a_hCall = DllCall("kernel32.dll", "hwnd", "CreateFile", _
                "str", "\\.\" & Chr(65 + $i) & ":", _; want handle to the logical drive
                "dword", 0, _
                "dword", 0, _
                "ptr", 0, _
                "dword", 3, _; OPEN_EXISTING
                "dword", 128, _; FILE_ATTRIBUTE_NORMAL
                "ptr", 0)

        $hDevice = $a_hCall[0]

        $a_iCall = DllCall("kernel32.dll", "int", "DeviceIoControl", _
                "hwnd", $hDevice, _
                "dword", 0x2D1080, _; IOCTL_STORAGE_GET_DEVICE_NUMBER
                "ptr", 0, _
                "dword", 0, _
                "ptr", DllStructGetPtr($tIOCTL_STORAGE_GET_DEVICE_NUMBER), _
                "dword", DllStructGetSize($tIOCTL_STORAGE_GET_DEVICE_NUMBER), _
                "dword*", 0, _
                "ptr", 0)

        DllCall("kernel32.dll", "int", "CloseHandle", "hwnd", $hDevice)

        ConsoleWrite("Drive " & Chr(65 + $i) & ": " & @CRLF)
        ConsoleWrite(@TAB & "DeviceType: " & DllStructGetData($tIOCTL_STORAGE_GET_DEVICE_NUMBER, "DeviceType") & @CRLF)
        ConsoleWrite(@TAB & "DeviceNumber: " & DllStructGetData($tIOCTL_STORAGE_GET_DEVICE_NUMBER, "DeviceNumber") & @CRLF)
        ConsoleWrite(@TAB & "PartitionNumber: " & DllStructGetData($tIOCTL_STORAGE_GET_DEVICE_NUMBER, "PartitionNumber") & @CRLF)
        ConsoleWrite(@CRLF)

    EndIf

Next

Data returned by that is in some degree different than using PsaltyDS's code.

In case that code is correct something like this could be written:

$sDDriveLetter = "C"

$iDiskNumber = _GetDiskNimberForDrive($sDDriveLetter)

If @error Then
    MsgBox(48, "Error", "Error Number " & @error & @CRLF)
Else
    MsgBox(64, "_GetDiskNimberForDrive", "Drive " & StringUpper($sDDriveLetter) & " is on disk #" & $iDiskNumber)
EndIf



Func _GetDiskNimberForDrive($sDriveLetter)

    Local $a_hCall = DllCall("kernel32.dll", "hwnd", "CreateFile", _
            "str", "\\.\" & $sDriveLetter & ":", _; logical drive
            "dword", 0, _
            "dword", 0, _
            "ptr", 0, _
            "dword", 3, _; OPEN_EXISTING
            "dword", 128, _; FILE_ATTRIBUTE_NORMAL
            "ptr", 0)

    If @error Then
        Return SetError(1, 0, -1); your system is very old. Do something.
    EndIf

    If $a_hCall[0] = -1 Then
        Return SetError(2, 0, -1); non-existing drive
    EndIf

    Local $hDevice = $a_hCall[0]

    Local $tIOCTL_STORAGE_GET_DEVICE_NUMBER = DllStructCreate("dword DeviceType;" & _
            "dword DeviceNumber;" & _
            "int PartitionNumber")

    Local $a_iCall = DllCall("kernel32.dll", "int", "DeviceIoControl", _
            "hwnd", $hDevice, _
            "dword", 0x2D1080, _; IOCTL_STORAGE_GET_DEVICE_NUMBER
            "ptr", 0, _
            "dword", 0, _
            "ptr", DllStructGetPtr($tIOCTL_STORAGE_GET_DEVICE_NUMBER), _
            "dword", DllStructGetSize($tIOCTL_STORAGE_GET_DEVICE_NUMBER), _
            "dword*", 0, _
            "ptr", 0)

    If @error Or Not $a_hCall[0] Then
        DllCall("kernel32.dll", "int", "CloseHandle", "hwnd", $hDevice)
        Return SetError(3, 0, -1); DeviceIoControl failed for some reason
    EndIf

    DllCall("kernel32.dll", "int", "CloseHandle", "hwnd", $hDevice)

; will write some data
    ConsoleWrite("Drive " & StringUpper($sDriveLetter) & ": " & @CRLF)
    ConsoleWrite(@TAB & "DeviceType: " & DllStructGetData($tIOCTL_STORAGE_GET_DEVICE_NUMBER, "DeviceType") & @CRLF)
    ConsoleWrite(@TAB & "DeviceNumber: " & DllStructGetData($tIOCTL_STORAGE_GET_DEVICE_NUMBER, "DeviceNumber") & @CRLF)
    ConsoleWrite(@TAB & "PartitionNumber: " & DllStructGetData($tIOCTL_STORAGE_GET_DEVICE_NUMBER, "PartitionNumber") & @CRLF)
    ConsoleWrite(@CRLF)
; end writing

    If DllStructGetData($tIOCTL_STORAGE_GET_DEVICE_NUMBER, "DeviceType") = 7 Then; FILE_DEVICE_DISK
        Return SetError(0, 0, DllStructGetData($tIOCTL_STORAGE_GET_DEVICE_NUMBER, "DeviceNumber"))
    EndIf

    Return SetError(4, 0, -1); not a disk partition

EndFunc ;==>_GetDiskNimberForDrive

I only have one disk, so I cannot test it.

Edited by trancexx
2 people like this

♡♡♡

.

eMyvnE

Share this post


Link to post
Share on other sites

That's cool.

Going to my special folder of special folders of... special things.

edit:

I did some thinking ( :D ) and I'm confused by the return values of the duck's code. For me it returns something like this:

DiskDrive = \\.\PHYSICALDRIVE0  Caption = WDC WD1200JS-00MVB1
    Partition = Disk #0, Partition #0
        LogicalDisk = C:
    Partition = Disk #0, Partition #1
        LogicalDisk = F:
    Partition = Disk #0, Partition #2
        LogicalDisk = G:
        LogicalDisk = H:
    Partition = Disk #0, Partition #3
        LogicalDisk = E:

What confuses me is that I never heard of partition #0 and that code returned drive C to be partition #0. I did some searching too and thing is that there shouldn't be partition 0 with windows (better say, partition(0) refers to the entire disk <- link, this too).

Further more, my mum (what?) told me that I should try to do something with DeviceIoControl function found in kernel32.dll.

I got this:

CODE
Local $aCall = DllCall("kernel32.dll", "dword", "GetLogicalDrives")

Local $iMask = $aCall[0]

Local $tIOCTL_STORAGE_GET_DEVICE_NUMBER = DllStructCreate("dword DeviceType;" & _

"dword DeviceNumber;" & _

"int PartitionNumber")

Local $hDevice

Local $a_hCall, $a_iCall

For $i = 0 To 25; alphabet (A = 0)

If BitAND(BitShift($iMask, $i), 1) Then; drive exists

$a_hCall = DllCall("kernel32.dll", "hwnd", "CreateFile", _

"str", "\\.\" & Chr(65 + $i) & ":", _; want handle to the logical drive

"dword", 0, _

"dword", 0, _

"ptr", 0, _

"dword", 3, _; OPEN_EXISTING

"dword", 128, _; FILE_ATTRIBUTE_NORMAL

"ptr", 0)

$hDevice = $a_hCall[0]

$a_iCall = DllCall("kernel32.dll", "int", "DeviceIoControl", _

"hwnd", $hDevice, _

"dword", 0x2D1080, _; IOCTL_STORAGE_GET_DEVICE_NUMBER

"ptr", 0, _

"dword", 0, _

"ptr", DllStructGetPtr($tIOCTL_STORAGE_GET_DEVICE_NUMBER), _

"dword", DllStructGetSize($tIOCTL_STORAGE_GET_DEVICE_NUMBER), _

"dword*", 0, _

"ptr", 0)

DllCall("kernel32.dll", "int", "CloseHandle", "hwnd", $hDevice)

ConsoleWrite("Drive " & Chr(65 + $i) & ": " & @CRLF)

ConsoleWrite(@TAB & "DeviceType: " & DllStructGetData($tIOCTL_STORAGE_GET_DEVICE_NUMBER, "DeviceType") & @CRLF)

ConsoleWrite(@TAB & "DeviceNumber: " & DllStructGetData($tIOCTL_STORAGE_GET_DEVICE_NUMBER, "DeviceNumber") & @CRLF)

ConsoleWrite(@TAB & "PartitionNumber: " & DllStructGetData($tIOCTL_STORAGE_GET_DEVICE_NUMBER, "PartitionNumber") & @CRLF)

ConsoleWrite(@CRLF)

EndIf

Next

Data returned by that is in some degree different than using PsaltyDS's code.

In case that code is correct something like this could be written:

CODE
$sDDriveLetter = "C"

$iDiskNumber = _GetDiskNimberForDrive($sDDriveLetter)

If @error Then

MsgBox(48, "Error", "Error Number " & @error & @CRLF)

Else

MsgBox(64, "_GetDiskNimberForDrive", "Drive " & StringUpper($sDDriveLetter) & " is on disk #" & $iDiskNumber)

EndIf

Func _GetDiskNimberForDrive($sDriveLetter)

Local $a_hCall = DllCall("kernel32.dll", "hwnd", "CreateFile", _

"str", "\\.\" & $sDriveLetter & ":", _; logical drive

"dword", 0, _

"dword", 0, _

"ptr", 0, _

"dword", 3, _; OPEN_EXISTING

"dword", 128, _; FILE_ATTRIBUTE_NORMAL

"ptr", 0)

If @error Then

Return SetError(1, 0, -1); your system is very old. Do something.

EndIf

If $a_hCall[0] = -1 Then

Return SetError(2, 0, -1); non-existing drive

EndIf

Local $hDevice = $a_hCall[0]

Local $tIOCTL_STORAGE_GET_DEVICE_NUMBER = DllStructCreate("dword DeviceType;" & _

"dword DeviceNumber;" & _

"int PartitionNumber")

Local $a_iCall = DllCall("kernel32.dll", "int", "DeviceIoControl", _

"hwnd", $hDevice, _

"dword", 0x2D1080, _; IOCTL_STORAGE_GET_DEVICE_NUMBER

"ptr", 0, _

"dword", 0, _

"ptr", DllStructGetPtr($tIOCTL_STORAGE_GET_DEVICE_NUMBER), _

"dword", DllStructGetSize($tIOCTL_STORAGE_GET_DEVICE_NUMBER), _

"dword*", 0, _

"ptr", 0)

If @error Or Not $a_hCall[0] Then

DllCall("kernel32.dll", "int", "CloseHandle", "hwnd", $hDevice)

Return SetError(3, 0, -1); DeviceIoControl failed for some reason

EndIf

DllCall("kernel32.dll", "int", "CloseHandle", "hwnd", $hDevice)

; will write some data

ConsoleWrite("Drive " & StringUpper($sDriveLetter) & ": " & @CRLF)

ConsoleWrite(@TAB & "DeviceType: " & DllStructGetData($tIOCTL_STORAGE_GET_DEVICE_NUMBER, "DeviceType") & @CRLF)

ConsoleWrite(@TAB & "DeviceNumber: " & DllStructGetData($tIOCTL_STORAGE_GET_DEVICE_NUMBER, "DeviceNumber") & @CRLF)

ConsoleWrite(@TAB & "PartitionNumber: " & DllStructGetData($tIOCTL_STORAGE_GET_DEVICE_NUMBER, "PartitionNumber") & @CRLF)

ConsoleWrite(@CRLF)

; end writing

If DllStructGetData($tIOCTL_STORAGE_GET_DEVICE_NUMBER, "DeviceType") = 7 Then; FILE_DEVICE_DISK

Return SetError(0, 0, DllStructGetData($tIOCTL_STORAGE_GET_DEVICE_NUMBER, "DeviceNumber"))

EndIf

Return SetError(4, 0, -1); not a disk partition

EndFunc ;==>_GetDiskNimberForDrive

I only have one disk, so I cannot test it.
Well, in the case of extended vice primary partitions, there could be...

wait-a-minute...

"the duck's code"?

:o


Valuater's AutoIt 1-2-3, Class... Is now in Session!For those who want somebody to write the script for them: RentACoder"Any technology distinguishable from magic is insufficiently advanced." -- Geek's corollary to Clarke's law

Share this post


Link to post
Share on other sites

:D

Huge thank you to everyone, I first tried the WMI call which worked on my local system, but did not work when I attempted to run it from my BartPE environment ... Moving to the DLL example, I was able to get exactly the result I wanted. Thank you all so much for pitching in.

Thomas Brown


Anyone have a TRS 80 Model III for sale?

Share this post


Link to post
Share on other sites

Well, in the case of extended vice primary partitions, there could be...

wait-a-minute...

"the duck's code"?

:D

:o <- click it

♡♡♡

.

eMyvnE

Share this post


Link to post
Share on other sites

I just want to add a thanks here too. Just goes to show if you search long enough you'll some brilliant posts (as shown above). I had all the WMI component working just didn't have the association piece! Thanks PsaltyDs for the code and everyone else who added to it and the thread and to twbradio for the original question!


The difference between Genius and Stupidity is that Genius has its limits....Einstein

Share this post


Link to post
Share on other sites

Further more, my mum (what?) told me that I should try to do something with DeviceIoControl function found in kernel32.dll.

Your mom is so cool... ;)

Share this post


Link to post
Share on other sites

#15 ·  Posted (edited)

Hi there!!

The following snippet gets the HDD serial number through a bat file.The bat file writes to a text file from which the sr. num. is retrieved by the Autoit script.In every run the HDD sr. num. is written successfully to comp_id.txt.But  .au3 script acts inconsistently.It fail frequently (though succeeds occasionally) to retrieve the sr.no..

Can any one please help remove this inconsistent behavior ?

here is the code:

#include <constants.au3>
#include <WinAPIFiles.au3>
#include <MsgBoxConstants.au3>
Func getHDDNum()
    Run("gtSrNumHDD.bat")
    While FileExists("comp_id.txt")==False
            Sleep(100)
    WEnd
    Sleep(100)
    Local $hddNum=FileReadLine("comp_id.txt",2)
    ConsoleWrite ("sr no is: "&$hddNum&@CRLF)
    MsgBox(0,"",$hddNum);
    ConsoleWrite ("sr no is: "&$hddNum&@CRLF)
EndFunc
getHDDNum()
FileDelete("comp_id.txt")

the .bat file code:

@ECHO OFF::writes to file  comp_id.txt
wmic diskdrive get serialnumber > comp_id.txt

I will greatly appreciate any help

 

olmar

Edited by olmanRvr

Share this post


Link to post
Share on other sites
Func getHDDNum()
    RunWait("gtSrNumHDD.bat")
    Sleep(100)
    Local $hddNum=FileReadLine("comp_id.txt",2)
    ConsoleWrite ("sr no is: "&$hddNum&@CRLF)
    MsgBox(0,"",$hddNum);
    ConsoleWrite ("sr no is: "&$hddNum&@CRLF)
EndFunc
getHDDNum()
FileDelete("comp_id.txt")
@ECHO Off
vol c: > comp_id.txt
Local $strDiskDrive = "C:"
Local $objWMIService = ObjGet("winmgmts:{impersonationLevel=impersonate}!\\.\root\cimv2")

;Local $colItems = $objWMIService.ExecQuery("SELECT * FROM Win32_LogicalDisk Where DeviceID = 'C:'")
Local $colItems = $objWMIService.ExecQuery("SELECT * FROM Win32_LogicalDisk Where DeviceID = '" & $strDiskDrive & "'" )
For $objItem In $colItems
   Local $strSerial = $objItem.VolumeSerialNumber
ConsoleWrite ( "Serial Number of Drive " & $strDiskDrive & $strSerial & @CRLF )
Next

@olmanRvr I changed Run to RunWait() in your'e function And In your'e batch file i changed the wmic command to: "Vol C: > comp_id.txt" After these changes the code seems to run ok. Also i added a third piece of code on how to do almost the same with WMI. Hope this helps

Share this post


Link to post
Share on other sites

Hi pluto41,

Many thanks for your reply.I tried your revised version.But there are errors. @ECHO OFF ->"undefined macro" and for vol c: > comp_id.txt ->"Statement cannot be just an expression".Attaching  snap shot(not showing the includes).Any idea why the errors?

cheers

olmar

codeImg.thumb.png.bc3fcf70509d1acd425d3a

Share this post


Link to post
Share on other sites

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!


Register a new account

Sign in

Already have an account? Sign in here.


Sign In Now