Russian Qt Forum

Qt => Общие вопросы => Тема начата: Alex Custov от Август 26, 2009, 16:03



Название: [windows] список USB накопителей
Отправлено: Alex Custov от Август 26, 2009, 16:03
Под виндз не писал уже несколько лет :) Как можно определить список подключенных USB накопителей, и информацию о них? В Qt форме необходимо вывести их буквы и метки (vendor+model если метки нет). Как это можно замутить? Кроссплатформенность неважна, программа будет только для виндз.


Название: Re: [windows] список USB накопителей
Отправлено: crackedmind от Август 26, 2009, 16:16
Почитай вот тут: http://msdn.microsoft.com/en-us/library/aa365730(VS.85).aspx


Название: Re: [windows] список USB накопителей
Отправлено: Alex Custov от Август 26, 2009, 16:17
Почитай вот тут: http://msdn.microsoft.com/en-us/library/aa365730(VS.85).aspx

угу, что-то похожее на правду. Спасибо.

Доп. А как узнать более подробную информацию об устройстве - vendor, model, bus и т.д.? Наподобие как в Linux через HAL.


Название: Re: [windows] список USB накопителей
Отправлено: crackedmind от Август 26, 2009, 18:35
Тут похоже надо копать в сторону Win DDK, средствами SDK это не решить.

p.s.
нашел программку, которая выводит различную инфу про разделы. http://www.winsim.com/diskid32/ Сорцы прилагаются.


Название: Re: [windows] список USB накопителей
Отправлено: zenden от Август 26, 2009, 19:04
можешь посмотреть исходники unetbootin (http://unetbootin.sourceforge.net/)
Написана на Qt4, каким-то образом получает список USB накопителей и винде, и в линуксе.


Название: Re: [windows] список USB накопителей
Отправлено: Alex Custov от Август 26, 2009, 19:33
спасибо, буду разбираться


Название: Re: [windows] список USB накопителей
Отправлено: Alex Custov от Август 26, 2009, 22:27
вобщем изыскания такие - unetbootin использует самый простой способ - берёт список дисков и отсеивает из них не-removable, это я уже и сам сделал :)

diskid32 делает всё через DDK, через DeviceIoControl. Проблема в том, что она показывает инфу только о жёстких дисках, а об USB флешках - нет (флешка вставлена). Глядя на код вижу, что там перебираются устройства по маске "\\\\.\\Scsi%d:" от 0 до 16. Может, USB накопители по другой маске индексируются?


Название: Re: [windows] список USB накопителей
Отправлено: ритт от Август 26, 2009, 23:27
конечно.
выведи dos-имена всех дисков - увидишь разницу...


Название: Re: [windows] список USB накопителей
Отправлено: kuzulis от Август 27, 2009, 07:55
А не проще ли читать реестр на предмет нужной информации? Пусть "ядро" самой винды берет инфу и кладет в реестр!

А Вы уже из рееестра! :)


Название: Re: [windows] список USB накопителей
Отправлено: Hordi от Август 27, 2009, 13:51
Вот тут я вендора и продукт айди получаю - ищи "SELECT * FROM Win32_USBControllerDevice".

