Get PID/VID of USB using Drive Letter

Viewed 403

I am trying to create a script that relates the Drive Letter (i.e. D:\ or E:\ etc) with the USB VID/PID (i.e. "USB\VID_XXXX&PID_XXX\XXXXXXXXXXXXXXX"). I trying searching whole of internet but couldn't find anything promising except the one here: See accepted answer at the top

This answer is able to resolve the issue but I need it in powershell. I have tried converting the code to powershell but its not working I would really appreciate if any help can be provided.

Note: You can get the device InstanceID with below snippet:

#Declaring variable & getting information about all the connected USB devices
$InstanceID = ""
$ConnectedDevices = Get-PnpDevice -Class "USB"

#Applying filter for USB Mass Storage Device and storing the instance ID to be used at later stage
ForEach($USB in $ConnectedDevices)
{
    If ($USB.FriendlyName -contains "USB Mass Storage Device")
        {  
            $InstanceID = $USB.DeviceID
        } 
}

Here is the code that doesn't work (or you can call the failed effort):

$AllDevices = Get-CimInstance -ClassName Win32_USBHub
$InstanceID = "USB\VID_XXXX&PID_XXX\XXXXXXXXXXXXXXX"
$AllProperties
$USBObjects
$SecondIdentity
$AllDrives = Get-CimInstance -ClassName Win32_DiskDrive
Foreach($device in $AllDevices)
{
    If($device.DeviceID -like $InstanceID)
    {
        $AllProperties = $device
    }
}

Function FindPath
{
    ForEach($DeviceProperty in $AllProperties)
    {
        If($Device.Description -Contains "*USB Mass Storage Device")
        {
            $Entity = $Device.DeviceID

            ForEach($Controller in $Entity.GetRelated('Win32_USBController'))
            {
                $USBControllerID = gwmi win32_diskdrive | %{gwmi -Query "ASSOCIATORS OF {Win32_USBController.DeviceID='" + $Controller.DeviceID + "'} WHERE AssocClass = Win32_USBController"}
                ForEach($Obj in $USBControllerID)
                {
                    If($Obj -contains "Device ID")
                    {
                        $USBObjects = $Obj.DeviceID
                        $USBObjects 
                    }
                }
            }
        }

        $VidPidPosition = $USBObjects.Indexof($Entity)
        for($i = $VidPidPosition; $i -le $USBObjects.Count; $i++)
        {
            if($USBObjects.[i] -contains "USBSTOR")
            {
                $SecondIdentity = $USBObjects.[i]
            } 
        }
    }
}

Function GetDriveLetter
{
    FindPath
    ForEach($Drive in $AllDrives)
    {
        If($Drive.PNPDeviceID -eq $SecondIdentity)
        {
            ForEach($o in $Drive.GetRelated('Win32_DiskPartition'))
            {
                ForEach($i in $o.GetRelated('Win32_LogicalDisk'))
                {
                    Write-Output "Disk: " $i.Name
                }
            }
        }
    }
}
GetDriveLetter

Thanks in advance.

1 Answers

After some brainstorming, I could find an easier way of achieving this i.e. relating USB drive letter with PID/VID. If you notice, in the string "USB\VID_XXXX&PID_XXXX\123X5678X0987X543210XXXX", the string followed by last backslash, it is same in the "USBSTOR" string, which can be used to compare the two.

Below is the example code that can be utilized for reading drive letter from txt file & comparing it with PID/VID. Finally, if it matches, it will perform disconnect & reconnect using PNPUtil

    $ExitCode

Function USBActions()
{
    #Declaring variables, few of which will store all the information required to be used later
    $InstanceID = ""
    $ConnectedDevices = Get-PnpDevice -Class "USB"
    $UserSelection = ((Get-Content C:\SelectedDrive.txt).ToString()).Trim("\")

    $Disk = Get-WmiObject -Class Win32_logicaldisk -Filter "DriveType = '2'"
    $Driveletters = $Disk.DeviceID.ToString()

    $DiskPartition = $Disk.GetRelated('Win32_DiskPartition')
    $DiskDrive = $DiskPartition.getrelated('Win32_DiskDrive')

    #Applying filter for USB Mass Storage Device and storing the instance ID to be used at later stage
    ForEach($USB in $ConnectedDevices)
    {
        If ($USB.FriendlyName -contains "USB Mass Storage Device")
            {  
                $InstanceID = $USB.DeviceID
            } 
    }

    If($InstanceID -eq "")
    {
        Write-Output "No removable mass storage device detected. Exiting..."
        $ExitCode = 1
        Return $Exitcode
    }
    Else
    {
        #For each connected mass storage device, iterate the drive letters in nested ForEach
        ForEach ($Instance in $InstanceID)
        {
            ForEach($Dsk in $DiskDrive)
            {
              ForEach($DriveLetter in $DriveLetters)
              {
                #Check if drive letter from text file is same as the one Win32_DiskDrive class
                If($UserSelection -match $Driveletter)
                {
                    #Extract the string after last "\" in PID/VID instanceID & USBSTOR... string. 
                    $IndexOfIID = $InstanceID.LastIndexOf('\')
                    $USBSTOR = ($DiskDrive.PNPDeviceID).ToString()
                    $USBSTORCMP = $USBSTOR.LastIndexOf('\')
                    $ComparableString = $InstanceID.Substring(++$IndexOfIID)

                    #Compare the two
                    If($USBSTOR.Substring(++$USBSTORCMP) -match $ComparableString)
                    {
                        Write-Output "Drive matches DeviceID. Proceeding with disconnect & reconnect"
                    }
                }
                Else
                {
                    Write-Output "Selected drive doesn't match device ID. Exiting..."
                    Exit
                }
              }
           }
            pnputil -Remove-Device $InstanceID
            Write-Log "Performed USB disconnect & reconnect for $InstanceID"
        }

        #Run scan for all the connected USB devices to reconnected the disconnected ones in previous step
        pnputil -scan-devices
        $ExitCode = 0
        Return $Exitcode
    }
}
Related