Ich verwende aus dem VS2008 deutsch Sprache BASIC.
Mit Hilfe von WMI und Registry ist es mir gelungen die VID und PID der angeschlossenen USB-Festplatten zu ermitteln.
Aber nun klemmt es gewaltig.
Zum ersten habe ich entdeckt, daß die HID.DLL diese Möglichkeiten auch anbietet und ich überlege, diese auch zu nutzen. Aber über HidD_GetHidGuid(guid) bin ich nicht hinausgekommen.
Zum zweiten suche ich darin eine Möglichkeit, die (meiste?) USB-Devices auszulesen. Nur wirklich funktionierende Hinweise für BASIC habe ich nicht gefunden.
Es müßte auch mit den API's gehen, doch auch dafür habe ich keine funktionierenden Beispiele für die Suche nach angeschlossenen USB-Devices gefunden. Auch weiß ich nicht, was in die Struktur Guid einzutragen ist, damit man zB mit HidD_GetHidGuid ein bestimmtes USB-Device findet. Aber eigentlich weiß ich zu wenig über diese Materie.
Microsofts MSDN bietet eine Dokumentation an, diese enthält aber keine weiterführenden Beispiele. Es gibt eine große Anzahl von Firmen, die Libraries (auch gratis) anbieten, mit denen man sich durch die USB-Devices hanteln kann. Allerdings sind die meisten davon für C, C++, C#. Und ich kann nicht erwarten, daß diese auf anderen Rechnern installiert sind. Es müßte ja mit Bordmitteln von VS gehen.
Kann mir jemand Dokumentationen und/oder funktionierende Beispiele benennen, die mir weiterhelfen? Irgendwie habe ich den Eindruck, daß die Ratgeber mehr herumreden als mit Wissen glänzen. Auf die Frage nach dem Finden der VID und PID wird zB. gemeint "Das **müßte** eigentlich mit WMI gehen". No comment.
> Ich verwende aus dem VS2008 deutsch Sprache BASIC.
> Mit Hilfe von WMI und Registry ist es mir gelungen die VID und PID der > angeschlossenen USB-Festplatten zu ermitteln.
> Aber nun klemmt es gewaltig.
> Zum ersten habe ich entdeckt, daß die HID.DLL diese Möglichkeiten auch > anbietet und ich überlege, diese auch zu nutzen. Aber über > HidD_GetHidGuid(guid) bin ich nicht hinausgekommen.
> Zum zweiten suche ich darin eine Möglichkeit, die (meiste?) USB-Devices > auszulesen. > Nur wirklich funktionierende Hinweise für BASIC habe ich nicht gefunden.
> Es müßte auch mit den API's gehen, doch auch dafür habe ich keine > funktionierenden Beispiele für die Suche nach angeschlossenen USB-Devices > gefunden. Auch weiß ich nicht, was in die Struktur Guid einzutragen ist, > damit man zB mit HidD_GetHidGuid ein bestimmtes USB-Device findet. > Aber eigentlich weiß ich zu wenig über diese Materie.
> Microsofts MSDN bietet eine Dokumentation an, diese enthält aber keine > weiterführenden Beispiele. > Es gibt eine große Anzahl von Firmen, die Libraries (auch gratis) anbieten, > mit denen man sich durch die USB-Devices hanteln kann. Allerdings sind die > meisten davon für C, C++, C#. Und ich kann nicht erwarten, daß diese auf > anderen Rechnern installiert sind. Es müßte ja mit Bordmitteln von VS gehen.
> Kann mir jemand Dokumentationen und/oder funktionierende Beispiele benennen, > die mir weiterhelfen? > Irgendwie habe ich den Eindruck, daß die Ratgeber mehr herumreden als mit > Wissen glänzen. > Auf die Frage nach dem Finden der VID und PID wird zB. gemeint "Das > **müßte** eigentlich mit WMI gehen". No comment.
> Mit bestem Dank im Voraus
> Wolfgang
Aufrund deiner Frage habe ich heute selbst mal den halben Tag mit der Angelegenheit beschäftigt da ich diesbezüglich auch noch völlig "blank war".
Es kommt jetzt natürlich darauf an, was du genau wissen willst. Unten zunächst einmal der Code zum Auflisten der HID-Geräte. Für die USB-Geräte - das sind i.d.R. die USB-Controller - musst du GUID_DEVCLASS_USB verwenden (s. auskommentierte Zeile). Die GUIDs weiterer "Setup Classes" findest du hier:
Const DIGCF_DEFAULT As UInt32 = 1 Const DIGCF_PRESENT As UInt32 = 2 Const DIGCF_ALLCLASSES As UInt32 = 4 Const DIGCF_PROFILE As UInt32 = 8 Const DIGCF_DEVICEINTERFACE As UInt32 = &H10
<StructLayout(LayoutKind.Sequential)> _ Structure SP_DEVINFO_DATA Public Size As Int32 Public guid As Guid Public devInst As UInt32 Public Reserved As UIntPtr End Structure
Shared ReadOnly INVALID_HANDLE_VALUE As IntPtr = New IntPtr(-1)
Shared ReadOnly GUID_DEVCLASS_USB As Guid = New Guid("36fc9e60-c465-11cf-8056-444553540000") Shared ReadOnly GUID_DEVCLASS_HID As Guid = New Guid("745a17a0-74d3-11d0-b6fe-00a0c90f57da")
Declare Auto Function SetupDiGetClassDevs Lib "setupapi.dll" ( _ <[In]()> ByVal Classguid As IntPtr, _ <[In](), MarshalAs(UnmanagedType.LPTStr)> ByVal Enumerator As String, _ <[In]()> ByVal hWndParent As IntPtr, _ <[In]()> ByVal Flags As UInt32) _ As IntPtr
Declare Auto Function SetupDiGetClassDevs Lib "setupapi.dll" ( _ <[In]()> ByRef Classguid As Guid, _ <[In](), MarshalAs(UnmanagedType.LPTStr)> ByVal Enumerator As String, _ <[In]()> ByVal hWndParent As IntPtr, _ <[In]()> ByVal Flags As UInt32) _ As IntPtr
Declare Auto Function SetupDiDestroyDeviceInfoList Lib "setupapi.dll" ( _ <[In]()> ByVal DeviceInfoSet As IntPtr) _ As Boolean
Declare Auto Function SetupDiEnumDeviceInfo Lib "setupapi.dll" ( _ <[In]()> ByVal DeviceInfoSet As IntPtr, _ <[In]()> ByVal MemberIndex As UInt32, _ <Out()> ByRef DeviceInfoData As SP_DEVINFO_DATA) _ As Boolean
Declare Auto Function SetupDiGetDeviceInstanceId Lib "setupapi.dll" ( _ <[In]()> ByVal DeviceInfoSet As IntPtr, _ <[In]()> ByRef DeviceInfoData As SP_DEVINFO_DATA, _ <[Out]()> ByVal DeviceInstanceId As Text.StringBuilder, _ <[In]()> ByVal DeviceInstanceIdSize As UInt32, _ <[Out]()> ByRef RequiredSize As UInt32 _ ) As Boolean
If hDevInfo = INVALID_HANDLE_VALUE Then ThrowWin32Exception("SetupDiGetClassDevs") Else Try Do Dim MemberIndex As UInt32 Dim DeviceInfo As SP_DEVINFO_DATA
If SetupDiEnumDeviceInfo(hDevInfo, MemberIndex, DeviceInfo) Then Dim RequiredSize As UInt32 Dim DeviceInstanceID As New Text.StringBuilder
DeviceInstanceID.Length = 500
If SetupDiGetDeviceInstanceId(hDevInfo, DeviceInfo, DeviceInstanceID, CUInt(DeviceInstanceID.Capacity), RequiredSize) Then Debug.WriteLine("Device instance id: " & DeviceInstanceID.ToString) Else ThrowWin32Exception("SetupDiGetDeviceInstanceId") End If Else Dim Win32Error = Marshal.GetLastWin32Error
If Win32Error = ERROR_NO_MORE_ITEMS Then Exit Do Else ThrowWin32Exception(Win32Error, "SetupDiEnumDeviceInfo") End If End If
MemberIndex += 1UI Loop Finally If Not SetupDiDestroyDeviceInfoList(hDevInfo) Then ThrowWin32Exception("SetupDiDestroyDeviceInfoList") End If End Try End If
End Sub Shared Sub ThrowWin32Exception(ByVal Location As String)
> Aufrund deiner Frage habe ich heute selbst mal den halben Tag mit der > Angelegenheit besch ftigt da ich diesbez glich auch noch v llig > "blank war".
Danke f r den halben Tag wegen meinerFrage. Du hattest aber sicherlich auch etwas davon. Wenn man das nicht braucht, besteht auch kein unmittelbarer Anla zur Informationsgewinnung.
Mir scheint, da HID ein noch unbeackertes Terrain ist. Weder in .NET noch in jenen Varianten, die unmittelbar mit den Win-API?s arbeiten. Viele Fragen im Netz, aber wenig brauchbare Antworten. Die Doku in VB ist h chst akademisch und ohne Beispiele, die meist mehr sagen als alles brige.
Darauf gesto en bin ich, weil ich ermitteln mu , welche USB-Massenspeicher als Verzeichnisse gemountet sind. Wenn sie als Laufwerke eingebunden sind ist es ja einfach. Hoffentlich geht das mit HID berhaupt.
> Hallo Armin! > "Armin Zingler" <az.nos...@freenet.de> wrote in message > news:8s2sa2F3anU1@mid.uni-berlin.de... >> Am 16.02.2011 10:27, schrieb Wolfgang Badura:
>> Aufrund deiner Frage habe ich heute selbst mal den halben Tag mit der >> Angelegenheit beschäftigt da ich diesbezüglich auch noch völlig >> "blank war".
> Danke für den halben Tag wegen meinerFrage. Du hattest aber sicherlich auch > etwas davon. > Wenn man das nicht braucht, besteht auch kein unmittelbarer Anlaß zur > Informationsgewinnung.
Ich habe Newsgroups schon immer vor allem auf diese Weise als Fortbildungseinrichtung verstanden. :) Ich steige nur dann tiefer ein, wenn es mich auch selbst interessiert.
> Mir scheint, daß HID ein noch unbeackertes Terrain ist. > Weder in .NET noch in jenen Varianten, die unmittelbar mit den Win-API?s > arbeiten. > Viele Fragen im Netz, aber wenig brauchbare Antworten. > Die Doku in VB ist höchst akademisch und ohne Beispiele, die meist mehr > sagen als alles übrige.
> Darauf gestoßen bin ich, weil ich ermitteln muß, welche USB-Massenspeicher > als Verzeichnisse gemountet sind.
Und bist du damit schon weitergekommen? Werde da heute auch mal nachforschen (aber später erst). Letzter Stand war, dass ich per DeviceIOControl mit ControlCode=IOCTL_VOLUME_GET_VOLUME_DISK_EXTENTS angewandt auf "\\.\K:" (wobei K: ein USB-Stick ist) nur die Rückmeldung "nicht unterstützt" (o.ä.) bekommen habe.
Bei dir wäre es dann die andere Richtung vom physikalischen Gerät ausgehend.
Wie gesagt, werde da mal weitersuchen....
> Wenn sie als Laufwerke eingebunden sind ist es ja einfach. > Hoffentlich geht das mit HID überhaupt.
Was ist denn gegeben und was willst du herausfinden? Bei USB verstehe ich dein Ansinnen aber bei HID nicht ganz.
> Bei dir wäre es dann die andere Richtung vom physikalischen Gerät > ausgehend.
Genau! Ein USB-Stick wurde vom Admin als Verzeichnis gemountet. In welches?
In der Registry gibt es einen Zweig
HKEY_CURRENT_USER\Software\Microsoft\Windows\CurrentVersion\Explorer\MountP oints2\CPC\LocalMOF F:\Hama\CF\ F:\Hama\SD\ F:\Hama\xD\ F:\SanDisk\ Dort stehen Die Verzeichnisse drin, aber ich fand bisher (noch) keinen Zusammenhang zum Stick.
> Wie gesagt, werde da mal weitersuchen....
>> Wenn sie als Laufwerke eingebunden sind ist es ja einfach. >> Hoffentlich geht das mit HID überhaupt.
> Was ist denn gegeben und was willst du herausfinden? Bei USB > verstehe ich dein Ansinnen aber bei HID nicht ganz.
Wenn Sie als eigenes Laufwerk erscheinen, wie zB "G:\" dann gehts ja mit der WMI, da finde ich auch Vid und Pid problemlos. Wenn aber als Verzeichnis? Ich dachte, daß dies vielleicht mit dem HID geht. Mein vielleicht nicht ganz unwesentlicher Fortschritt war bisher, mittels WMI und Registry die Vid und Pid aller USB-Geräte, soweit vorhanden, zu ermitteln. Und jetzt gehts nicht mehr weiter.
Damit im Zusammenhang habe ich ein weiteres Problem geortet, für welches ich hier aber einen neuen Thread öffnen werde.
Noch eine Frage: Gibt es ein Forum für VB Net, in dem ich Dich ev. auch wiederfinden kann?
>> Bei dir w re es dann die andere Richtung vom physikalischen Ger t >> ausgehend.
> Genau! > Ein USB-Stick wurde vom Admin als Verzeichnis gemountet. > In welches?
Ich wei gar nicht, ob diese Info in dieser Richtung berhaupt verf gbar ist. Ich denke eher, dass man anhand des gemounteten Verzeichnisses herausfinden kann, um welches Volume es sich handelt.
> HKEY_CURRENT_USER\Software\Microsoft\Windows\CurrentVersion\Explorer\MountP oints2\CPC\LocalMOF > F:\Hama\CF\ > F:\Hama\SD\ > F:\Hama\xD\ > F:\SanDisk\ > Dort stehen Die Verzeichnisse drin, aber ich fand bisher (noch) keinen > Zusammenhang zum Stick.
>> Wie gesagt, werde da mal weitersuchen....
>>> Wenn sie als Laufwerke eingebunden sind ist es ja einfach. >>> Hoffentlich geht das mit HID berhaupt.
>> Was ist denn gegeben und was willst du herausfinden? Bei USB >> verstehe ich dein Ansinnen aber bei HID nicht ganz.
> Wenn Sie als eigenes Laufwerk erscheinen, wie zB "G:\" dann gehts ja mit der > WMI, da finde ich auch Vid und Pid problemlos. > Wenn aber als Verzeichnis? Ich dachte, da dies vielleicht mit dem HID geht. > Mein vielleicht nicht ganz unwesentlicher Fortschritt war bisher, mittels > WMI und Registry die Vid und Pid > aller USB-Ger te, soweit vorhanden, zu ermitteln. Und jetzt gehts nicht mehr > weiter.
Mit den Registry-Zugriffen und auch mit WMI habe ich es nicht so. Ich verwende lieber (auch) die API.
Vielleicht hilft das schon weiter. Ich wollte zuvor erst einmal herausfinden, wieviele "physical disks" es berhaupt gibt. Ich habe nirgends etwas dazu gefunden. Die einzig brauchbare Antwort von einem MVP im Bereich WDK war das, was ich schon vermutet hatte: Mit der Funktion SetupDiGetClassDevs und der GUID f r die Klasse "DiskDrives" l sst sich immerhin die Anzahl feststellen. Das ist erforderlich, wenn man anschlie end mit CreateFile("\\.\PhysicalDrive#") alle physikalischen Laufwerke durchgehen will. F r jedes Laufwerk lassen sich dann mit DeviceIOControl und IOCTL_DISK_GET_DRIVE_LAYOUT_EX die Partitionsinformationen ermitteln:
> Damit im Zusammenhang habe ich ein weiteres Problem geortet, > f r welches ich hier aber einen neuen Thread ffnen werde.
> Noch eine Frage: Gibt es ein Forum f r VB Net, in dem ich Dich ev. auch > wiederfinden kann?
Nur "nebenan" in m.p.dotnet.languages.vb In einem Forum bin ich nicht. Ich hatte nach Abschaltung des MSFT Newsservers keine Lust, mich dazu n tigen zu lassen, der privaten MSFT Community beizutreten.
Solange es die m.p-Gruppen auf irgendeinem Server gibt, werde ich sie auch lesen. Au erdem de.comp.lang.misc. Ein Eintrag auf Einrichtung einer Gruppe f r VB.Net unter der de.comp-Hierarchie wurde gestellt, ich muss aber zugeben, dass ich den Verlauf nicht weiter verfolgt hatte.
>>> Bei dir w re es dann die andere Richtung vom physikalischen Ger t >>> ausgehend.
>> Genau! >> Ein USB-Stick wurde vom Admin als Verzeichnis gemountet. >> In welches?
> Ich wei gar nicht, ob diese Info in dieser Richtung berhaupt > verf gbar ist. Ich denke eher, dass man anhand des gemounteten > Verzeichnisses herausfinden kann, um welches Volume es sich > handelt.
>> In der Registry gibt es einen Zweig
>> HKEY_CURRENT_USER\Software\Microsoft\Windows\CurrentVersion\Explorer\MountP oints2\CPC\LocalMOF >> F:\Hama\CF\ >> F:\Hama\SD\ >> F:\Hama\xD\ >> F:\SanDisk\ >> Dort stehen Die Verzeichnisse drin, aber ich fand bisher (noch) keinen >> Zusammenhang zum Stick.
Also, Stand der Dinge:
1. Mit FindFirstVolume/FindNextVolume alle "unique volume names" ermitteln Sie sind im Format \\?\Volume{GUID}\
2. F r jedes gefundenen Volumes: FindFirstVolumeMountPoint/FindNextVolumeMountPoint aufrufen. Wenn du das f r das Volume, das auch den Buchstaben F:\ tr gt, durchf hrst, bekommst du die Verzeichnisse - Hama\CF\ - Hama\SD\ - usw
3. bergib "\\?\Volume{GUID}\Hama\CF\" (usw) an die Funktion GetVolumeNameForVolumeMountPoint. Ergebnis ist das Volume, das du gemountet hast, also z.B. das auf dem USB-Stick.
Die Richtung ist also, wie schon vermutet, eine andere: Alle gemounteten Verzeichnisse ermitteln und nachpr fen, woher sie kommen. Du musst nur die sammeln, die vom USB-Stick stammen.
Bleibt nur die Frage: Woran willst du den USB-Stick identifizieren? Was ist also gegeben? Ein Laufwerksbuchstabe? Wenn ja, dann m sstets du nur f r den LW-Buchstaben GetVolumeNameForVolumeMountPoint aufrufen und hast somit den "unique volume name". Den musst du dann mit den eindeutigen Volume-Namen aller gefundenen Mount points vergleichen. Die gefundenen Mountpoints sind dann die des USB-Sticks.
Um dann vom Volume aus auch noch das physikalische Device zu ermitteln, m sstest du DeviceIOControl mit ControlCode=IOCTL_VOLUME_GET_VOLUME_DISK_EXTENTS aufrufen. Da sich ein Volume theoretisch ber mehrere physikalische Disks erstrecken kann, w rde es auch hier in diese Richtung funktionieren.
So, mehr war heute nicht drin. ;-)
(Code habe ich auch, aber der sieht sehr, h, experimentell aus.)
> Ich weiß gar nicht, ob diese Info in dieser Richtung überhaupt > verfügbar ist. Ich denke eher, dass man anhand des gemounteten > Verzeichnisses herausfinden kann, um welches Volume es sich > handelt.
Im Internet habe ich eine Site mit VB6 Code gefunden, die das können soll. (http://www.emmet-gray.com/Articles/USB_SerialNumbers.htm) Es ist sehr viel Code anzupassen, wird also dauern. Solange ich mit Definitionsproblemen kämpfe, wird das auch nichts. Aber da hast Du mir schon geholfen. Ist leider aufwendig, da es sehr viele API?s gibt, um zu diesem Ziel zu gelangen. Erst nach fehlerfreiem Durchlauf werde ich wissen ob es geht oder nicht. Es gibt in .Net ja schon eine Anbindung an die HID-Programmierung. Daher werde ich es auch damit versuchen.
> Mit den Registry-Zugriffen und auch mit WMI habe ich es nicht so. > Ich verwende lieber (auch) die API.
Nachdem ich damit schon oft arbeiten mußte, ist mir das ziemlich geläufig geworden. Denn auch in VBS-Skripts läßt sich das einfach umsetzen. Und nicht überall sind alle zB. VB6 Controls registriert. Manchmal mit dem Killbit nach irgend einem Win Update versehen. VBS gibt es praktisch auf allen Windowsrechnern sicher ab XP.
> Vielleicht hilft das schon weiter. Ich wollte zuvor erst einmal > herausfinden, wieviele "physical disks" es überhaupt gibt. > Ich habe nirgends etwas dazu gefunden. Die einzig brauchbare > Antwort von einem MVP im Bereich WDK war das, was ich schon > vermutet hatte: Mit der Funktion SetupDiGetClassDevs und > der GUID für die Klasse "DiskDrives" lässt sich immerhin > die Anzahl feststellen. Das ist erforderlich, wenn man > anschließend mit CreateFile("\\.\PhysicalDrive#") alle > physikalischen Laufwerke durchgehen will. Für jedes Laufwerk > lassen sich dann mit DeviceIOControl und IOCTL_DISK_GET_DRIVE_LAYOUT_EX > die Partitionsinformationen ermitteln:
SetupDiGetClassDevs ist mir geläufig.
Es gibt das WMI-Äquivalent Set wmiServices = GetObject _ ("winmgmts:{impersonationLevel=Impersonate}!//" & strComputer) Set wmiDiskDrives = wmiServices.ExecQuery _ ("SELECT * FROM Win32_DiskDrive") für die Drives,
Set wmiDiskPartitions = wmiServices.ExecQuery _ ("ASSOCIATORS OF {Win32_DiskDrive.DeviceID=""" & _ strEscapedDeviceID & """} WHERE AssocClass = " & _ "Win32_DiskDriveToDiskPartition") für die auf den Disks sich befindlichen Partitionen. Die Größe in TB ist in VBS auch kein Problem, in den entsprechenden API?s leider schon.
> Nur "nebenan" in m.p.dotnet.languages.vb > In einem Forum bin ich nicht. Ich hatte nach Abschaltung des > MSFT Newsservers keine Lust, mich dazu nötigen zu lassen, der > privaten MSFT Community beizutreten.
Ist auch widerlich. Die Werbung, das Auffinden der eigenen Postings, die unübersichtliche Präsentation usf. Nur hat mein Provider aon diese NG noch nicht im Angebot. Muß ich wieder ein Mail senden, sich darum zu kümmern. Deswegen auch meine Frage.
> Am 17.02.2011 18:16, schrieb Armin Zingler: > Also, Stand der Dinge:
> 1. Mit FindFirstVolume/FindNextVolume alle "unique volume names" ermitteln > Sie sind im Format \\?\Volume{GUID}\
> 2. Für jedes gefundenen Volumes: > FindFirstVolumeMountPoint/FindNextVolumeMountPoint aufrufen. Wenn du > das für das Volume, das auch den Buchstaben F:\ trägt, durchführst, > bekommst du die Verzeichnisse > - Hama\CF\ > - Hama\SD\ > - usw
> 3. Übergib "\\?\Volume{GUID}\Hama\CF\" (usw) > an die Funktion GetVolumeNameForVolumeMountPoint. Ergebnis > ist das Volume, das du gemountet hast, also z.B. das auf > dem USB-Stick.
> Die Richtung ist also, wie schon vermutet, eine andere: > Alle gemounteten Verzeichnisse ermitteln und nachprüfen, woher > sie kommen. Du musst nur die sammeln, die vom USB-Stick stammen.
> Bleibt nur die Frage: Woran willst du den USB-Stick identifizieren?
An VID PID und, falls die Tests das ergeben, ev. die Seriennummer.
> Was ist also gegeben? Ein Laufwerksbuchstabe?
Leider ist mir nur VID, PID und die Seriennummer bekannt. Soweit bin ich schon gekommen, daß diese Daten auf allen Rechnern dieselben sind. Das Verzeichnis in welchen sie möglicherweise gemountet eben sind nicht.
> Wenn ja, dann > müsstets du nur für den LW-Buchstaben GetVolumeNameForVolumeMountPoint > aufrufen und hast somit den "unique volume name". Den musst > du dann mit den eindeutigen Volume-Namen aller gefundenen > Mount points vergleichen. Die gefundenen Mountpoints sind dann > die des USB-Sticks.
> Um dann vom Volume aus auch noch das physikalische Device > zu ermitteln, müsstest du DeviceIOControl mit > ControlCode=IOCTL_VOLUME_GET_VOLUME_DISK_EXTENTS > aufrufen. Da sich ein Volume theoretisch über mehrere > physikalische Disks erstrecken kann,
Bei Sticks eher nicht mehr. ;-)
> würde es auch hier > in diese Richtung funktionieren.
Das werde ich so mal ausprobieren. Ist ein wirklich interessanter Ansatz.
Hoffentlich habe ich Deine Zeit nicht schon über die Maßen strapaziert.
>> Da sich ein Volume theoretisch ber mehrere >> physikalische Disks erstrecken kann, > Bei Sticks eher nicht mehr. ;-)
:) Klar, nur die allgemeinen Strukturen erlauben das auch wenn es im konkreten Fall nicht zutrifft.
Alle Einheiten wie Devices, Disks, Partitionen, Volumes, Mounting Points, etc unter einen Hut und in Zusammenhang zu bringen, ist eben doch nicht so einfach, wie es zun chst scheint.
Wobei ich noch nicht am Mangel an Dokumentation scheitere, sondern es einfach nur ein Gebiet ist, mit dem ich mich bisher noch nicht (programmatisch) besch ftigt hatte und es deswegen sehr viel zu lesen gibt. Zumal Vieles auch aus unterschiedlichen Bereichen der Doku zusammengesucht werden muss.
Dass die VID/PID eine Rolle spielt, wusste ich ja schon, aber jetzt werde ich mal suchen, wie man anhand derer zu den Infos kommt. Meine Annahme, dass ich durch die Auflistung der "DiskDrives" an die Nummern der "PhysicalDrives 0-n" komme, war ja falsch. Richtig sind wohl die Nummern, wie sie auch in der Datentr gerverwaltung von Windows ("Datentr ger XY") zu sehen sind. Na ich schau mal.
> Hoffentlich habe ich Deine Zeit nicht schon ber die Ma en strapaziert.
Also ich finde das Thema momentan ziemlich interessant! Wie gesagt, sonst w rde ich es auch nicht machen.
Ich bleib jetzt mal weiter auf dem Gebiet der API-Aufrufe aktiv. W re ja gelacht...!
>> In einem Forum bin ich nicht. Ich hatte nach Abschaltung des >> MSFT Newsservers keine Lust, mich dazu n tigen zu lassen, der >> privaten MSFT Community beizutreten.
> Ist auch widerlich. > Die Werbung, das Auffinden der eigenen Postings, die un bersichtliche > Pr sentation usf. > Nur hat mein Provider aon diese NG noch nicht im Angebot. > Mu ich wieder ein Mail senden, sich darum zu k mmern. > Deswegen auch meine Frage.
Mich hat eigentlich eher die Tatsache des privaten Clubs an sich gest rt und die anfangs erforderliche Zustimmung zu irgendwelchen Konditionen hat mich dann ganz abgeschreckt. Nicht, dass ich nicht auch sonst w sste, wie ich mich zu benehmen h tte, sondern aus Prinzip.
> :) Klar, nur die allgemeinen Strukturen erlauben das > auch wenn es im konkreten Fall nicht zutrifft.
> Alle Einheiten wie Devices, Disks, Partitionen, Volumes, > Mounting Points, etc unter einen Hut und in Zusammenhang > zu bringen, ist eben doch nicht so einfach, wie es zunächst > scheint.
> Wobei ich noch nicht am Mangel an Dokumentation scheitere, > sondern es einfach nur ein Gebiet ist, mit dem ich mich > bisher noch nicht (programmatisch) beschäftigt hatte und es > deswegen sehr viel zu lesen gibt. Zumal Vieles auch aus > unterschiedlichen Bereichen der Doku zusammengesucht werden > muss.
> Dass die VID/PID eine Rolle spielt, wusste ich ja schon, > aber jetzt werde ich mal suchen, wie man anhand derer > zu den Infos kommt. Meine Annahme, dass ich durch die Auflistung > der "DiskDrives" an die Nummern der "PhysicalDrives 0-n" komme, > war ja falsch. Richtig sind wohl die Nummern, wie sie auch > in der Datenträgerverwaltung von Windows ("Datenträger XY") > zu sehen sind. Na ich schau mal.
Ein wenig kann ich so einem höchst versierten Spezialisten vielleicht doch helfen: Das VBS-Skript, mit welchem ich ua. die Daten der Massenspeicher ermittle habe ich unter Upload Link: http://www.file-upload.net/download-3224081/NW_WMI_Infos.vbs.html hochgeladen. Wenn ich von einem PC das Wichtigste wissen möchte, so sende ich dieses Skript und ersuche um Rücksendung des Ergebnisses.
Ich bin nach Adaption der Declares der API?s und der Strukturen soweit gekommen, daß es keine Fehler bis zu jenem Punkt gibt, an dem ich die USB-Devices Enumeriere. Ich erhalte aber beim Aufruf der API SetupDiEnumDeviceInterfaces 0. Ob es für USB Massenspeicher keine Werte gibt, oder der Aufruf ins Leere geht weiß ich natürlich nicht, da ich neben den USBSTORes keine USB-Devices besitze: keine Tastatur, Maus, Fernsteuerung etc. Fehler treten bis dorthin jedenfalls nicht auf. Ich werde am Nachmittag versuchen beim Media-Markt ein Device zu erstehen, das ich nicht nur für diese Tests verwenden kann: vielleicht einen MultiDrucker,Scanner,Fax für meine Frau.
Aber allein die Bereinigung der Strukturen und Declares war ein befriedigendes Erlebnis als das Kompilieren und Tracen bis zum Punkt des Nichtvorhandenseins von Devices funktionierte.
Ich möchte mich erneut für Deine Bemühungen bedanken. So war auch meine Nacht lang. Hoffentlich strapazierst Du Dich wegen meiner Anfrage nicht zu sehr.
> Ein wenig kann ich so einem höchst versierten Spezialisten vielleicht doch > helfen:
Dieses Gebiet ist für mich ja auch Neuland. Danke auch für den Link, dennoch werde ich mich weiter ins WDK/SDK einlesen.
> Ich erhalte aber beim Aufruf der API SetupDiEnumDeviceInterfaces 0.
Ging mir erst genau so. Herausgefunden habe ich: Das Ding ist, dass nicht jedes Device jedes Interface anbietet. Wenn ich bei SetupDiGetClassDevs die Setup-Class "disk drive" hole, dann gibt es davon kein einziges Devices, das die Interface-Class "disk" anbietet. Ergo: 0.
Wenn man aber bei SetupDiGetClassDevs als ersten Parameter die gewünschte Interface-Class-GUID übergibt, z.B. GUID_DEVINTERFACE_DISK und gleichzeitig als letzten Parameter DIGCF_DEVICEINTERFACE angibt, dann bekommt man auch nur devices geliefert, die das Interface anbieten. Ergo liefert auch SetupDiEnumDeviceInterfaces etwas zurück.
Wobei die Info aus SetupDiEnumDeviceInterfaces lediglich die Flags sind (Active, Default oder Removed). Nicht sehr wertvoll.
> Hoffentlich strapazierst Du Dich wegen meiner Anfrage nicht zu sehr.
Auslöser <> Verantwortlicher. :) Nein, mich interessiert es selbst sehr.
> Ging mir erst genau so. Herausgefunden habe ich: Das Ding ist, dass nicht > jedes Device jedes Interface anbietet. Wenn ich bei SetupDiGetClassDevs > die Setup-Class "disk drive" hole, dann gibt es davon kein einziges > Devices, das die Interface-Class "disk" anbietet. Ergo: 0.
> Wenn man aber bei SetupDiGetClassDevs als ersten Parameter die > gewünschte Interface-Class-GUID übergibt, z.B. GUID_DEVINTERFACE_DISK > und gleichzeitig als letzten Parameter DIGCF_DEVICEINTERFACE > angibt, dann bekommt man auch nur devices geliefert, die das > Interface anbieten. Ergo liefert auch SetupDiEnumDeviceInterfaces > etwas zurück.
> Wobei die Info aus SetupDiEnumDeviceInterfaces lediglich die Flags > sind (Active, Default oder Removed). Nicht sehr wertvoll.
Heute Nacht ist mir einfach so eingefallen, daß es mit der GUID innerhalb des Aufrufs der API SetupDiGetClassDevs zusammenhängen muß. Richtig, wie Deine Antwort beweist. Bin gerade dabei mit der Information GUID_DEVINTERFACE_DISK und DIGCF_DEVICEINTERFACE weiter zu probieren. Leider eben mehr probieren als gezielt zu handeln. Aber auch dabei kann ich was dazulernen.
> Ich bleib jetzt mal weiter auf dem Gebiet der API-Aufrufe aktiv. > Wäre ja gelacht...!
Inzwischen war die von Dir angeregte Änderung betr. des Aufrufs SetupDiGetClassDevs insoferne erfolgreich, daß ich als Anzahl der USB-Devices 1 erhielt.
Aber ich komme über die Ermittlung der Devcedetails nicht hinaus. Wahrscheinlich ist die folgende Deklaration falsch:
Public Declare Auto Function SetupDiGetDeviceInterfaceDetail Lib "setupapi.dll" _ Alias "SetupDiGetDeviceInterfaceDetailW" ( _ ByVal hDevInfo As IntPtr, _ ByRef deviceInterfaceData As SP_DEVICE_INTERFACE_DATA, _ ByVal deviceInterfaceDetailData As SP_DEVICE_INTERFACE_DETAIL_DATA, _ ByVal deviceInterfaceDetailDataSize As Int32, _ ByRef requiredSize As Int32, _ ByVal deviceInfoData As SP_DEVINFO_DATA) As Boolean
Schon der erste Aufruf Dim ptrDeviceHandle As IntPtr = DeviceHandle bRet = SetupDiGetDeviceInterfaceDetail( _ ptrDeviceHandle, _ spDeviceInterfaceData, _ SPDeviceInterfaceDetailData, 0, Needed, _ spDevInfoData) ergibt in bRet False
Ich habe die Definitionen x-mal angepasst. aber erfolglos.
>> Ich bleib jetzt mal weiter auf dem Gebiet der API-Aufrufe aktiv. >> Wäre ja gelacht...!
> Inzwischen war die von Dir angeregte Änderung > betr. des Aufrufs SetupDiGetClassDevs insoferne erfolgreich, > daß ich als Anzahl der USB-Devices 1 erhielt.
> Aber ich komme über die Ermittlung der Devcedetails nicht hinaus. > Wahrscheinlich ist die folgende Deklaration falsch:
> Public Declare Auto Function SetupDiGetDeviceInterfaceDetail Lib > "setupapi.dll" _ > Alias "SetupDiGetDeviceInterfaceDetailW" ( _ > ByVal hDevInfo As IntPtr, _ > ByRef deviceInterfaceData As SP_DEVICE_INTERFACE_DATA, _ > ByVal deviceInterfaceDetailData As SP_DEVICE_INTERFACE_DETAIL_DATA, _ > ByVal deviceInterfaceDetailDataSize As Int32, _ > ByRef requiredSize As Int32, _ > ByVal deviceInfoData As SP_DEVINFO_DATA) As Boolean
> Schon der erste Aufruf > Dim ptrDeviceHandle As IntPtr = DeviceHandle > bRet = SetupDiGetDeviceInterfaceDetail( _ > ptrDeviceHandle, _ > spDeviceInterfaceData, _ > SPDeviceInterfaceDetailData, 0, Needed, _ > spDevInfoData) > ergibt in bRet False
> Ich habe die Definitionen x-mal angepasst. aber erfolglos.
Die Parameter deviceInterfaceDetailData und deviceInfoData müssen ByRef sein. Ansonsten entspricht es auch meiner Deklaration.
Wenn du "Auto" verwendest, kannst du dir den Alias-Abschnitt sparen.
>> Schon der erste Aufruf >> Dim ptrDeviceHandle As IntPtr = DeviceHandle >> bRet = SetupDiGetDeviceInterfaceDetail( _ >> ptrDeviceHandle, _ >> spDeviceInterfaceData, _ >> SPDeviceInterfaceDetailData, 0, Needed, _ >> spDevInfoData) >> ergibt in bRet False
>> Ich habe die Definitionen x-mal angepasst. aber erfolglos.
- ptrDeviceHandle ist das Handle des Device Info Set, das du per SetupDiGetClassDevs zurückbekommst?
- Und statt der 0 müsstest du eigentlich die Größe von SPDeviceInterfaceDetailData übergeben.
- Wie hast du den Typ von SPDeviceInterfaceDetailData deklariert?
- Außerdem muss SPDeviceInterfaceDetailData.size vorher richtig gesetzt worden sein. Wenn man sich das vierte Posting von unten auf dieser Seite http://developer.garmin.com/forum/viewtopic.php?p=762&sid=7fe7dda9a1d... ansieht, scheint 8 der richtige Wert für 64-Bit-Plattformen und 5 der richtige für 32-Bit-Plattformen zu sein. Es steht sogar ein Kommentar dabei, dass das so ist. Ich habe das einfch mal ganz dumm übernommen.
- spDevInfoData.Size mus natürlich auch richtig gesetzt sein.
Die Ausgabe der gesamten Enumerierung für die "Volumes" sieht wie folgt aus. Unter "Details" steht die Rückgabe von SPDeviceInterfaceDetailData.
> - Außerdem muss SPDeviceInterfaceDetailData.size vorher richtig gesetzt > worden sein. Wenn man sich das vierte Posting von unten auf dieser Seite > http://developer.garmin.com/forum/viewtopic.php?p=762&sid=7fe7dda9a1d... > ansieht, scheint 8 der richtige Wert für 64-Bit-Plattformen > und 5 der richtige für 32-Bit-Plattformen zu sein. > Es steht sogar ein Kommentar dabei, dass das so ist. > Ich habe das einfch mal ganz dumm übernommen.
Hätte ich nicht machen sollen. Habe es jetzt mal für 32-Bit kompiliert. Der richtige Wert ist 6 (nicht 5). Ist aber auch logisch, denn die Deklaration der Struktur ist ja:
DWORD cbSize; TCHAR DevicePath[ANYSIZE_ARRAY];
TCHAR ist 1 Byte bei 32 Bit und 2 Bytes bei 64 Bit. ANYSIZE_ARRAY ist mit 1 deklariert. Da 1 Zeichen plus der nul-Terminator Platz haben müssen, wäre das dann
- 32 Bit: 4 + 2*1 = 6 - 64 Bit: 4 + 2*2 = 8
Somit also: dim Details as SP_DEVICE_INTERFACE_DETAIL_DATA
Hallo Armin! Also ich komme mit den Deklarationen nicht klar und eigentlich überhaupt nicht mehr weiter. Bin auch von diesen schon ganz schwindlig.
Hier meine Definitionen nach dem letzten Umbau Public Const BUFFER_SIZE As Short = 255 Public Const DIGCF_PRESENT As Int32 = (2) Public Const DIGCF_DEVICEINTERFACE = &H10 Public Const GUID_DEVINTERFACE_DISK = "{53F56307-B6BF-11D0-94F2-00A0C91EFB8B}"
Public Structure SP_DEVINFO_DATA Public cbSize As Int32 Public InterfaceClassGuid As Guid Public Flags As Int32 Public Reserved As IntPtr End Structure
<StructLayout(LayoutKind.Sequential, pack:=2)> _ Public Structure SP_DEVICE_INTERFACE_DATA Public cbSize As Int32 Public interfaceClassGuid As Guid Public flags As Int32 Private reserved As UIntPtr End Structure
<StructLayout(LayoutKind.Sequential, CharSet:=CharSet.Auto, pack:=1)> _ Public Structure SP_DEVICE_INTERFACE_DETAIL_DATA Public cbSize As Int32 <MarshalAs(UnmanagedType.ByValTStr, SizeConst:=BUFFER_SIZE)> _ Public DevicePath As String End Structure
Declare Auto Function SetupDiGetClassDevs Lib _ "setupapi.dll" Alias "SetupDiGetClassDevsA" _ (ByRef GuidPtr As Guid, _ ByVal EnumPtr As IntPtr, _ ByVal HwndParent As Int32, _ ByVal Flags As Int32) _ As Int32
Public Declare Function SetupDiEnumDeviceInterfaces Lib "setupapi.dll" ( _ ByVal DeviceInfoSet As Int32, _ ByVal DeviceInfoData As Int32, _ ByRef InterfaceClassGuid As Guid, _ ByVal MemberIndex As Int32, _ ByRef DeviceInterfaceData As SP_DEVINFO_DATA) _ As Boolean
Public Declare Auto Function SetupDiGetDeviceInterfaceDetail Lib "setupapi.dll" _ Alias "SetupDiGetDeviceInterfaceDetailW" ( _ ByRef hDevInfo As Int32, _ ByRef deviceInterfaceData As SP_DEVICE_INTERFACE_DATA, _ ByRef deviceInterfaceDetailData As SP_DEVICE_INTERFACE_DETAIL_DATA, _ ByVal deviceInterfaceDetailDataSize As Int32, _ ByRef requiredSize As Int32, _ ByVal deviceInfoData As SP_DEVINFO_DATA) As Boolean
Deklarationen in der Funktion USB_GetSerNums (hier sollen einmal die Devices ermittelt werden) . Dim HidGuid As Guid Dim spDeviceInterfaceData As New SP_DEVICE_INTERFACE_DATA Dim spDevInfoData As New SP_DEVINFO_DATA Dim SPDeviceInterfaceDetailData As New SP_DEVICE_INTERFACE_DETAIL_DATA Dim Needed As Int32
HidGuid = New Guid(GUID_DEVINTERFACE_DISK)
DeviceHandle = SetupDiGetClassDevs(HidGuid, 0, 0, DIGCF_PRESENT Or DIGCF_DEVICEINTERFACE)
' das ist der erste Aufruf zwecks Ermittlung der Buffergrößen bRetDiEnumInterfaceDetail = SetupDiGetDeviceInterfaceDetail( _ DeviceHandle, _ spDeviceInterfaceData, _ SPDeviceInterfaceDetailData, 0, Needed, _ spDevInfoData)
und hier ist auch Schluß Der Fehler lautet immer "The Handle is invalid."
Vielleicht siehst Du in meinem Code das von mir unwissentlich offenbar gut versteckte Problem.
> Hallo Armin! > Also ich komme mit den Deklarationen nicht klar und eigentlich überhaupt > nicht mehr weiter. > Bin auch von diesen schon ganz schwindlig. > [...]
Als erstes solltest du ganz dringend Option Strict On einschalten. Erst recht bei solchen Aktionen sind die richtigen Datentypen wichtig. Momentan kann ich den Code deshalb nicht testen. Beseitige erst mal die Compilierfehler, und dann schau ich gerne noch mal drüber.
> - ptrDeviceHandle ist das Handle des Device Info Set, das du > per SetupDiGetClassDevs zurückbekommst?
> - Und statt der 0 müsstest du eigentlich die Größe von > SPDeviceInterfaceDetailData > übergeben.
> - Wie hast du den Typ von SPDeviceInterfaceDetailData deklariert?
> - Außerdem muss SPDeviceInterfaceDetailData.size vorher richtig gesetzt > worden sein. Wenn man sich das vierte Posting von unten auf dieser Seite > http://developer.garmin.com/forum/viewtopic.php?p=762&sid=7fe7dda9a1d... > ansieht, scheint 8 der richtige Wert für 64-Bit-Plattformen > und 5 der richtige für 32-Bit-Plattformen zu sein. > Es steht sogar ein Kommentar dabei, dass das so ist. > Ich habe das einfch mal ganz dumm übernommen.
> - spDevInfoData.Size mus natürlich auch richtig gesetzt sein.
> Die Ausgabe der gesamten Enumerierung für die "Volumes" sieht wie folgt > aus. > Unter "Details" steht die Rückgabe von SPDeviceInterfaceDetailData.
Ich gratuliere! strict on werde ich einschalten, die Definitionen nochmals durchgehen und die resultierenden *Unebenheiten beseitigen*.
Ich hoffe noch heute berichten zu können. Allerdings bin ich ab Dienstag für **mindestens** 2 ganze Tage im Spital. Dann kann ich mich frühestens am Donnerstag, 24.2.2011 wieder melden.
> Ich gratuliere! > strict on werde ich einschalten, die Definitionen nochmals durchgehen > und die resultierenden *Unebenheiten beseitigen*.
> Ich hoffe noch heute berichten zu können. > Allerdings bin ich ab Dienstag für **mindestens** 2 ganze Tage im Spital. > Dann kann ich mich frühestens am Donnerstag, 24.2.2011 wieder melden.
> Als erstes solltest du ganz dringend Option Strict On einschalten. > Erst recht bei solchen Aktionen sind die richtigen Datentypen wichtig. > Momentan kann ich den Code deshalb nicht testen. Beseitige erst mal > die Compilierfehler, und dann schau ich gerne noch mal drüber.
Hier nun der ganze Code (mit strict on und ohne Kompilerfehler): Imports System.Threading Imports System.Runtime.InteropServices
Public Class Form1 ' P/Invoke API <DllImport("HID.dll")> _ Private Shared Sub HidD_GetHidGuid(ByRef GuidPtr As Guid) End Sub
Public Const BUFFER_SIZE As Short = 255 Public Const DIGCF_PRESENT As Int32 = (2) Public Const DIGCF_DEVICEINTERFACE As UInt32 = &H10 Public Const GUID_DEVINTERFACE_DISK As String = "{53F56307-B6BF-11D0-94F2-00A0C91EFB8B}"
Public Structure SP_DEVINFO_DATA Public cbSize As Int32 Public InterfaceClassGuid As Guid Public Flags As Int32 Public Reserved As IntPtr End Structure
<StructLayout(LayoutKind.Sequential, pack:=2)> _ Public Structure SP_DEVICE_INTERFACE_DATA Public cbSize As Int32 Public interfaceClassGuid As Guid Public flags As Int32 Private reserved As UIntPtr End Structure
<StructLayout(LayoutKind.Sequential, CharSet:=CharSet.Auto, pack:=1)> _ Public Structure SP_DEVICE_INTERFACE_DETAIL_DATA Public cbSize As UInt32 <MarshalAs(UnmanagedType.ByValTStr, SizeConst:=BUFFER_SIZE)> _ Public DevicePath As String End Structure
Declare Auto Function SetupDiGetClassDevs Lib _ "setupapi.dll" Alias "SetupDiGetClassDevsA" _ (ByRef GuidPtr As Guid, _ ByVal EnumPtr As IntPtr, _ ByVal HwndParent As Int32, _ ByVal Flags As Int32) _ As IntPtr
Public Declare Function SetupDiEnumDeviceInterfaces Lib "setupapi.dll" ( _ ByVal DeviceInfoSet As IntPtr, _ ByVal DeviceInfoData As Int32, _ ByRef InterfaceClassGuid As Guid, _ ByVal MemberIndex As Int32, _ ByRef DeviceInterfaceData As SP_DEVINFO_DATA) _ As Boolean
Public Declare Auto Function SetupDiGetDeviceInterfaceDetail Lib _ "setupapi.dll" Alias "SetupDiGetDeviceInterfaceDetailW" ( _ ByRef hDevInfo As IntPtr, _ ByRef deviceInterfaceData As SP_DEVICE_INTERFACE_DATA, _ ByRef deviceInterfaceDetailData As SP_DEVICE_INTERFACE_DETAIL_DATA, _ ByVal deviceInterfaceDetailDataSize As Int32, _ ByRef requiredSize As Int32, _ ByVal deviceInfoData As SP_DEVINFO_DATA) As Boolean
Private Sub Form1_Load(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles MyBase.Load Dim HidGuid As Guid Dim spDeviceInterfaceData As New SP_DEVICE_INTERFACE_DATA Dim spDevInfoData As New SP_DEVINFO_DATA Dim SPDeviceInterfaceDetailData As New SP_DEVICE_INTERFACE_DETAIL_DATA Dim LenB As Int32 Dim Needed As Int32 Dim DeviceHandle As IntPtr Dim MemberIndex As Integer Dim bRetDiEnum As Boolean Dim bRetDiEnumInterfaceDetail As Boolean
HidGuid = New Guid(GUID_DEVINTERFACE_DISK)
DeviceHandle = SetupDiGetClassDevs(HidGuid, IntPtr.Zero, 0, DIGCF_PRESENT Or DIGCF_DEVICEINTERFACE)
MemberIndex = 0 bRetDiEnum = SetupDiEnumDeviceInterfaces(DeviceHandle, 0, HidGuid, MemberIndex, spDevInfoData) Do While bRetDiEnum ' das ist der erste Aufruf zwecks Ermittlung der Buffergrößen bRetDiEnumInterfaceDetail = SetupDiGetDeviceInterfaceDetail( _ DeviceHandle, _ spDeviceInterfaceData, _ SPDeviceInterfaceDetailData, 0, Needed, _ spDevInfoData) bRetDiEnum = SetupDiEnumDeviceInterfaces(DeviceHandle, 0, HidGuid, MemberIndex, spDevInfoData) Loop End Sub End Class
bRetDiEnumInterfaceDetail ist immer noch false. Do While bRetDiEnum wird 5mal durchlaufen.