Seite 2 von 2

Verfasst: 12.11.2008 18:54
von Xaby
Na ja,

also wenn man einen Kartenlesegerät fest im Rechner hat, kommen diese Meldungen auch.

Und er merkt den Unterschied fast nicht, ob man nun eine Karte drin hat oder nicht :?

Verfasst: 12.11.2008 19:12
von scholly
@Xaby:
Verhindert meine Grippe, daß ich den Zusammenhang zwischen meinem USB-Stick-Problem und Deinem ersten Beitrag erkenne?

@sibru:
Den Requester bekomm ich überflüssigerweise auch, aber dann werden 2 Zeilen für A: und L: debugged.
Allerdings löst die Kette GetDriveType - GetLogicalDrives - GetVolumeInformation mein Problem auch nicht.

Bei meinen Tests heute hab ich dummerweise festgestellt, daß neue Probleme auftauchen, wenn ein Benutzer der Database auf die Idee kommt, über einen USB-Cardreader SDs oder so zu katalogisieren.
Allerdings ist DAS Problem sekundär, da ich bisher ja noch nichtmal USB erkennen kann.

Über Win32_Diskdrive bekomme ich heraus, welche physikalischen Drives als Interface USB haben.
Als Volume-Erkennung würde mir die VolumeSerialNumber per Win32_Logicaldisk oder GetVolumeInformation_() reichen.

Was ich eigentlich nun händeringend suche, ist die verläßliche Zuordnung der Volumes zu physikalischen Drives.

Verfasst: 13.11.2008 14:27
von Agent
Hallo Scholly.

Ich habe mit ähnlichem zu tun und nutze folgene Procedures:

Die erste liefert einen String der alle angemeldeten Laufwerksbuchstaben ermittelt:

Code: Alles auswählen

Procedure.s SK_GetAllDrives() ; PB 3+4
  Protected bitmask.l, one.l, i
  Protected drives.s
  
  bitmask.l = GetLogicalDrives_()       ; not a PB Function, its Windows API (becourse of the '_' )
  
  ; each bit represents one drive.
  drives.s = ""
  one.l = 1
  
  For i = 0 To 31                       ; go from bit 0 to 31.
    If bitmask  & one<<i                ; the 'one<<i' thingy is a bit tricky, what it does is something like 2^i
      ; '&' is bitwise AND operator, so if the bit i is one, the whole thing returns true.
      drives = drives + Chr(65+i)       ; add the driveletter to the string.
    EndIf
  Next i
  ProcedureReturn drives
EndProcedure

Und mit einem einfachen API frage ich den Typ ab:

GetDriveType_()

Hier mal ein schnelles Beispiel:

Code: Alles auswählen

EnableExplicit

Define.l i
Define.s AllSystemDrives$
Define.s LW_Letter$

; Alle gemounteten Laufwerke ermitteln
AllSystemDrives$ = SK_GetAllDrives()

; Anzeigen, welche bestimmten Typ haben:
For i = 1 To Len(AllSystemDrives$)
  LW_Letter$ = Mid(AllSystemDrives$, i, 1)
  
  Debug "Checking Drive: " + LW_Letter$
  
  If GetDriveType_(LW_Letter$) = 2 ; Removable
    Debug "Drive " + LW_Letter$ + ":\ is REMOVABLE"
  EndIf
Next i

Verfasst: 13.11.2008 16:36
von scholly
Danke, Agent, aaaaaaber:

2 bei GetDriveType() ist AFAIK definiert als:
MSDN hat geschrieben:The drive has removable media; for example, a floppy drive, thumb drive, or flash card reader.
Floppies sind A und B, die kann man abfangen, aber alle anderen können IMHO nur über Win32_DiskDrive mit InterfaceType verläßlich erkannt werden, denn neben USB-Sticks oder -HDDS könnten doch FireWire-Devices da auftauchen, oder etwa nicht?
Da ich kein FW habe, hab ich kein Plan, was da überhaupt auftauchen könnte und ob es neben HDDs in externen (FW-)Gehäusen noch andere potentielle Speichermedien gibt, deren Inhalt jemand erfassen will.

