![]() |
| ||
|
|
Новости |
Поиск |
FAQ |
Статьи |
Книги |
Новости VCL
| | Форумы ЧАТ |
Орешник |
|
| |||
| |||
« предыдущая ветвь | форум | следующая ветвь »
как можно узнать модель USB-устройства?
Ral'f © (2007-06-14 14:47:00)Серийный номер USB-устройства определяю так:
var VolumeName, FileSystemName : array [0..MAX_PATH-1] of Char;
VolumeSerialNo : DWord;
MaxComponentLength,FileSystemFlags: Cardinal;
begin
GetVolumeInformation('J:\',VolumeName,MAX_PATH,@VolumeSerialNo,
MaxComponentLength,FileSystemFlags, FileSystemName,MAX_PATH);
Memo1.Lines.Add('SerialNo = $'+IntToHex(VolumeSerialNo,8));
А как можно узнать (дополнительно) его модель? (Пр.: "Kingston DataTraveler ( DTI/512 )")
Dimaxx (2007-06-18 10:43:00) [1]Вот еще нарыл. Дешего и сердито. Плюс чтение/запись есть до кучи, с демками.
http://www.soft-gems.net/supplement/download.php?ID=37
Riply (2007-06-16 20:29:00) [2]> [15] Riply © (16.06.07 20:21)
Забыла добавить к
"Следующий сюрприз: при нашем запросе, если мы задали слишком маленький буффер для приема данных,
мало того, что этот поросенок (DeviceIoControl :) вернет True, так еще и
GetLastError вернет нам ERROR_SUCCESS :)"
cbReturned вернет сколько байт реально записано, а не сколько на самом деле нужно.
Riply (2007-06-16 20:21:00) [3]Искомое можно получить, примерно, так:
Весь код не привожу, т.к. его очень сложно выдернуть из проекта.
Опишу, только, подводные камни, с которыми я столкнулась
Первая проблема: несоответствие размера параметров структур из заголовочных файлов С++ с Delphi.
Здесь мой вариант ее решения(не факт, что правильный, но рабочий :)
Менять закоментированность {$MINENUMSIZE 4} не рекомендуется :)
Я предпочла не везде его({$MINENUMSIZE) использовать,
а ввести доп. поле _Fill: array[0..2] of Byte; в _STORAGE_DEVICE_DESCRIPTOR
и изменить размерность AdditionalParameters: array[0..9] of Byte в STORAGE_PROPERTY_QUERY
т.к. было необходимо поддержать "совместимость размерности» и в др. запросах и структурах.
type
//{$MINENUMSIZE 4}
PSTORAGE_QUERY_TYPE = ^STORAGE_QUERY_TYPE;
_STORAGE_QUERY_TYPE = (PropertyStandardQuery = 0, // Retrieves the descriptor
PropertyExistsQuery, // Used to test whether the descriptor is supported
PropertyMaskQuery, // Used to retrieve a mask of writeable fields in the descriptor
PropertyQueryMaxDefined); // use to validate the value
STORAGE_QUERY_TYPE = _STORAGE_QUERY_TYPE;
//{$MINENUMSIZE 4-}
type
//{$MINENUMSIZE 4}
PSTORAGE_PROPERTY_ID = ^STORAGE_PROPERTY_ID;
_STORAGE_PROPERTY_ID = (StorageDeviceProperty = 0, StorageAdapterProperty, StorageDeviceIdProperty);
STORAGE_PROPERTY_ID = _STORAGE_PROPERTY_ID;
//{$MINENUMSIZE 4-}
type
PSTORAGE_PROPERTY_QUERY = ^STORAGE_PROPERTY_QUERY;
_STORAGE_PROPERTY_QUERY = packed record
PropertyId: STORAGE_PROPERTY_ID;
QueryType: STORAGE_QUERY_TYPE;
AdditionalParameters: array[0..9] of Byte;
end;
STORAGE_PROPERTY_QUERY = _STORAGE_PROPERTY_QUERY;
type
{$MINENUMSIZE 4}
PSTORAGE_BUS_TYPE = ^STORAGE_BUS_TYPE;
_STORAGE_BUS_TYPE = (BusTypeUnknown = 0, BusTypeScsi, BusTypeAtapi, BusTypeAta, BusType1394,
BusTypeSsa, BusTypeFibre, BusTypeUsb, BusTypeRAID, BusTypeiScsi,
BusTypeSas, BusTypeSata, BusTypeMaxReserved = $7F);
STORAGE_BUS_TYPE = _STORAGE_BUS_TYPE;
{$MINENUMSIZE 4-}
type
PSTORAGE_DEVICE_DESCRIPTOR = ^STORAGE_DEVICE_DESCRIPTOR;
_STORAGE_DEVICE_DESCRIPTOR = packed record
Version: DWord; // Sizeof(_STORAGE_DEVICE_DESCRIPTOR)
Size: DWord; // Total size of the descriptor, including the space for additional data and id strings
DeviceType: Byte; // The SCSI-2 device type
DeviceTypeModifier: Byte; // The SCSI-2 device type modifier, if any, - this may be zero
RemovableMedia: Boolean;
CommandQueueing: Boolean;
VendorIdOffset: DWord;
ProductIdOffset: DWord;
ProductRevisionOffset: DWord;
SerialNumberOffset: DWord;
BusType: STORAGE_BUS_TYPE;
RawPropertiesLength: DWord;
_Fill: array[0..2] of Byte;
RawDeviceProperties: array[0..0] of Byte;
end;
STORAGE_DEVICE_DESCRIPTOR = _STORAGE_DEVICE_DESCRIPTOR;
Разобравшись с размерами полей, переходим к попытке получить, нужные нам данные:
Следующий сюрприз: при нашем запросе, если мы задали слишком маленький буффер для приема данных,
мало того, что этот поросенок (DeviceIoControl :) вернет True, так еще и
GetLastError вернет нам ERROR_SUCCESS :)
В нашем запросе значения ERROR_MORE_DATA и ERROR_INSUFFICIENT_BUFFER,
GetLastError, почему-то выдавать не хочет :)
Схема того, как я пыталась бороться c этим "все в порядке" ниже.
const
IOCTL_STORAGE_QUERY_PROPERTY = ((IOCTL_STORAGE_BASE shl 16) or (FILE_ANY_ACCESS shl 14) or
($0500 shl 2) or METHOD_BUFFERED);
const
DEVICE_DESCRIPTOR_INC = 512 - SizeOf(STORAGE_DEVICE_DESCRIPTOR);
function StorageQueryProperty(const hDevice: THandle; var pDescript: PSTORAGE_DEVICE_DESCRIPTOR; var cbDescript, cbReturned: DWord): DWord;
var
PropQuery: STORAGE_PROPERTY_QUERY;
begin
FillChar(PropQuery, SizeOf(STORAGE_PROPERTY_QUERY), 0);
PropQuery.PropertyId := StorageDeviceProperty;
PropQuery.QueryType := PropertyStandardQuery;
while DeviceIoControl(hDevice, IOCTL_STORAGE_QUERY_PROPERTY,
@PropQuery, SizeOf(STORAGE_PROPERTY_QUERY),
pDescript, cbDescript, cbReturned, nil) do
begin
Result := GetLastError;
case Result of
ERROR_SUCCESS:
if (pDescript.Size >= cbReturned) then
begin
cbDescript := pDescript.Size + DEVICE_DESCRIPTOR_INC;
ReallocMem(pDescript, cbDescript);
end
else Break;
// ERROR_MORE_DATA:
// begin
// if cbReturned > cbDescript then cbDescript := cbReturned else inc(cbDescript, IO_BUFFER_SIZE_INC);
// ReallocMem(pDescript, cbDescript);
// end;
// ERROR_INSUFFICIENT_BUFFER:
// begin
// inc(cbDescript, IO_BUFFER_SIZE_INC);
// ReallocMem(pDescript, cbDescript);
// end;
// else Break;
Вот, вроде и все.
Разобраться со смещениями в STORAGE_DEVICE_DESCRIPTOR и перевести наши данные на "человеческий язык"
оставляю в виде домашнего задания :)
P.S. Выдергивалось и подгонялось "на коленке", так что строго не судить.
Но принцип сохранился :)
Вот кусочек, возвращаемых данных:
RemovableMedia: True
CommandQueueing: False
BusType: BusTypeUsb
VendorId: C-ONE-5.0
ProductId: 128MB Aqua
ProductRevision: 1.03
Ral'f (2007-06-16 12:56:00) [4]Так и придётся сделать! Надеялся по-быстренькому... :-)))
Пока я, наверно, буду использовать метку тома, а там глядишь - мож что вычитаю!
Правда, пока искал неоднократно встречал сообщения про NoName устройства, вроде как от серийников во всём мире сейчас отказываются. Так что, может, и связываться не стоит!
koha (2007-06-16 12:39:00) [5]
> Ral'f (14.06.07 14:47) [0]
Найди книгу "Интерфейс USB практика использования и программирования"
Автор: Павел Агуров. Издатель: Санкт-Петербург "БХВ-Петербург" 2005
- там почти все про USB
Ral'f (2007-06-16 08:54:00) [6]> к ним надо не CreateFile(PChar('\\.\С:'), а как к физическому устройству
Думаешь я не пробовал?!!!!!!!
Dimaxx (2007-06-15 21:59:00) [7]Я же написал, что все флэш накопители становятся съемными жесткими дисками. Значит обращаться к ним надо не
CreateFile(PChar('\\.\С:'), а как к физическому устройству, т.е.CreateFile(PChar('\\.\PhysicalDriveХ'), где Х - номер физического устройства.
Dimaxx (2007-06-15 21:59:00) [8]Я же написал, что все флэш накопители становятся съемными жесткими дисками. Значит обращаться к ним надо не
CreateFile(PChar('\\.\С:'), а как к физическому устройству, т.е.CreateFile(PChar('\\.\PhysicalDriveХ'), где Х - номер фичиеского устройства.
Ral'f (2007-06-15 21:37:00) [9]У меня хард на компьютере разбит на два раздела: С и D
Когда я пишу:
if Win32Platform=VER_PLATFORM_WIN32_NT then
begin // Windows NT, Windows 2000
Str(ControllerNumber,s);
hDevice := CreateFile(PChar('\\.\С:'), // или D
подключаю flash, пишу “F” и ничего не получаю!
С помощью этих кодов можно получить информацию только о внутренних устройствах:
HDD, DVD-ROM…
Или что-то надо дописать, чтобы он понимал и внешние (usb)?
P.S. попробовал и IdeInfo2 , и IdeSN2 !
Dimaxx (2007-06-15 16:18:00) [10]У меня все работает под ХР. Недавно проверял и брал оттуда некоторые вещи для своей проги.
Ral'f (2007-06-15 15:33:00) [11]Всё-равно спасибо!
Ral'f (2007-06-15 15:32:00) [12]> IdeInfo2 - получение различной информации об IDE диске
- то, что нужно, НО в XP не работает (а сейчас в основном везде эта ОС)
> IdeSN2 - получение серийного номера первого IDE диска
- в первом, как раз, у меня необходимости то и нету!
Dimaxx (2007-06-15 14:31:00) [13]Да, забыл отметить. USB-накопители (флэшки, USB-винты) в системе становятся съемными жесткими дисками, поэтому к ним можно обращаться через CreateFile, следовательно, вышеуказанные примеры к ним применимы.
Dimaxx (2007-06-15 14:28:00) [14]Вот тебе в помощь. Как раз определяется и тип устройства, и модель, и серийный номер.
IdeInfo2 - получение различной информации об IDE диске( http://home.earthlink.net/~akonshin/files/IdeInfo2.zip, 30 Jul 2000, 27K, D3+) С помощью SMART Ioctl API можно получить модель, версию прошивки, серийный номер, состояния различных счетчиков IDE винчестера. Проверялось на Windows 98, Windows NT 4.0 и Windows 2000.
IdeSN - получение серийного номера первого IDE диска( http://home.earthlink.net/~akonshin/files/IdeSN.zip, 30 Jul 2000, 4K, D3+) Пример, показывающий как получить серийный номер первого IDE винчестера. Проверялось на Windows 98, Windows NT 4.0 и Windows 2000.
IdeSN2 - получение серийного номера первого IDE диска(новый пример) ( http://home.earthlink.net/~akonshin/files/IdeSN2.zip, 22 Oct 2003, 5K, D5+) Пример, показывающий как получить серийный номер первого IDE винчестера. Проверялось на Windows 98, Windows NT 4.0, Windows 2000 и Windows XP.
Ral'f (2007-06-15 13:49:00) [15]Да, после форматирования VolumeSerialNo меняется (
Попробовал я поискать в реестре - нашёл!
Что-то типа ID устройств там, правда, есть!
Но тогда как связать в программе - запись в реестре и букву диска?
Теперь вопрос даже - как вообще можно идентифицировать внешнее устройство (будь это флешка, плекстор или карта памяти)?
Ral'f (2007-06-14 16:04:00) [16]и на том спасибо!
Правильный Вася (2007-06-14 15:26:00) [17]это в реестре покопаться
LocalMachine\system\currentcontrolset