Код:
void DrivesEnumerator::setDriveInfoEx(std::vector<DriveInfo>& rez,bool hasUSB)
{
  if(rez.empty()){
    return;
  }

  HRESULT hres = CoInitializeEx(0, COINIT_MULTITHREADED); //COINIT_APARTMENTTHREADED

  bool uninit = (S_OK==hres);

  IWbemLocator *pLoc = NULL;
  IWbemServices *pSvc = NULL;
  IEnumWbemClassObject* pEnumerator = NULL;
  IWbemClassObject *pclsObj = NULL;

  std::map<unicodeString,int> mm; //PnP-SN,index

  do{
    if(uninit){
      hres = CoInitializeSecurity(NULL,-1,NULL,NULL,
        RPC_C_AUTHN_LEVEL_DEFAULT,
        RPC_C_IMP_LEVEL_IMPERSONATE,
        NULL,EOAC_NONE,NULL);

      if(FAILED(hres)){
        break;
      }
    }

    hres = CoCreateInstance(CLSID_WbemLocator,0,CLSCTX_INPROC_SERVER,IID_IWbemLocator, (LPVOID*)&pLoc);

    if(FAILED(hres)){
      break;
    }

    hres = pLoc->ConnectServer(_bstr_t(L"ROOT\\CIMV2"),NULL,NULL,0,NULL,0,0,&pSvc);
     
    if(FAILED(hres)){
      break;
    }

    hres = CoSetProxyBlanket(
      pSvc,
      RPC_C_AUTHN_WINNT,
      RPC_C_AUTHZ_NONE,
      NULL,
      RPC_C_AUTHN_LEVEL_CALL,
      RPC_C_IMP_LEVEL_IMPERSONATE,
      NULL,
      EOAC_NONE
    );

    if(FAILED(hres)){
      break;
    }

    VARIANT v;
    HRESULT hr;

    //retrieving Drive's name
    hres = pSvc->ExecQuery( bstr_t("WQL"),
      bstr_t("SELECT * FROM Win32_DiskDrive"), //Win32_DiskDrive, PhysicalMedia , Win32_DiskDrivePhysicalMedia
      WBEM_FLAG_FORWARD_ONLY | WBEM_FLAG_RETURN_IMMEDIATELY,
      NULL,&pEnumerator);
     
    if(FAILED(hres)){
      break;
    }

    while(pEnumerator){
      ULONG uReturn = 0;

      hr = pEnumerator->Next(WBEM_INFINITE, 1, &pclsObj, &uReturn);

      if(0 == uReturn){
        break;
      }

      if(S_OK == (hr = pclsObj->Get(L"Index", 0, &v, 0, 0))){

        for(unsigned i=0;i<rez.size();++i){
          adf::gui::DriveInfo& r = rez[i];
          if(r.driveNumber() == (int)v.uintVal){

            if(S_OK == (hr = pclsObj->Get(L"Model", 0, &v, 0, 0))){
              r._name = v.bstrVal;
              VariantClear(&v);
            }
           
            if(!hasUSB){
              break;
            }
            if(S_OK != (hr = pclsObj->Get(L"InterfaceType", 0, &v, 0, 0))){
              break;
            }

            //SCSI,HDC,IDE,USB,1394
            bool ok = (unicodeString(v.bstrVal)==STRING_CONST("USB"));
            VariantClear(&v);
            if(!ok){
              break;
            }
            if(S_OK != (hr = pclsObj->Get(L"PNPDeviceID", 0, &v, 0, 0))){
              break;
            }
            unicodeString s = (v.bstrVal);
            VariantClear(&v);

            unicodeString::size_type ps, pos = s.rfind(UNICHR('\\'));
            if(unicodeString::npos!=pos){
              ps = s.find(UNICHR('&'),++pos);
              if(unicodeString::npos!=ps){
                mm[unicodeString(s.substr(pos,ps-pos))] = i;
              }
            }

            break;
          }
        }

        VariantClear(&v);
      }
    }

    if(!hasUSB){
      break;
    }

    if(pEnumerator){
      pEnumerator->Release();
    }

    //retrieving USB VendorID,ProductID
    hres = pSvc->ExecQuery( bstr_t("WQL"),
      bstr_t("SELECT * FROM Win32_USBControllerDevice"),
      WBEM_FLAG_FORWARD_ONLY | WBEM_FLAG_RETURN_IMMEDIATELY,
      NULL,&pEnumerator);
     
    if(FAILED(hres)){
      break;
    }

    while(pEnumerator){
      ULONG uReturn = 0;

      hr = pEnumerator->Next(WBEM_INFINITE, 1, &pclsObj, &uReturn);

      if(0 == uReturn){
        break;
      }

      if(S_OK == (hr = pclsObj->Get(L"Dependent", 0, &v, 0, 0))){

        unicodeString s = v.bstrVal;
        VariantClear(&v);
       
        //"USB\\VID_058F&PID_6387\\GXP25EUB"
        unicodeString str( STRING_CONST("=\"USB\\\\VID_") );
        unicodeString::size_type ps, pos = s.find(str);
        if(pos==unicodeString::npos){ //extract VendorID, ProductID, SerialNumber(for searching)
          continue;
        }
        pos += str.size();
        str = STRING_CONST("&PID_");
        ps = s.find(str,pos);
        if(unicodeString::npos==ps){
          continue;
        }

        unicodeString VID( s.substr(pos,ps-pos) );
        ps += str.size();
       
        //extract PID
        str = STRING_CONST("\\\\");
        pos = s.find(str,ps);
        if(unicodeString::npos==ps){
          continue;
        }
        unicodeString PID( s.substr(ps,pos-ps) );
        pos += str.size();
       
        if(unicodeString::npos != s.find(STRING_CONST("&"),pos)){
          continue;
        }

        //extract SerialNumber
        ps = s.find(STRING_CONST("\""),pos);
        if(unicodeString::npos==ps){
          continue;
        }

        unicodeString SN( s.substr(pos,ps-pos) );

        //set founded information
        std::map<unicodeString,int>::iterator it = mm.find(SN);
        if(it!=mm.end()){
          DriveInfo& r = rez[it->second];
          r._vendorID = VID;
          r._productID = PID;
          r._serial = SN;
        }
      }
    }

  }while(0);

  if(pSvc){
    pSvc->Release();
  }
  if(pLoc){
    pLoc->Release();
  }
  if(pEnumerator){
    pEnumerator->Release();
  }
  if(pclsObj){
    pclsObj->Release();
  }

  if(uninit){
    CoUninitialize();
  }
}