Es gibt bestimmt eine Brücke, wie man die Ergebnisse von GetDriveType bzw. Win32_LogicalDisk mit Win32_DiskDrive zusammenbringt, nur den Weg dahin finde ich nich :(

Verfasst: 14.11.2008 14:31
von Agent
Das ist korrekt. Mir reichte dies bisher, da ich nicht explizit nach USB-Laufwerken gesucht habe. Diese Lösung ist auch sehr einfach. Leider kann ich Dir keine präzisere für Deine Anwendung liefer ;-)

Verfasst: 19.11.2008 16:40
von jpd
Hallo scholly,

anbei ein beispiel dass dir möglicherweise weiterhelfen wird...

Verwende WMI über die Aktuelle Comate version

http://www.purebasic.fr/english/viewtopic.php?t=33983

Ciao
jpd

Code: Alles auswählen


;/////////////////////////////////////////////////////////////// 
;// Disk Drive WMI Comate Example                      // 
;// jpd                                                               // 
;/////////////////////////////////////////////////////////////// 

Enumeration
  #DiskNr
  #List_partition
  #Check_USB
EndEnumeration

IncludeFile "COMate.pbi"

Structure PartitionInfo
  
  Partition.s
  DriveLetter.s
  FileSystem.s
  FreeSpace.s
  Size.s
  VolumeName.s
  VolumeSerialNumber.s
  Bootable.l
  BootPartition.l
  PrimaryPartition.l
  Type.s
          
 EndStructure 

Structure DiskInfo
  DiskNr.s
  PartNr.PartitionInfo
  DeviceID.s
  PNPDeviceID.s
  FirmwareRevision.s
  InterfaceType.s
  MediaType.s
  Model.s
  Status.s
EndStructure

Global NewList info.DiskInfo()




Procedure Partition_To_DiskDrive(devID.s)
  
  Define.COMateObject objWMIService, USBCfg,EnumUSB
  strComputer.s = "." 
  objWMIService = COMate_GetObject("winmgmts:\\" + strComputer + "\root\cimv2", "") 
  If objWMIService 
    EnumUSBset.COMateEnumObject 
    x=0
   Debug devID
    EnumUSBset = objWMIService\CreateEnumeration("ExecQuery('Select * From Win32_DiskDrive Where DeviceID= $0027" + devID +"$0027')") 
    Debug  COMate_GetLastErrorCode() 
    Debug COMate_GetLastErrorDescription() 
    If EnumUSBset
      EnumUSB = EnumUSBset\GetNextObject() 
      While EnumUSB
        If EnumUSB
          Debug x
          Debug "Description: "+EnumUSB\GetstringProperty("Description")
          info()\FirmwareRevision=EnumUSB\GetstringProperty("FirmwareRevision")
          info()\InterfaceType=EnumUSB\GetstringProperty("InterfaceType")
          info()\MediaType=EnumUSB\GetstringProperty("MediaType")
          info()\Model=EnumUSB\GetstringProperty("Model")
          info()\PNPDeviceID=EnumUSB\GetstringProperty("PNPDeviceID")
          info()\Status=EnumUSB\GetstringProperty("Status")
          EnumUSB\Release() 
          x=x+1
        EndIf 
        EnumUSB = EnumUSBset\GetNextObject() 
      Wend
      EnumUSBset\Release() 
    EndIf
    objWMIService\Release() 
  EndIf
    
EndProcedure   

Procedure Win32_DiskDrivePhysicalMedia()

  Define.COMateObject objWMIService, EnumDiskDrive
  EnumDiskDriveset.COMateEnumObject 
  strComputer.s = "." 
  objWMIService = COMate_GetObject("winmgmts:\\" + strComputer + "\root\cimv2", "") 
  If objWMIService 
   
    x=0
    EnumDiskDriveset = objWMIService\CreateEnumeration("ExecQuery('Select * From Win32_DiskDrivePhysicalMedia')")
    If EnumDiskDriveset
     EnumDiskDrive = EnumDiskDriveset\GetNextObject() 
     While EnumDiskDrive
        If EnumDiskDrive
          physdrive.l=FindString(EnumDiskDrive\GetstringProperty("Antecedent"),"\\\\.\\PHYSICALDRIVE",1)
          If physdrive
            diskpart.s=RemoveString(Mid(EnumDiskDrive\GetstringProperty("Antecedent"),physdrive,Len("\\\\.\\PHYSICALDRIVE")+2),Chr(34))
            Partition_To_DiskDrive(diskpart)
          EndIf 
        EndIf
        EnumDiskDrive = EnumDiskDriveset\GetNextObject() 
      Wend
      EnumDiskDriveset\Release() 
    EndIf
    objWMIService\Release() 
  EndIf

