Конференция "WinAPI" » Узнать путь USB устройства
 
  • dimonbest (28.07.09 15:19) [0]
    В чем собственно проблема.
    Не получается получить путь устройства. Делаю так:

     LoadSetupApi;
     LoadConfigManagerApi;
     Memo1.Clear;

     PnPHandle:=SetupDiGetClassDevs(@USB_CLASS_GUID, nil, 0,DIGCF_PRESENT);
     if Cardinal(PnPHandle) = INVALID_HANDLE_VALUE then  Exit;

     Devn := 0;
     repeat
      DevData.cbSize := SizeOf(DevData);
      RES := SetupDiEnumDeviceInfo(PnPHandle, Devn, DevData);
      if (RES) and (_DN<>DN_ROOT_ENUMERATED) then
       begin
         St:=GetDeviceName(PnPHandle, DevData);

         if St='AVR309:USB to UART protocol converter' then begin //здесь из списка устройств по имени нахожу нужное мне устройство

           DeviceInterfaceDetailData:=nil;
           RequiredSize:=nil;
           new(RequiredSize);

    //   А вот здесь пытаюсь получить путь устройства

            if(SetupDiGetInterfaceDeviceDetail(PnPHandle,        
                                 @DevData,
                                                   nil,
                                     0,
                                        RequiredSize,
                                              nil))then begin

             new(DeviceInterfaceDetailData);
             DeviceInterfaceDetailData^.cbSize:=SizeOf(DeviceInterfaceDetailData^);

             SetupDiGetInterfaceDeviceDetail(PnPHandle,
                                 @DevData,
                                 DeviceInterfaceDetailData,
                                     RequiredSize^,
                                        nil,
                                              nil);
             Memo1.Lines.Add('OK');
    // В мемо выводит всегда длину , равную 1          

    Memo1.Lines.Add(IntToStr(Length(DeviceInterfaceDetailData^.DevicePath)));
            end;
         end;
        Inc(Devn);
       end;
     until not RES;
     SetupDiDestroyDeviceInfoList(PnPHandle);
     UnloadSetupApi;
     UnloadConfigManagerApi;


    Предполагаю, что неправильно использую функцию SetupDiGetInterfaceDeviceDetail.
    Может кто то работал с данной функцией?
    dimonbest на форуме Добавить отзыв для dimonbest Пожаловаться на это сообщение    Ответить с цитированием

  • Дмитрий (31.07.09 08:01) [1]
    Вот пример, у меня работает. GIUD поменяешь.


    procedure GetDeviceInfo;
    var
     h_DevInfo: HDEVINFO;
     DeviceNumber: DWORD;
     DevData: TSPDevInfoData;
     DevInfoData: TSPDeviceInterfaceData;
     DevInfoDetail: PSPDeviceInterfaceDetailData;
     RES:BOOL;
     requiredLength: PDWORD;
     predictedLength: DWORD;
    begin
     h_DevInfo := SetupDiGetClassDevs(@GUID_CLASS_USB_DEVICE, nil, 0, DIGCF_PRESENT or DIGCF_DEVICEINTERFACE);
     if h_DevInfo = INVALID_HANDLE_VALUE then  Exit;
     DeviceNumber := 0;
     repeat
      DevData.cbSize := SizeOf(TSPDevInfoData);
      DevInfoData.cbSize := SizeOf(TSPDeviceInterfaceData);
      RES := SetupDiEnumDeviceInterfaces(h_DevInfo, nil, GUID_CLASS_USB_DEVICE, DeviceNumber, DevInfoData);
      if (RES) then
       begin

       SetupDiGetInterfaceDeviceDetail(h_DevInfo,
                                       @DevInfoData,
                                       nil,
                                       0,
                                       requiredlength,
                                       nil);
        predictedLength := requiredLength^;
        GetMem(DevInfoDetail, predictedLength);
        DevInfoDetail^.cbSize := Sizeof(TSPDeviceInterfaceDetailData);
        if SetupDiGetInterfaceDeviceDetail(h_DevInfo,
                                           @DevInfoData,
                                           DevInfoDetail,
                                           predictedLength,
                                           requiredLength,
                                           @DevData)
        then
         begin
           DevPath:=PChar(@DevInfoDetail.devicepath);
           Memo1.Lines.Add(DevPath);
         end;
        FreeMem(DevInfoDetail);
        Inc(DeviceNumber);
       end;
     until not RES;
     SetupDiDestroyDeviceInfoList(h_DevInfo);
    end;

  • Дмитрий (31.07.09 08:06) [2]
    Не знаю что у тебя в LoadSetupApi, но на всякий случай...


    type

     HDEVINFO = THandle;

     PSPDevInfoData = ^TSPDevInfoData;
     SP_DEVINFO_DATA = packed record
       cbSize: DWORD;
       ClassGuid: TGUID;
       DevInst: DWORD; // DEVINST handle
       Reserved: ULONG_PTR;
     end;
     TSPDevInfoData = SP_DEVINFO_DATA;

     PSPDeviceInterfaceData = ^TSPDeviceInterfaceData;
     SP_DEVICE_INTERFACE_DATA = packed record
       cbSize: DWORD;
       InterfaceClassGuid: TGUID;
       Flags: DWORD;
       Reserved: ULONG_PTR;
     end;
     TSPDeviceInterfaceData = SP_DEVICE_INTERFACE_DATA;

     PSPDeviceInterfaceDetailData = ^TSPDeviceInterfaceDetailData;
     SP_DEVICE_INTERFACE_DETAIL_DATA = packed record
       cbSize: DWORD;
       DevicePath: array [0..0] of Char;
     end;
     TSPDeviceInterfaceDetailData = SP_DEVICE_INTERFACE_DETAIL_DATA;
  • dimonbest (31.07.09 10:39) [3]
    Спасибо за ответ, уже как месяц борюсь с этой проблемой!
    У меня проект не компилит, выдает ошибки, например

    [Error] Unit1.pas(31): Undeclared identifier: 'ULONG_PTR'


    Какие модули надо добавлять в uses?
  • dimonbest (31.07.09 11:10) [4]
    А если делаю через  LoadConfigManagerApi
    unit Unit1;

    interface

    uses
     Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
     Dialogs, StdCtrls, SetupAPI, Cfg, CfgMgr32;

    type

     TForm1 = class(TForm)
       Button1: TButton;
       Memo1: TMemo;
       procedure Button1Click(Sender: TObject);
       procedure FormCreate(Sender: TObject);
       procedure FormClose(Sender: TObject; var Action: TCloseAction);
     private
       { Private declarations }
     public
       { Public declarations }
     end;

    var
     Form1: TForm1;

    implementation

    {$R *.dfm}

    procedure GetDeviceInfo;
    const
     USB_CLASS_GUID:TGUID = '{36FC9E60-C465-11CF-8056-444553540000}';
     USB_DEVICE_GUID:TGUID = '{A5DCBF10-6530-11D2-901F-00C04FB951ED}';
    var
    h_DevInfo: HDEVINFO;
    DeviceNumber: DWORD;
    DevData: TSPDevInfoData;
    DevInfoData: TSPDeviceInterfaceData;
    DevInfoDetail: PSPDeviceInterfaceDetailData;
    RES:BOOL;
    requiredLength: PDWORD;
    predictedLength: DWORD;
    devpath: string;
    begin
    form1.Memo1.Clear;
    h_DevInfo := SetupDiGetClassDevs(@USB_CLASS_GUID, nil, 0, DIGCF_PRESENT or DIGCF_DEVICEINTERFACE);
    if cardinal(h_DevInfo) = INVALID_HANDLE_VALUE then  Exit;
    DeviceNumber := 0;
    repeat
     DevData.cbSize := SizeOf(TSPDevInfoData);
     DevInfoData.cbSize := SizeOf(TSPDeviceInterfaceData);
     RES := SetupDiEnumDeviceInterfaces(h_DevInfo, nil, USB_CLASS_GUID, DeviceNumber, DevInfoData);
     if (RES) then
      begin

      SetupDiGetInterfaceDeviceDetail(h_DevInfo,
                                      @DevInfoData,
                                      nil,
                                      0,
                                      requiredlength,
                                      nil);
       predictedLength := requiredLength^;
       GetMem(DevInfoDetail, predictedLength);
       DevInfoDetail^.cbSize := Sizeof(TSPDeviceInterfaceDetailData);
       if SetupDiGetInterfaceDeviceDetail(h_DevInfo,
                                          @DevInfoData,
                                          DevInfoDetail,
                                          predictedLength,
                                          requiredLength,
                                          @DevData)
       then
        begin
          DevPath:=PChar(@DevInfoDetail.devicepath);
          form1.Memo1.Lines.Add('ok');
          form1.Memo1.Lines.Add(DevPath);
        end;
       FreeMem(DevInfoDetail);
       Inc(DeviceNumber);
      end;
    until not RES;
    SetupDiDestroyDeviceInfoList(h_DevInfo);
    end;

    procedure TForm1.Button1Click(Sender: TObject);
    begin
    GetDeviceInfo;
    end;

    procedure TForm1.FormCreate(Sender: TObject);
    begin
    //  LoadSetupApi;
     LoadConfigManagerApi;
    end;

    procedure TForm1.FormClose(Sender: TObject; var Action: TCloseAction);
    begin
    //  UnloadSetupApi;
     UnloadConfigManagerApi;
    end;

    end.



    То когда передаю  
    USB_CLASS_GUID:TGUID = '{36FC9E60-C465-11CF-8056-444553540000}';

    RES := SetupDiEnumDeviceInterfaces(h_DevInfo, nil, USB_CLASS_GUID, DeviceNumber, DevInfoData); Равно False

    А если передаю
    USB_DEVICE_GUID:TGUID = '{A5DCBF10-6530-11D2-901F-00C04FB951ED}';

    То в этом месте:
    DevInfoDetail^.cbSize := Sizeof(TSPDeviceInterfaceDetailData);
    Происходит исключение -
    Access violation at address 0045A92F in module 'Project1.exe'. Read of address 00000003.
    В чем может быть проблема?
  • Дмитрий (31.07.09 12:24) [5]
    У меня как-то так примерно...

    uses
     Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms, Dialogs, StdCtrls;

    const
    GUID_CLASS_USB_DEVICE:TGUID='{A5DCBF10-6530-11D2-901F-00C04FB951ED}';

    type

     ULONG_PTR = ^ ULONG;
     HDEVINFO = THandle;

     PSPDevInfoData = ^TSPDevInfoData;
     SP_DEVINFO_DATA = packed record
       cbSize: DWORD;
       ClassGuid: TGUID;
       DevInst: DWORD; // DEVINST handle
       Reserved: ULONG_PTR;
     end;
     TSPDevInfoData = SP_DEVINFO_DATA;

     PSPDeviceInterfaceData = ^TSPDeviceInterfaceData;
     SP_DEVICE_INTERFACE_DATA = packed record
       cbSize: DWORD;
       InterfaceClassGuid: TGUID;
       Flags: DWORD;
       Reserved: ULONG_PTR;
     end;
     TSPDeviceInterfaceData = SP_DEVICE_INTERFACE_DATA;

     PSPDeviceInterfaceDetailData = ^TSPDeviceInterfaceDetailData;
     SP_DEVICE_INTERFACE_DETAIL_DATA = packed record
       cbSize: DWORD;
       DevicePath: array [0..0] of Char;
     end;
     TSPDeviceInterfaceDetailData = SP_DEVICE_INTERFACE_DETAIL_DATA;

     TForm1 = class(TForm)
       Button1: TButton;
       Memo1: TMemo;
     private
     public
     end;

    var
     Form1: TForm1;

    implementation

    {$R *.dfm}

    function SetupDiGetClassDevs(ClassGuid: PGUID;
                                const Enumerator: PAnsiChar;
                                hwndParent: HWND;
                                Flags: DWORD): HDEVINFO; stdcall; external 'SetupApi.dll' name 'SetupDiGetClassDevsA';
    function SetupDiEnumDeviceInfo(DeviceInfoSet: HDEVINFO;
                                  MemberIndex: DWORD;
                                  var DeviceInfoData: TSPDevInfoData): BOOL; stdcall; external 'SetupApi.dll';                            
    function SetupDiEnumDeviceInterfaces(DeviceInfoSet: HDEVINFO;
                                        DeviceInfoData: PSPDevInfoData;
                                        const InterfaceClassGuid: TGUID;
                                        MemberIndex: DWORD;
                                        var DeviceInterfaceData: TSPDeviceInterfaceData): BOOL; stdcall; external 'SetupApi.dll';
    function SetupDiGetInterfaceDeviceDetail(DeviceInfoSet: HDEVINFO;
                                            DeviceInterfaceData: PSPDeviceInterfaceData;
                                            DeviceInterfaceDetailData: PSPDeviceInterfaceDetailData;
                                            DeviceInterfaceDetailDataSize: DWORD;
                                            RequiredSize: PDWORD;
                                            Device: PSPDevInfoData): BOOL; stdcall; external 'SetupApi.dll' name 'SetupDiGetDeviceInterfaceDetailA';
    function SetupDiDestroyDeviceInfoList(DeviceInfoSet: HDEVINFO): BOOL; stdcall; external 'SetupApi.dll';

    процедуры

    end.

  • dimonbest (31.07.09 14:03) [6]
    Огромное человеческое спасибо.
    Код использовал свой, но Ваш помог разобраться что не так.
    я неправильно получал путь.
    Получал так:

    result:=DeviceInterfaceDetailData.DevicePath;


    Оно выдовало симол "/"
    А надо так:

    result:=pchar(@DeviceInterfaceDetailData.DevicePath);


    И выдает то что надо! :-)
  • Getulio (09.09.10 05:21) [7]
    Please, I'm Brazilian USB Developer and I can't read your description, but I understand your code. I stopped at the same point: DevInfoDetail^.cbSize := Sizeof(TSPDeviceInterfaceDetailData);  and I found the same error (Access Violation at address...)

    Can you to solve this error?

    Thank you so much!
  • Rouse_ © (11.09.10 01:45) [8]

    > Getulio   (09.09.10 05:21) [7]

    http://rouse.drkb.ru/files/devlist.zip
  • Getulio (14.09.10 01:26) [9]
    Thank You, Rouse.

    Best Regards!!!
  • sialia © (30.01.11 17:26) [10]
    SetupDiEnumDeviceInterfaces выдает ошибку 259 не знаете почему?
  • sialia © (30.01.11 17:30) [11]
    Здравствуйте у меня возникла такая проблема в коде который выше приведены
    SetupDiEnumDeviceInterfaces выдает ошибку 259 не знаете почему?
  • Дмитрий (11.02.11 13:43) [12]
    В чьём коде конкретно ? И настоятельно рекомендую сделать

    var LastError: Integer;
    ...
    SetLastError(0);
    ...
    LastError := GetLastError;
    FormatMessage(FORMAT_MESSAGE_FROM_SYSTEM, nil, LastError, LANG_SYSTEM_DEFAULT, chBufErr, 80, nil);
    MessageDlg('Error №'+IntToStr(LastError)+' :'+chBufErr, mtError, [mbOK], 0);


    И узнаете на что SetupDiEnumDeviceInterfaces ругаеццо...
  • sialia © (12.04.11 21:41) [13]
    Все эта проблема была из за не правильного GUID-a
    Я до этого использовал вот эти  
    USB_CLASS_GUID:TGUID = '{36FC9E60-C465-11CF-8056-444553540000}';
    USB_DEVICE_GUID:TGUID = '{A5DCBF10-6530-11D2-901F-00C04FB951ED}';

    но правильный вот такая
    GUID_DEVINTERFACE_DISK: TGUID = (
       D1:$53f56307; D2:$b6bf; D3:$11d0; D4:($94, $f2, $00, $a0, $c9, $1e, $fb, $8b));
  • 4elout © (26.06.13 09:59) [14]
    Люди, доброго времени суток. Мне бы проникнуть к памяти телефона, для восстановления инф. и необходимо прописать путь в прог-у, не подскажите как     этот путь найти и вообще возможно ли это?
  • Дмитрий (26.06.13 12:07) [15]
    Хм... А вы уверены, что всё так просто ? Систему команд и сервисную документацию телефона изучили ? Если ДА на оба вопроса - то дело за малым, открыть порт зная vid & pid & GUID не так уж сложно. См. пример выше. В сети много таких примеров, в том числе с поиском всех USB-устройств на шине и отслеживании WM_DEVICEARRIVAL в реальном времени.
  • 4elout © (26.06.13 14:28) [16]
    Начнем с того, что я "агроном любитель"... Нужно просто очень очень восстановить запись на тел. Если бы он определялся как носитель - это было бы все гораздо проще... Док-ию изучил, восстановления данных там нет, как хотелось бы(что тоже очень упростило бы ситуацию). Сейчас остался вариант восстановить инф-ю через прог. (напр. Recova) ну или др. не важно. Но они работают с определенным разделом или диском, а который нужно указывать путь... а так как тел. не опр. как носитель, его путь мне неизвестен и открывается он только через PC Studio.
    Я конечно пробовал указывать путь, как написано в диспетчере устр.
    Пример:
    usb\root_hub
    Что то вроде того, все перепробовал, щас просто тел. нет под рукой, он гулять ушел))
    Я  не утверждаю что я делаю все правильно просто экспериментирую... так что сильно не смейтесь)
    ... вот прога эта не понимает путь!!! Возможно ей его как-нибуть прописать, чтоб достучаться до внутр.памяти тел.????
  • Дмитрий (27.06.13 10:01) [17]
    А гуглить на тему ближайшего АСЦ (Авторизованного Сервисного Центра) по производителю телефона не пробовали ? Как правило производитель телефонов высылает АСЦ специализированный софт. В вашей ситуации - это самый простой на текущий момент выход. Не спорю, есть люди, которые не один год посвятили работой с телефонами на программном уровне,  помнится еще лет 7-8 назад первые "альтернативные производителю" программы появились. Но таких людей мало и они как правило обладают специализированной документацией для написания программ.
    А Рекува  работает только с ЛОГИЧЕСКИМИ дисками (не путать с физическим наличием носителя на шине)  или ТОМАМИ. Если диск в системе не определяется - она не поможет.
  • Дмитрий (27.06.13 10:05) [18]
    Да, на всякий случай,
    GUID_DEVINTERFACE_VOLUME: TGuid = {53F5630D-B6BF-11D0-94F2-00A0C91EFB8B};
  • 4elout © (27.06.13 17:12) [19]
    Спасибо! АСЦ - для незаморачивающихся людей)))
  • ffh2000 (10.01.14 21:03) [20]
    Ребят, поясните плиз.
    Вот я получил в посте Дмитрия от  (31.07.09 08:01) [1]

    ...
    DevPath:=PChar(@DevInfoDetail.devicepath);



    Это то имя устройства, которое я могу использовать в CreateFile?

    Вопрос задаю потому, что у меня USB термопринтер китайский (GPrinter GP3120-T), не поддерживает русские шрифты и мне надо сформировать картинку с текстом и отправить на него как команды принтера напрямую. Через COM3 все ок, но медленно. Его родная программа умеет с ним работать через COM и через USB (у принтера два порта). Понятно, что через USB быстрее на много. Но GDI драйвера в системе на этот принтер нет т.е. я не могу использовать обычный спулер печати.
    Я нашел имя этого устройства (пусть пока вручную с помощью программы от Rouse_. Имя такое: \Device\USBPDO-5. Вот тут http://www.itshop.ru/Visual-C-Rabota-s-USB-ustroystvami/l9i22755 (см. в самом конце статьи листинг) они передают именно  devinfodetail->devicepath. Если я передаю это имя, то получаю "Системе не удается найти указанный путь", как будто я открываю файл на диске. Аналогично я пробовал подставить имя порта COM1, он у меня есть в системе и его devinfodetail->devicepath = '\Device\0000006f', получаю ту же ошибку. А вот если вызову как 'COM1', то все нормально. Пробовал впереди писать '\\.', но толку нет.
    Может кто подскажет где собака порылась?
  • Rouse_ © (17.02.14 14:05) [21]

    > Может кто подскажет где собака порылась?

    CreateFile не откроет такие пути, используй ZwOpenFile()
 
Конференция "WinAPI" » Узнать путь USB устройства
Есть новые Нет новых   [134427   +35][b:0][p:0.008]