Название: Re: [windows] список USB накопителей
Отправлено: NurMKM от Март 13, 2013, 09:08
Вот тут я вендора и продукт айди получаю - ищи "SELECT * FROM Win32_USBControllerDevice".

Всем привет.

Hordi, у меня такая же задача найти вендор ид и прод ид USB флешки. Я не знаком с QT. Я вставил ваш код но у меня ссыпаются ошибки. Можете вы проконсультировать.
#include "stdafx.h"
#include <iostream>
#include <WTypes.h>
using namespace std;
#define _WIN32_DCOM
#include <comdef.h>
#include <Wbemidl.h>

# pragma comment(lib, "wbemuuid.lib") 
Я добавил эти библиотеки может еще какие то надо, что бы решить эти ошибки.
1>c:\users\user\desktop\c++\projects\wmi_device_pid\wmi_device_pid\wmi_device_pid.cpp(178): error C2065: 'r' : undeclared identifier
1>c:\users\user\desktop\c++\projects\wmi_device_pid\wmi_device_pid\wmi_device_pid.cpp(178): error C2228: left of '._name' must have class/struct/union
1>          type is ''unknown-type''
1>c:\users\user\desktop\c++\projects\wmi_device_pid\wmi_device_pid\wmi_device_pid.cpp(182): error C2065: 'hasUSB' : undeclared identifier
1>c:\users\user\desktop\c++\projects\wmi_device_pid\wmi_device_pid\wmi_device_pid.cpp(190): error C2446: '==' : no conversion from 'const char *' to 'BSTR'
1>          Types pointed to are unrelated; conversion requires reinterpret_cast, C-style cast or function-style cast
1>c:\users\user\desktop\c++\projects\wmi_device_pid\wmi_device_pid\wmi_device_pid.cpp(190): error C2440: '==' : cannot convert from 'const char [4]' to 'BSTR'
1>c:\users\user\desktop\c++\projects\wmi_device_pid\wmi_device_pid\wmi_device_pid.cpp(198): error C2065: 'unicodeString' : undeclared identifier
1>c:\users\user\desktop\c++\projects\wmi_device_pid\wmi_device_pid\wmi_device_pid.cpp(198): error C2146: syntax error : missing ';' before identifier 's'
1>c:\users\user\desktop\c++\projects\wmi_device_pid\wmi_device_pid\wmi_device_pid.cpp(198): error C2065: 's' : undeclared identifier
1>c:\users\user\desktop\c++\projects\wmi_device_pid\wmi_device_pid\wmi_device_pid.cpp(201): error C2653: 'unicodeString' : is not a class or namespace name
1>c:\users\user\desktop\c++\projects\wmi_device_pid\wmi_device_pid\wmi_device_pid.cpp(201): error C2065: 'size_type' : undeclared identifier   


Название: Re: [windows] список USB накопителей
Отправлено: Alex Custov от Март 13, 2013, 21:32
добавляю namespace, который я использовал в конечном проекте. Функция Ddk::drives(num) возвращает подключённые USB накопители, размер которых минимум num байт. Перед работой нужно вызвать Ddk::init()


Название: Re: [windows] список USB накопителей
Отправлено: lolbla2 от Март 15, 2013, 10:16
А как насчёт посмотреть в сторону libusb?


Название: Re: [windows] список USB накопителей
Отправлено: kuzulis от Март 15, 2013, 11:40
Под Windows проще всего использовать энумерацию устройств конкретного класса через SetupAPI:

SetupDiGetDeviceRegistryProperty + SetupDiOpenDevRegKey + SetupDiGetClassDevs + SetupDiEnumDeviceInfo

см. MSDN и гугл. :)

UPD: И никаких заголовков и прочего от WDK не нужно.