Hallo
Gibt es eine Möglichkeit den Pfad zu einem USB-Stick anhand dessen USB Device ID herauszufinden, um auf den Inhalt zugreifen zu können?
Gruß
Atalanttore
Zugriff auf Inhalt eines USB-Sticks mittels USB Device ID
-
- User
- Beiträge: 407
- Registriert: Freitag 6. August 2010, 17:03
Wenn es unter Linux und Windows funktionieren würde, wäre ich vollkommen zufrieden.
Gruß
Atalanttore
Gruß
Atalanttore
Für beides geht das nicht mit dem gleichen Code. Unter Linux sollte eigentlich alles unter /sys zu finden sein. Kann etwas hakelig werden, aber geht bestimmt. Oder du hörst auf die udev Ereignisse (habe ich gestern ein bisschen Code zu hier gepostet) und veknüpfts die Ereignisse durch ihre Daten. Erst kommt das USB device, dann das Blockdevice. Mit lsblk kann man (mit nettem json) erfahren, wo das blockdevice hin gemounted wurde.
Windows - kA. Auf der Ebene habe ich damit noch nicht gearbeitet.
Windows - kA. Auf der Ebene habe ich damit noch nicht gearbeitet.
-
- User
- Beiträge: 407
- Registriert: Freitag 6. August 2010, 17:03
Okay. Dann werde ich das mal probieren.
Gruß
Atalanttore
Gruß
Atalanttore
-
- User
- Beiträge: 407
- Registriert: Freitag 6. August 2010, 17:03
Ich habe jetzt mehrere Sachen getestet, aber funktioniert hat nur folgendes Skript zur Erkennung von USB-Sticks, dass ich mit Informationen aus den Weiten des Internets zusammengebastelt habe.
Kann man mit den von dieser Funktion zurückgelieferten Daten schon den Einhängepunkt des USB-Sticks herausfinden?
Gruß
Atalanttore
Code: Alles auswählen
#!/usr/bin/python3
from usb.core import find
from usb.util import find_descriptor
DEVICE_CLASS_MASS_STORAGE = 0x0
INTERFACE_CLASS_MASS_STORAGE = 0x8
def get_mass_storage():
for device in find(find_all=True, bDeviceClass=DEVICE_CLASS_MASS_STORAGE):
for descriptor in device:
if find_descriptor(descriptor, bInterfaceClass=INTERFACE_CLASS_MASS_STORAGE) is not None:
return device
print(get_mass_storage())
Gruß
Atalanttore
-
- User
- Beiträge: 407
- Registriert: Freitag 6. August 2010, 17:03
@__deets__: Dann hoffe ich mal das Beste (Open Source) und erwarte das Schlimmste (Closed Source mit NDA).
Was hast du eigentlich mit Blockdevice in "Erst kommt das USB device, dann das Blockdevice" gemeint?
Gruß
Atalanttore
Was hast du eigentlich mit Blockdevice in "Erst kommt das USB device, dann das Blockdevice" gemeint?
Gruß
Atalanttore
Ein externes Windows-Programm, dass USB-Devices in einem Windows Fenster darstellt klingt jetzt nicht wie eine plattformunabhängige Lösung für Python.
Selbst wenn es ein CLI hat, kommt man sicher auch selbst an die Information.
Selbst wenn es ein CLI hat, kommt man sicher auch selbst an die Information.
@Atalanttore: Nur damit ich das richtig verstehe: Du hast VID und PID des USB-Sticks und möchtest anhand dieser Angaben herausfinden, wo er ins System eingehängt ist, korrekt?
Die meisten USB-Sticks verwenden eine generische VID und eine generische PID die bei den meisten identisch ist. Was ja auch logisch ist. Bist du dir dessen bewusst? Ist der Stick so speziell, dass er eine eigene Geräteklasse hat? Falls nicht, kann es im Zweifelsfall dazu kommen, dass man den falschen von 2 angesteckten USB-Sticks auswählt, weil VID und PID identisch sind.
Die meisten USB-Sticks verwenden eine generische VID und eine generische PID die bei den meisten identisch ist. Was ja auch logisch ist. Bist du dir dessen bewusst? Ist der Stick so speziell, dass er eine eigene Geräteklasse hat? Falls nicht, kann es im Zweifelsfall dazu kommen, dass man den falschen von 2 angesteckten USB-Sticks auswählt, weil VID und PID identisch sind.
So ungewöhnlich ist das nicht.
Gefühlt haben die eine Hälfte der USB-Stick "058f:6387" und die andere Hälfte "abcd:1234" als vid:pid.
Ungefühlt sind es alle, die ich hier habe.
Eigentlich ist das auch naheliegend, dass Hersteller das machen. Die Geräteklasse wird gebraucht, um den korrekten Treiber zu laden. Und wenn ein Treiber für einen generischen Massenspeicher reicht, geben die dem halt die vid:pid dafür mit.
Gefühlt haben die eine Hälfte der USB-Stick "058f:6387" und die andere Hälfte "abcd:1234" als vid:pid.
Ungefühlt sind es alle, die ich hier habe.
Eigentlich ist das auch naheliegend, dass Hersteller das machen. Die Geräteklasse wird gebraucht, um den korrekten Treiber zu laden. Und wenn ein Treiber für einen generischen Massenspeicher reicht, geben die dem halt die vid:pid dafür mit.
Das fuer mass-storage-devices (oder generell USB -Gearteklasssen) die VID:PID ausschliesslich eine Rolle spielen, waere mir neu.
Bei meinem gerade mal eingesteckten USB-Stick kommt mit lsusb folgendes raus:
Es gibt zwar durchaus eine Liste der "ungewoehnlichen" USB mass storage devices, und die werden tatsaechlich nach VID:PID aufgeloest. Aber genauso wird mit "bInterfaceClass 8 Mass Storage" gearbeitet. Und ganz generell ist das ja auch die Idee hinter USB und seinen Deskriptoren. Den ganzen Aufstand braeuchte man ja nicht, wenn man nur zwei 16-Bit-Nummer zugrunde legt.
Und eine Serien-Nummer gibt's auch, also auch damit kann man einen Stick individuell identifizieren. Wird ja auch permanent gemacht. Wenn du nun natuerlich einen Stick aus einem chinesischen Ueberraschungsei benutzt, dann ist da dann irgendwann Hopfen und Malz verloren.
Bei meinem gerade mal eingesteckten USB-Stick kommt mit lsusb folgendes raus:
Code: Alles auswählen
Bus 002 Device 078: ID 0781:5580 SanDisk Corp. SDCZ80 Flash Drive
Device Descriptor:
bLength 18
bDescriptorType 1
bcdUSB 3.00
bDeviceClass 0 (Defined at Interface level)
bDeviceSubClass 0
bDeviceProtocol 0
bMaxPacketSize0 9
idVendor 0x0781 SanDisk Corp.
idProduct 0x5580 SDCZ80 Flash Drive
bcdDevice 0.10
iManufacturer 1 SanDisk
iProduct 2 Extreme
iSerial 3 XXXXX
bNumConfigurations 1
Configuration Descriptor:
bLength 9
bDescriptorType 2
wTotalLength 44
bNumInterfaces 1
bConfigurationValue 1
iConfiguration 0
bmAttributes 0x80
(Bus Powered)
MaxPower 100mA
Interface Descriptor:
bLength 9
bDescriptorType 4
bInterfaceNumber 0
bAlternateSetting 0
bNumEndpoints 2
bInterfaceClass 8 Mass Storage
bInterfaceSubClass 6 SCSI
bInterfaceProtocol 80 Bulk-Only
iInterface 0
Endpoint Descriptor:
bLength 7
bDescriptorType 5
bEndpointAddress 0x81 EP 1 IN
bmAttributes 2
Transfer Type Bulk
Synch Type None
Usage Type Data
wMaxPacketSize 0x0400 1x 1024 bytes
bInterval 0
bMaxBurst 15
Endpoint Descriptor:
bLength 7
bDescriptorType 5
bEndpointAddress 0x02 EP 2 OUT
bmAttributes 2
Transfer Type Bulk
Synch Type None
Usage Type Data
wMaxPacketSize 0x0400 1x 1024 bytes
bInterval 0
bMaxBurst 15
Binary Object Store Descriptor:
bLength 5
bDescriptorType 15
wTotalLength 22
bNumDeviceCaps 2
USB 2.0 Extension Device Capability:
bLength 7
bDescriptorType 16
bDevCapabilityType 2
bmAttributes 0x00000002
Link Power Management (LPM) Supported
SuperSpeed USB Device Capability:
bLength 10
bDescriptorType 16
bDevCapabilityType 3
bmAttributes 0x00
wSpeedsSupported 0x000e
Device can operate at Full Speed (12Mbps)
Device can operate at High Speed (480Mbps)
Device can operate at SuperSpeed (5Gbps)
bFunctionalitySupport 1
Lowest fully-functional device speed is Full Speed (12Mbps)
bU1DevExitLat 7 micro seconds
bU2DevExitLat 101 micro seconds
Device Status: 0x0000
(Bus Powered)
Und eine Serien-Nummer gibt's auch, also auch damit kann man einen Stick individuell identifizieren. Wird ja auch permanent gemacht. Wenn du nun natuerlich einen Stick aus einem chinesischen Ueberraschungsei benutzt, dann ist da dann irgendwann Hopfen und Malz verloren.
Natürlich sind das USB-Sticks aus chinesischen Überraschungseiern. Und im Zweifelsfall sind es ja die, die irgendwo in der Schreibtischschublade liegen.
Tatsächlich tut man sich unter Windows unglaublich schwer damit mit vid und pid voran zu kommen.
Das einfachste wäre, wenn man die "Volume Serial Number" dafür nehmen könnte. Da kann man sich per WMIC behelfen:
Tatsächlich tut man sich unter Windows unglaublich schwer damit mit vid und pid voran zu kommen.
Das einfachste wäre, wenn man die "Volume Serial Number" dafür nehmen könnte. Da kann man sich per WMIC behelfen:
Code: Alles auswählen
import io
import subprocess
import sys
WMICPATH = r"C:\Windows\System32\wbem\wmic.exe"
def get_path_for_volumeserialnumber(number):
if sys.platform == "win32":
command = (WMICPATH, "logicaldisk", "get", "Caption,VolumeSerialNumber")
proc = subprocess.Popen(command, stdout=subprocess.PIPE)
for line in io.TextIOWrapper(proc.stdout, encoding="utf-8"):
try:
caption, serial_number = line.strip().split()
if serial_number == number:
return caption
except ValueError:
pass
else:
raise NotImplementedError("This works only on Windows")
if __name__ == "__main__":
print(get_path_for_volumeserialnumber("C0D2B631"))
Und hiermit sollte man unter Windows anhand der vid und der pid den Laufwerksbuchstaben ermitteln können.
Die Infos kommen aus der Registry.
Aber ich lege nicht meine Hand dafür ins Feuer, dass das immer tut.
Zumindest die Registry-Einträge unter HLM\SYSTEM\MountedDevices scheinen nicht so richtig konsistent zu sein. Da taucht bei mir der Eintrag für 2 Laufwerke auf, obwohl nur eins davon existiert. Es scheint aber, als würde der erste beim Durchlaufen auch der Neueste sein, deshalb müsste es passen.
Und ich tue mir nach wie vor schwer mit dieser Byte-Geschichte.
Die Infos kommen aus der Registry.
Code: Alles auswählen
import sys
import winreg
def find_device_id(vendor_id, product_id):
subkey = r"Software\Microsoft\Windows\CurrentVersion\Explorer\MountPoints2\CPC\Volume"
volumeroot = winreg.OpenKey(winreg.HKEY_CURRENT_USER, subkey)
volumenames = []
try:
for i in range(sys.maxsize):
volumenames.append(winreg.EnumKey(volumeroot, i))
except OSError:
pass
searchstring = bytearray("VID_{0}&PID_{1}".format(vendor_id, product_id),
"UTF-8")
for volumename in volumenames:
volumekey = winreg.OpenKey(volumeroot, volumename)
data_value = winreg.QueryValueEx(volumekey, "Data")[0]
cleared_value = data_value.replace(b"\0", b"")
if searchstring in cleared_value:
device_id = cleared_value[cleared_value.find(b"{"):
cleared_value.find(b"}")]
return device_id
def find_mountpoint_for_device(device_id):
subkey = r"SYSTEM\MountedDevices"
deviceroot = winreg.OpenKey(winreg.HKEY_LOCAL_MACHINE, subkey)
try:
for i in range(sys.maxsize):
name, value, type_ = winreg.EnumValue(deviceroot, i)
cleared_value = value.replace(b"\0", b"")
if device_id in cleared_value and "DosDevices" in name:
return name.split("\\")[-1]
except OSError:
pass
def get_path_for_usbid(vendor_id, product_id):
if sys.platform == "win32":
device_id = find_device_id(vendor_id, product_id)
if device_id:
mountpoint = find_mountpoint_for_device(device_id)
return mountpoint
else:
raise NotImplementedError("This works only on Windows")
if __name__ == "__main__":
print(get_path_for_usbid("ABCD", "1234"))
Zumindest die Registry-Einträge unter HLM\SYSTEM\MountedDevices scheinen nicht so richtig konsistent zu sein. Da taucht bei mir der Eintrag für 2 Laufwerke auf, obwohl nur eins davon existiert. Es scheint aber, als würde der erste beim Durchlaufen auch der Neueste sein, deshalb müsste es passen.
Und ich tue mir nach wie vor schwer mit dieser Byte-Geschichte.
-
- User
- Beiträge: 407
- Registriert: Freitag 6. August 2010, 17:03
Es müsste ein Signal ausgelöst werden, wenn ein USB-Speicher angesteckt wird.
@sparrow: Vielen Dank für den Code.
Gruß
Atalanttore
- __blackjack__
- User
- Beiträge: 13004
- Registriert: Samstag 2. Juni 2018, 10:21
- Wohnort: 127.0.0.1
- Kontaktdaten:
@Atalanttore: Wäre schön, ist aber nicht vorgesehen. Unter Linux kann man sich per DBus über solche Ereignisse informieren lassen.
“Most people find the concept of programming obvious, but the doing impossible.” — Alan J. Perlis
Eh. Was hat das denn mit deiner Frage und meiner Antwort darauf zu tun?Atalanttore hat geschrieben: ↑Dienstag 5. März 2019, 22:43Es müsste ein Signal ausgelöst werden, wenn ein USB-Speicher angesteckt wird.
Wobei ich die Frage glaube ich auch falsch gelesen habe. Ein Blockdevice ist die Bezeichnung fuer Massenspeicher und ihrere Repraesentation in Linux. Mehr oder minder. Nicht, dass man das auch nachschauen koennte. https://unix.stackexchange.com/question ... ock-device
Und signale helfen doch nicht. Die haben keine Parameter. Woher weisst du denn, welches von den dutzenden /dev/sd*, /dev/nvme* oder was auch immer nun gerade das Geraet ist, das angesteckt wurde?