Jump to content
Sign in to follow this  
Dougiefresh

[Need Help] Get PNP Device ID for USB Drive

Recommended Posts

Dougiefresh

Can someone translate this code to AutoIt for me? I'm not sure what is happening here, so I can't translate this correctly. Any assistance would be greatly appreciated!

Source: http://home.hot.rr.com/graye/Articles/USB_SerialNumbers.htm

Public Function GetSerialNumber(ByVal DriveLetter As String) As String
   Dim wmi_ld, wmi_dp, wmi_dd As ManagementObject
   Dim temp, parts(), ans As String

   ans = ""
   ' get the Logical Disk for that drive letter
   wmi_ld = New ManagementObject("Win32_LogicalDisk.DeviceID='" & DriveLetter.TrimEnd("\"c) & "'")
   ' get the associated DiskPartition 
      For Each wmi_dp In wmi_ld.GetRelated("Win32_DiskPartition")
      ' get the associated DiskDrive
      For Each wmi_dd In wmi_dp.GetRelated("Win32_DiskDrive")
      '  the serial number is embedded in the PnPDeviceID
         temp = wmi_dd("PnPDeviceID").ToString
         If Not temp.StartsWith("USBSTOR") Then
            Throw New ApplicationException(DriveLetter & " doesn't appear to be USB Device")
         End If
         parts = temp.Split("\&".ToCharArray)
         ' The serial number should be the next to the last element
         ans = parts(parts.Length - 2)
      Next
   Next

   Return ans
End Function
Edited by Dougiefresh

Share this post


Link to post
Share on other sites
MadBoy

Can someone translate this code to AutoIt for me? I'm not sure what is happening here, so I can't translate this correctly. Any assistance would be greatly appreciated!

Source: http://home.hot.rr.com/graye/Articles/USB_SerialNumbers.htm

Public Function GetSerialNumber(ByVal DriveLetter As String) As String
    Dim wmi_ld, wmi_dp, wmi_dd As ManagementObject
    Dim temp, parts(), ans As String
 
    ans = ""
    ' get the Logical Disk for that drive letter
    wmi_ld = New ManagementObject("Win32_LogicalDisk.DeviceID='" & DriveLetter.TrimEnd("\"c) & "'")
    ' get the associated DiskPartition 
       For Each wmi_dp In wmi_ld.GetRelated("Win32_DiskPartition")
       ' get the associated DiskDrive
       For Each wmi_dd In wmi_dp.GetRelated("Win32_DiskDrive")
       '  the serial number is embedded in the PnPDeviceID
          temp = wmi_dd("PnPDeviceID").ToString
          If Not temp.StartsWith("USBSTOR") Then
             Throw New ApplicationException(DriveLetter & " doesn't appear to be USB Device")
          End If
          parts = temp.Split("\&".ToCharArray)
          ' The serial number should be the next to the last element
          ans = parts(parts.Length - 2)
       Next
    Next
 
    Return ans
 End Function
Won't the builtin autoit code work? Lemme know if it doesn't then i'll check the WMI call.

$var = DriveGetSerial(  "c:\" )
MsgBox(4096, "Serial Number: ",  $var)

My little company: Evotec (PL version: Evotec)

Share this post


Link to post
Share on other sites
MadBoy

Won't the builtin autoit code work? Lemme know if it doesn't then i'll check the WMI call.

$var = DriveGetSerial(  "c:\" )
MsgBox(4096, "Serial Number: ",  $var)

I'll see if i can modify the wmi for you.


My little company: Evotec (PL version: Evotec)

Share this post


Link to post
Share on other sites
Dougiefresh

Yes and no. The AutoIt function returns the serial number just fine. However, the WMI code also pulls the PNP device description, which is what I'm really after....

EDIT: Hah! Looks like you posted right before me! LOL!

Edited by Dougiefresh

Share this post


Link to post
Share on other sites
MadBoy

Yes and no. The AutoIt function returns the serial number just fine. However, the WMI code also pulls the PNP device description, which is what I'm really after....

EDIT: Hah! Looks like you posted right before me! LOL!

Can you tell me exactly what you want the script to do? I saw 2 your posts and not sure what you want to achieve.


My little company: Evotec (PL version: Evotec)

Share this post


Link to post
Share on other sites
Dougiefresh

Sorry, I posted the incompatible-with-Vista code. Here's the right code:

Public Function GetSerialNumber(ByVal DriveLetter As String) As String
   Dim wmi_ld, wmi_dp, wmi_dd As ManagementObject
   Dim temp, parts(), ans As String

   ans = ""
   ' get the Logical Disk for that drive letter
   wmi_ld = New ManagementObject("Win32_LogicalDisk.DeviceID='" & DriveLetter.TrimEnd("\"c) & "'")
   ' get the associated DiskPartition 
      For Each wmi_dp In wmi_ld.GetRelated("Win32_DiskPartition")
      ' get the associated DiskDrive
      For Each wmi_dd In wmi_dp.GetRelated("Win32_DiskDrive")
         ' There is a bug in WinVista that corrupts some of the fields
         ' of the Win32_DiskDrive class if you instantiate the class via
         ' its primary key (as in the example above) and the device is
         ' a USB disk. Oh well... so we have go thru this extra step
         Dim wmi As New ManagementClass("Win32_DiskDrive")
         ' loop thru all of the instances. This is silly, we shouldn't
         ' have to loop thru them all, when we know which one we want.
         For Each obj As ManagementObject In wmi.GetInstances
            ' do the DeviceID fields match?
            If obj("DeviceID").ToString = wmi_dd("DeviceID").ToString Then
               ' the serial number is embedded in the PnPDeviceID
                temp = obj("PnPDeviceID").ToString
                If Not temp.StartsWith("USBSTOR") Then
                   Throw New ApplicationException(DriveLetter & " doesn't appear to be USB Device")
                End If
                parts = temp.Split("\&".ToCharArray)
                ' The serial number should be the next to the last element
                ans = parts(parts.Length - 2)
            End If
         Next
      Next
   Next

   Return ans
End Function

What I'm wanting to do is to pull the PNPDeviceID from the function. I don't really need the serial number, just the PNP device ID. I believe that is the first part of the string that's split.... But, I can use the entire string to try to determine whether a device is an MP3 player, a digital camera, a digital camcorder, etc.

If you could translate it to AutoIt, I can take it the rest of the way so (hopefully) it'll do what I need it to....

EDIT: Don't need or care about the "throw exception" part, so you don't have to include that....

Edited by Dougiefresh

Share this post


Link to post
Share on other sites
MadBoy

I would prefer straight answer what the code is supposed to do (so what you want to get). Not what the code you posted does :P However take a look at this.

#Include <array.au3>
Global $array_pnp_deviceid[1]

_GetPnpDevice()
_ArrayDisplay($array_pnp_deviceid)

Func _GetPnpDevice()
    
    $wbemFlagReturnImmediately = 0x10
    $wbemFlagForwardOnly = 0x20
    $colItems = ""
    $strComputer = "localhost"

    $objWMIService = ObjGet("winmgmts:\\" & $strComputer & "\root\CIMV2")
    $colItems = $objWMIService.ExecQuery("SELECT * FROM Win32_DiskDrive", "WQL", $wbemFlagReturnImmediately + $wbemFlagForwardOnly)

    If IsObj($colItems) Then
        For $objItem In $colItems
            $string_pnp_deviceid = $objItem.PNPDeviceID
            _ArrayAdd($array_pnp_deviceid, $string_pnp_deviceid)
        Next
    Else
        MsgBox(0, "WMI Output", "No WMI Objects Found for class: " & "Win32_DiskDrive")
    EndIf
    $array_pnp_deviceid[0] = UBound($array_pnp_deviceid) - 1
EndFunc   ;==>_GetPnpDevice

My little company: Evotec (PL version: Evotec)

Share this post


Link to post
Share on other sites
Dougiefresh

But the code you posted doesn't retrieve the PNPDeviceID for the drive letter specified (if available). It retrieves all PNP Device ID's for mass-storage devices. Not helpful to me.... The code I posted (code isn't in AutoIt, though) is supposed to, according to the web site that it was copied from.

I'm trying to determine whether a drive letter is a specific device, like a MP3 player, digital camera, camcorder, etc. (I thought I explaned that... I guess I wasn't clear....)

EDIT: I have a program located here. Take a look, please....

Edited by Dougiefresh

Share this post


Link to post
Share on other sites
ptrex
Dougiefresh

Tried it. Doesn't return any devices..... I guess I'll give translating it myself a shot, since no one wants to help me with the translation.

Share this post


Link to post
Share on other sites
MadBoy

Tried it. Doesn't return any devices..... I guess I'll give translating it myself a shot, since no one wants to help me with the translation.

I'll help you in a moment. Just gimme time (work first :P). That's why i asked in the beging what the code is supposed to do! So i wouldn't have to guess what you realy realy want.


My little company: Evotec (PL version: Evotec)

Share this post


Link to post
Share on other sites
Dougiefresh

I'll help you in a moment. Just gimme time (work first :P). That's why i asked in the beging what the code is supposed to do! So i wouldn't have to guess what you realy realy want.

Thanks. I do appreciate it. I really do!

Share this post


Link to post
Share on other sites
MadBoy

Thanks. I do appreciate it. I really do!

Pheeww! Finally. Took me a while. It's not preety but it works ;) Function returns 0 if the drive letter cannot be found. Otherwise it returns the PnpDEVICEID.

Note to self: never volunteer again to write scripts that look easy but aren;t :P

#include <String.au3>

$test = _GetPNPDeviceID("H:")
MsgBox(0, "Hurray", $test)

Func _GetPNPDeviceID($drive_letter)
    Local $drive_letter_found, $drive_letter_found
    $wbemFlagReturnImmediately = 0x10
    $wbemFlagForwardOnly = 0x20
    $colItems = ""
    $strComputer = "localhost"
    
    $objWMIService = ObjGet("winmgmts:\\" & $strComputer & "\root\CIMV2")
    $colItems = $objWMIService.ExecQuery("SELECT * FROM Win32_LogicalDiskToPartition", "WQL", $wbemFlagReturnImmediately + $wbemFlagForwardOnly)
    If IsObj($colItems) Then
        For $objItem In $colItems
            $LogicalDiskToPartitionAntecedent = _StringBetween($objItem.Antecedent, '"', '"')
            $LogicalDiskToPartitionDependent = _StringBetween($objItem.Dependent, '"', '"')
            ;ConsoleWrite(@CR & $LogicalDiskToPartitionAntecedent[0] & " - " & $LogicalDiskToPartitionDependent[0])
            $drive_statistics = $LogicalDiskToPartitionAntecedent[0]
            $drive_letter_found = $LogicalDiskToPartitionDependent[0]
            If $drive_letter = $drive_letter_found Then
                ExitLoop
            EndIf
        Next
    Else
        MsgBox(0, "WMI Output", "No WMI Objects Found for class: " & "Win32_LogicalDiskToPartition")
    EndIf
    If $drive_letter <> $drive_letter_found Then Return 0 ; If drive letter isn't function returns 0
    
    $colItems = $objWMIService.ExecQuery("SELECT * FROM Win32_DiskDriveToDiskPartition", "WQL", $wbemFlagReturnImmediately + $wbemFlagForwardOnly)
    If IsObj($colItems) Then
        For $objItem In $colItems
            $DiskDriveToDiskPartitionAntecedent = _StringBetween($objItem.Antecedent, '"', '"')
            $DiskDriveToDiskPartitionDependent = _StringBetween($objItem.Dependent, '"', '"')
            ;ConsoleWrite(@CR & $DiskDriveToDiskPartitionAntecedent[0] & " - " & $DiskDriveToDiskPartitionDependent[0])
            $drive_statistics_found = $DiskDriveToDiskPartitionDependent[0]
            $drive_physical = StringTrimLeft($DiskDriveToDiskPartitionAntecedent[0], StringInStr($DiskDriveToDiskPartitionAntecedent[0], "\", 1, -1))
            ;MsgBox(0,"TEST", $drive_physical)
            If $drive_statistics = $drive_statistics_found Then
                ExitLoop
            EndIf
        Next
    Else
        MsgBox(0, "WMI Output", "No WMI Objects Found for class: " & "Win32_DiskDriveToDiskPartition")
    EndIf

    $colItems = $objWMIService.ExecQuery("SELECT * FROM Win32_DiskDrive", "WQL", $wbemFlagReturnImmediately + $wbemFlagForwardOnly)
    If IsObj($colItems) Then
        For $objItem In $colItems
            ;MsgBox(0,324234, $objItem.DeviceID)
            $DeviceID = StringTrimLeft($objItem.DeviceID, StringInStr($objItem.DeviceID, "\", 1, -1))
            $PNPDeviceID = $objItem.PNPDeviceID
            ;MsgBox(0,122, $DeviceID)
            If $drive_physical = $DeviceID Then
                Return $PNPDeviceID
            EndIf
        Next
    Else
        MsgBox(0, "WMI Output", "No WMI Objects Found for class: " & "Win32_DiskDrive")
    EndIf
EndFunc   ;==>_GetPNPDeviceID

My little company: Evotec (PL version: Evotec)

Share this post


Link to post
Share on other sites
Dougiefresh

Whoa... I didn't expect the AutoIt translation to be so long! It definitely does the job! Doesn't work on my card reader, but it picks up my digital camera! This solves quite a few problems! I thank you very much!

EDIT: Hold on, it looked easy to you? I couldn't make heads or tails of it. Well! ....I'm an OK AutoIt scripter, but that code from whatever language looked to be a mess and a half. I salute you for your AutoIt skills! You're amazing!

EDIT2: Pretty don't count. Function does!

Edited by Dougiefresh

Share this post


Link to post
Share on other sites
MadBoy

Whoa... I didn't expect the AutoIt translation to be so long! It definitely does the job! Doesn't work on my card reader, but it picks up my digital camera! This solves quite a few problems! I thank you very much!

It probably could be done in a simpler way however i am "not" that experienced in WMI ;P Just figured i would help you. As for the card reader what's the problem?


My little company: Evotec (PL version: Evotec)

Share this post


Link to post
Share on other sites
Dougiefresh

It probably could be done in a simpler way however i am "not" that experienced in WMI ;P Just figured i would help you. As for the card reader what's the problem?

The code returns 0 for any of the slots for the card reader. It's not a problem. This code is wonderful! I appreciate it. And, you could have fooled me that you're not "that experienced"! I appreciate your help. Edited by Dougiefresh

Share this post


Link to post
Share on other sites
MadBoy

The code returns 0 for any of the slots for the card reader. It's not a problem. This code is wonderful! I appreciate it. And, you could have fooled me that you're not "that experienced"! I appreciate your help.

Hrmms, are those visible as a removable disk? I just used my sd card reader and it worked fine reporting FlashMedia?


My little company: Evotec (PL version: Evotec)

Share this post


Link to post
Share on other sites
Dougiefresh

Hrmms, are those visible as a removable disk? I just used my sd card reader and it worked fine reporting FlashMedia?

Yeah. Hold on, let me try detecting it with media in the drive.... I'll be right back....

EDIT: I'm back. With media in the reader, the code picked up the PNP device ID. Sorry about the false alarm! Thanks again.

Edited by Dougiefresh

Share this post


Link to post
Share on other sites
ptrex

@all

Tried it. Doesn't return any devices

Sorry guys but the WMI code provided only return data from devices that are connected the PC.

It will not return PNP ID's of devices that are connected in the network, like Wireless routers etc..

the code example I provided will return all UPnP ID info is the conditions is met that the device is UPnP compatible AND

your (XP) firewall does't block UPnP trafic.

So in your case if it didnt return anything 1 of the 2 requirements are not met.

regards,

ptrex

Share this post


Link to post
Share on other sites
Dougiefresh

Don't care about devices attached to the network. Sorry....

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
Sign in to follow this  

×