EndProcedure

Procedure.s Diskpartition(diskpart.s)

  found.l= FindString(diskpart,Chr(34),1)
  ProcedureReturn  Mid(diskpart,found,Len(diskpart)-found+1)
  
EndProcedure 

Procedure LogicalDiskToPartition(antecedent.s)

  Define.COMateObject objWMIService, EnumLDisk
  EnumLDiskset.COMateEnumObject 
  strComputer.s = "." 
  objWMIService = COMate_GetObject("winmgmts:\\" + strComputer + "\root\cimv2", "") 
  If objWMIService 
    x=0
    antecedent=ReplaceString(antecedent, "\", "\\")
    EnumLDiskset = objWMIService\CreateEnumeration("ExecQuery('Select * From Win32_LogicalDiskToPartition Where Antecedent= $0027" + antecedent +"$0027')") 
    If EnumLDiskset
      EnumLDisk = EnumLDiskset\GetNextObject() 
      While EnumLDisk
        If EnumLDisk
          driveletter.s=EnumLDisk\GetstringProperty("Dependent")
          info()\PartNr\DriveLetter=RemoveString(diskpartition(driveletter),Chr(34))
          EnumLDisk\Release() 
        EndIf
        EnumLDisk = EnumLDiskset\GetNextObject() 
      Wend
      EnumLDiskset\Release() 
    EndIf
    objWMIService\Release() 
  EndIf

EndProcedure

Procedure Win32_DiskDriveToDiskPartition()

  Define.COMateObject objWMIService, EnumDisk
  EnumDiskset.COMateEnumObject 
  strComputer.s = "." 
  objWMIService = COMate_GetObject("winmgmts:\\" + strComputer + "\root\cimv2", "") 
  If objWMIService 
    x=0
    EnumDiskset = objWMIService\CreateEnumeration("ExecQuery('Select * From Win32_DiskDriveToDiskPartition')"); Where DeviceID= $0027" + devID +"$0027')") 
    If EnumDiskset
      EnumDisk = EnumDiskset\GetNextObject() 
      While EnumDisk
        If EnumDisk
          Debug x
          AddElement(Info())
          diskpart.s=  EnumDisk\GetstringProperty("Dependent")
          LogicalDiskToPartition(diskpart)
          diskpartition(diskpart)
          For xx=1 To CountString(diskpartition(diskpart),",")+1
            Ergebnis$ = StringField(diskpartition(diskpart), xx, ",")
            Ergebnis$= RemoveString(Ergebnis$,Chr(34))
            If xx=1
              Info()\DiskNr=Ergebnis$
              Debug "Disk Nr: "+Ergebnis$
              If tmp$<>Ergebnis$
                Debug "DisktoCheck: "+Ergebnis$
                tmp$=Ergebnis$
                diskNr.s=RemoveString(tmp$,"Disk #")
                Debug DiskNr
              EndIf 
              y=x
            Else
              Debug "Partition Nr: "+Ergebnis$
              Info()\PartNr\Partition=Ergebnis$
              y=x
              x=x+1 
            EndIf      
          Next 
          physdrive.l=FindString(EnumDisk\GetstringProperty("Antecedent"),"\\\\.\\PHYSICALDRIVE",1)
          If physdrive
            diskpart.s=RemoveString(Mid(EnumDisk\GetstringProperty("Antecedent"),physdrive,Len("\\\\.\\PHYSICALDRIVE")+2),Chr(34))
            Debug diskpart
            If tmpdisk$<>diskpart
              tmpdisk$=diskpart
              Info()\DeviceID=EnumDisk\GetstringProperty("Antecedent")
              Partition_To_DiskDrive(diskpart)
            EndIf
          EndIf 
        EndIf
        EnumDisk = EnumDiskset\GetNextObject() 
      Wend
      EnumDiskset\Release() 
    EndIf
    objWMIService\Release() 
  EndIf

EndProcedure

Procedure Win32_DiskPartition(DeviceID.s)


  Define.COMateObject objWMIService, EnumPart
  EnumPartset.COMateEnumObject 
  strComputer.s = "." 
  objWMIService = COMate_GetObject("winmgmts:\\" + strComputer + "\root\cimv2", "") 
  If objWMIService 
    x=0
    EnumPartset = objWMIService\CreateEnumeration("ExecQuery('Select * From Win32_DiskPartition Where DeviceID= $0027" + DeviceID +"$0027')") 
    If EnumPartset
      EnumPart = EnumPartset\GetNextObject() 
      While EnumPart
        If EnumPart
          Info()\PartNr\Bootable=EnumPart\GetIntegerProperty("Bootable")
          Info()\PartNr\BootPartition=EnumPart\GetIntegerProperty("BootPartition")
          Info()\PartNr\PrimaryPartition=EnumPart\GetIntegerProperty("PrimaryPartition")
          Info()\PartNr\Type=EnumPart\GetstringProperty("Type")
        EndIf
        EnumPart = EnumPartset\GetNextObject() 
      Wend
      EnumPartset\Release() 
    EndIf
    objWMIService\Release() 
  EndIf

EndProcedure

Procedure.s DiskSpace(strval.s)
  
  Protected lpTotalNumberOfBytes.q, res.f, CapStr.s
  
  lpTotalNumberOfBytes=ValQ(strval.s)
  res=  lpTotalNumberOfBytes/(1024*1024*1024)
  CapStr= StrD(res,2)
  ProcedureReturn CapStr 
 
EndProcedure 

Procedure Win32_LogicalDisk(Driveletter.s)

  Define.COMateObject objWMIService, EnumDrive
  EnumDriveset.COMateEnumObject 
  strComputer.s = "." 
  objWMIService = COMate_GetObject("winmgmts:\\" + strComputer + "\root\cimv2", "") 
  If objWMIService 
    x=0
    EnumDriveset = objWMIService\CreateEnumeration("ExecQuery('Select * From Win32_LogicalDisk Where Caption= $0027" + Driveletter +"$0027')") 
    If EnumDriveset
      EnumDrive = EnumDriveset\GetNextObject() 
      While EnumDrive
        If EnumDrive
          Debug x
          Debug EnumDrive\GetstringProperty("Caption")
          Info()\PartNr\FileSystem=EnumDrive\GetstringProperty("FileSystem")
          Info()\PartNr\FreeSpace=DiskSpace(EnumDrive\GetstringProperty("FreeSpace"))
          Info()\PartNr\Size=DiskSpace(EnumDrive\GetstringProperty("Size"))
          Info()\PartNr\VolumeName=EnumDrive\GetstringProperty("VolumeName")
          Info()\PartNr\VolumeSerialNumber= EnumDrive\GetstringProperty("VolumeSerialNumber")
        EndIf
        EnumDrive = EnumDriveset\GetNextObject() 
      Wend
      EnumDriveset\Release() 
    EndIf
    objWMIService\Release() 
  EndIf

EndProcedure

Procedure Start()
ClearList(Info())
ClearGadgetItemList(#List_partition)
ClearGadgetItemList(#DiskNr)
Win32_DiskDriveToDiskPartition()
    
    ResetList(Info())
    x=0
    While NextElement(Info())
      Win32_LogicalDisk(Info()\PartNr\Driveletter)
      Win32_DiskPartition(Info()\DiskNr+","+Info()\partNr\Partition)
      If tmpdisk.s <>Info()\DiskNr
        If  Info()\InterfaceType <> "" And GetGadgetState(#Check_USB) =0
          
          AddGadgetItem(#DiskNr, -1, Info()\DiskNr)
          SetGadgetItemText(#DiskNr, x, Info()\InterfaceType,1)
          SetGadgetItemText(#DiskNr, x, Info()\MediaType,2)
          SetGadgetItemText(#DiskNr, x, Info()\Model,3)
          SetGadgetItemText(#DiskNr, x, Info()\DeviceID,4)
          SetGadgetItemText(#DiskNr, x, Info()\PNPDeviceID,5)
          SetGadgetItemText(#DiskNr, x, Info()\FirmwareRevision,6)
          SetGadgetItemText(#DiskNr, x, Info()\Status,7)
          x=x+1
          tmpdisk.s =Info()\DiskNr
        ElseIf Info()\InterfaceType = "USB" And GetGadgetState(#Check_USB) =1
          AddGadgetItem(#DiskNr, -1, Info()\DiskNr)
          SetGadgetItemText(#DiskNr, x, Info()\InterfaceType,1)
          SetGadgetItemText(#DiskNr, x, Info()\MediaType,2)
          SetGadgetItemText(#DiskNr, x, Info()\Model,3)
          SetGadgetItemText(#DiskNr, x, Info()\DeviceID,4)
          SetGadgetItemText(#DiskNr, x, Info()\PNPDeviceID,5)
          SetGadgetItemText(#DiskNr, x, Info()\FirmwareRevision,6)
          SetGadgetItemText(#DiskNr, x, Info()\Status,7)
          x=x+1
          
        EndIf
        
      EndIf   
    Wend
EndProcedure

If OpenWindow(0, 100, 100, 800, 550, "Disk Drive", #PB_Window_SystemMenu | #PB_Window_ScreenCentered)
  If CreateGadgetList(WindowID(0))
    ListIconGadget(#DiskNr, 5, 5, 790, 250, "DiskNr", 80, #PB_ListIcon_FullRowSelect|#PB_ListIcon_AlwaysShowSelection)
      AddGadgetColumn(#DiskNr, 1, "InterfaceType", 50)
      AddGadgetColumn(#DiskNr, 2, "MediaType", 100)
      AddGadgetColumn(#DiskNr, 3, "Model", 100)
      AddGadgetColumn(#DiskNr, 4, "DeviceID", 100)
      AddGadgetColumn(#DiskNr, 5, "PNPDeviceID", 100)
      AddGadgetColumn(#DiskNr, 6, "FirmwareRevision", 100)
      AddGadgetColumn(#DiskNr, 7, "Status", 100)
    ListIconGadget(#List_partition, 5, 260, 790, 250, "Partition", 80, #PB_ListIcon_FullRowSelect|#PB_ListIcon_AlwaysShowSelection)
      AddGadgetColumn(#List_partition, 1, "DriveLetter", 40)
      AddGadgetColumn(#List_partition, 2, "FileSystem", 50)
      AddGadgetColumn(#List_partition, 3, "Size Gb:", 60)
      AddGadgetColumn(#List_partition, 4, "FreeSpace Gb:", 60)
      AddGadgetColumn(#List_partition, 5, "FreeSpace %:", 50)
      AddGadgetColumn(#List_partition, 6, "VolumeName", 100)
      AddGadgetColumn(#List_partition, 7, "VolumeSerialNumber", 80)
      AddGadgetColumn(#List_partition, 8, "Bootable", 40)
      AddGadgetColumn(#List_partition, 9, "BootPartition", 40)
      AddGadgetColumn(#List_partition, 10, "PrimaryPartition", 40)
      AddGadgetColumn(#List_partition, 11, "Type", 100)
    CheckBoxGadget(#Check_USB,5,520,150,20,"View only USB Device")
  EndIf
EndIf
    
    start() 
    Repeat
      Event = WaitWindowEvent()
        Select Event 
          Case #PB_Event_Gadget 
            Select EventGadget() 
              Case #Check_USB
              If GetGadgetState(#Check_USB)
                Debug "check"
                start() 
              Else
                Debug "Uncheck"
                start() 
              EndIf
              Case #DiskNr
                Debug GetGadgetState(#DiskNr) 
                ResetList(info())
                ClearGadgetItemList(#List_partition)
                x=0
                While NextElement(Info())
                  If Info()\DiskNr=GetGadgetItemText(#DiskNr, GetGadgetState(#DiskNr))
                    AddGadgetItem(#List_partition, -1, info()\partNr\Partition)
                    SetGadgetItemText(#List_partition, x, Info()\PartNr\Driveletter,1)
                    SetGadgetItemText(#List_partition, x, Info()\PartNr\FileSystem,2)
                    SetGadgetItemText(#List_partition, x, Info()\PartNr\FreeSpace,4)
                    SetGadgetItemText(#List_partition, x, Info()\PartNr\Size,3)
                    procent.s=StrD((ValF(Info()\PartNr\FreeSpace)*100)/ValF(Info()\PartNr\Size),2)+" %"
                    SetGadgetItemText(#List_partition, x, procent,5)
                    SetGadgetItemText(#List_partition, x, Info()\PartNr\VolumeName,6)
                    SetGadgetItemText(#List_partition, x, Info()\PartNr\VolumeSerialNumber,7)
                    SetGadgetItemText(#List_partition, x, RemoveString(Str(Info()\PartNr\Bootable),"-"),8)
                    SetGadgetItemText(#List_partition, x, RemoveString(Str(Info()\PartNr\BootPartition),"-"),9)
                    SetGadgetItemText(#List_partition, x, RemoveString(Str(Info()\PartNr\PrimaryPartition),"-"),10)
                    SetGadgetItemText(#List_partition, x, Info()\PartNr\Type,11)
                    x=x+1
                  EndIf
                Wend 
            EndSelect
        EndSelect
    Until Event = #PB_Event_CloseWindow
  
 

Verfasst: 19.11.2008 17:56
von scholly
jpd hat geschrieben:anbei ein beispiel dass dir möglicherweise weiterhelfen wird...
Verwende WMI über die Aktuelle Comate version
:allright:
Ich komme zwar mit COMate nicht klar, aber es sieht auf den ersten Blick so aus, als wenn ich nun die Kette Driveletter <-> USB schließen könnte. Werde ich mich heute Abend mal dransetzen.

thx...
scholly

Verfasst: 20.11.2008 00:22
von scholly
Okidoki, ich habs geschafft:

Code: Alles auswählen

IncludeFile "wmi_430.pbi" ; http://www.purebasic.fr/german/viewtopic.php?t=2925

drive.s = "l:" ; LW-Buchstabe des USB-Sticks

WMI_INIT()
  WMI_Call("Select * FROM Win32_LogicalDiskToPartition", "Dependent, Antecedent")
  ResetList(wmidata())
  While NextElement(wmidata())
    If FindString(wmidata(), UCase(drive),1)
      NextElement(wmidata())
      deviceID.s = wmidata()
      Break      
    EndIf
  Wend

  WMI_Call("Select * FROM Win32_DiskDriveToDiskPartition", "Dependent, Antecedent")
  ResetList(wmidata())
  While NextElement(wmidata())
    If FindString(wmidata(), deviceID,1)
      NextElement(wmidata())
      pdp.l = FindString(wmidata(),"PHYSICAL",1)
      pysicaldrive.s = ReplaceString(Mid(wmidata(), pdp), Chr(34),"")
      Break      
    EndIf
  Wend

  WMI_Call("Select * FROM Win32_DiskDrive", "DeviceID, InterfaceType, Model")
  ResetList(wmidata())
  While NextElement(wmidata())
    If FindString(wmidata(), pysicaldrive,1)
      NextElement(wmidata())
      InterfaceTyp.s = wmidata()
      NextElement(wmidata())
      Model.s = wmidata()
      Break     
    EndIf
  Wend
  
  Debug "Laufwerk "+UCase(drive)+" ist am Interface "+interfacetyp+" und das Modell ist "+model
Danke für Deinen Code, jpd, ich hatte bei meinen bisherigen Versuchen nicht alle von Dir benutzten WMI-Klassen berücksichtigt.

bis denne...
scholly

Verfasst: 20.11.2008 10:37
von jpd
Hi Scholly,

freut mich das du damit eine lösung gefunden hast!

:)

Ciao
jpd