STORAGE_DEVICE_NUMBER = record DeviceType: DEVICE_TYPE; DeviceNumber: ULONG; PartitionNumber: ULONG; end; PSTORAGE_DEVICE_NUMBER = ^STORAGE_DEVICE_NUMBER;/// <summary> /// 根据盘符取硬件编号, 包括PID,VID,序列号 /// </summary> /// <param name="Drive"></param> /// <returns></returns> function GetHardwardIDs(const Drive: Char): string;/// <summary> /// 根据设备号取设备实例,函数名是GetDeviceInstanceByDeviceNumber的简称 /// </summary> /// <param name="Num"></param> /// <returns></returns> function GetDevInstByNum(Num: Integer): DEVINST;/// <summary> /// 根据盘符取设备号 /// </summary> /// <param name="ADrive"></param> /// <returns></returns> function GetDeviceNumberByDrive(const ADrive: Char): Integer;implementation/// <summary> /// 根据设备路径获取设备号 /// </summary> /// <param name="DevicePath">设备路径</param> /// <returns>失败返回-1</returns> function GetDeviceNumberByPath(const DevicePath: string): Integer; var h: THandle; sdn: STORAGE_DEVICE_NUMBER; dwBytesReturned: DWORD; Res: BOOL; begin Result := -1; h := CreateFile(PChar(DevicePath), 0, FILE_SHARE_READ or FILE_SHARE_WRITE, nil, OPEN_EXISTING, 0, 0); if ( h <> INVALID_HANDLE_VALUE ) then begin dwBytesReturned := 0; res := DeviceIoControl(h, IOCTL_STORAGE_GET_DEVICE_NUMBER, nil, 0, @sdn, sizeof(sdn), dwBytesReturned, nil); if (res) then Result := sdn.DeviceNumber; CloseHandle(h);//关闭句柄 end; end;// function GetDevInstByNum(Num: Integer): DEVINST; const USBGUID: TGUID = '{53f56307-b6bf-11d0-94f2-00a0c91efb8b}'; var // USBGuid: TGUID; USBHandle: HDEVINFO; Devn: Integer; DevData: TSPDevInfoData; interfaceData: TSPDeviceInterfaceData; detailData: PSPDeviceInterfaceDetailData; BytesReturned: DWORD; DevicePath: String; begin Result := INVALID_HANDLE_VALUE; USBHandle := SetupDiGetClassDevsA(@USBGuid, nil, 0, DIGCF_PRESENT Or DIGCF_DEVICEINTERFACE); if USBHandle = Pointer(INVALID_HANDLE_VALUE) then Exit; Devn := 0; while True do begin interfaceData.cbSize := SizeOf(TSPDeviceInterfaceData); if not SetupDiEnumDeviceInterfaces(USBHandle, Nil, USBGuid, Devn, interfaceData) then Break; DevData.cbSize := SizeOf(DevData); BytesReturned := 0; SetupDiGetDeviceInterfaceDetailA(USBHandle, @interfaceData, Nil, 0, BytesReturned, @DevData); if (BytesReturned <> 0) And (GetLastError = ERROR_INSUFFICIENT_BUFFER) then begin detailData := AllocMem(BytesReturned); try detailData.cbSize := SizeOf(TSPDeviceInterfaceDetailData); if SetupDiGetDeviceInterfaceDetailA(USBHandle, @interfaceData, detailData, BytesReturned, BytesReturned, @DevData) Then begin DevicePath := StrPas(PChar(@detailData.DevicePath)); if Num = GetDeviceNumberByPath(DevicePath) then begin Result := DevData.DevInst; Break; end; end;
finally FreeMem(detailData); end;//try finally end end; Inc(Devn); end; SetupDiDestroyDeviceInfoList(USBHandle); end;function GetDeviceNumberByDrive(const ADrive: Char): Integer; const DevicePath = '\\?\%s:'; begin Result := GetDeviceNumberByPath(Format(DevicePath, [ADrive])); end;function GetHardwardIDs(const Drive: Char): string; var Buffer: array[0..MAX_PATH- 1] of Char; hDevInst, DevInstParent: DEVINST; Num: Integer; begin Result := '';
//根据设备取得设备号 Num := GetDeviceNumberByDrive(Drive); if Num = -1 then Exit; hDevInst := GetDevInstByNum(Num); if hDevInst = INVALID_HANDLE_VALUE then Exit; FillChar(Buffer, MAX_PATH, 0); CM_Get_Parent(DevInstParent, hDevInst, 0); CM_Get_Device_ID(DevInstParent, Buffer, MAX_PATH, 0);
Result := StrPas(Buffer); end;initialization LoadSetupApi; CfgMgr32.LoadConfigManagerApi;finalization Setupapi.UnloadSetupApi; CfgMgr32.UnloadConfigManagerApi; end.这是我帮你找到的,看看能不能用到,如果不能,就帮不了你了
哈哈 "wzwcn" 同学也不算瞎掰了,因为他可能只做过 USB->COM 的设备 采用于CDC驱动或专用的USB转COM驱动楼主是有这么一个设备 接上PC 后 枚举成三个设备? 一个HID 一个 MassStorage 一个USB 声卡?此时你可以调用设备管理函数 枚举全部设备或仅仅 USB 类型设备 找出你需要的设备列表就行了这些函数在 SetupApi.pas 单元中,网上很好找例如下函数把 接在PC上的WM手机枚举出来var ii: Integer; gd: TGUID; hdi: hDevInfo; pszText: array[0..255] of char; DeviceInfoData: TSPDevInfoData; begin ii := 0; Result := 0; gd := StringToGUID('{4D36E972-E325-11CE-BFC1-08002BE10318}'); DeviceInfoData.cbSize := SizeOf(TSPDevInfoData); hdi := SetupDiGetClassDevs(@gd, PChar('USB'), 0, DIGCF_PRESENT); if (hdi <> Pointer(INVALID_HANDLE_VALUE)) then begin while SetupDiEnumDeviceInfo(hdi, ii, DeviceInfoData) do begin ConstructDeviceName(hdi, DeviceInfoData, pszText, DWord(nil)); if Pos('Mobile-based',pszText) > 0 then begin Result := 1; if CheckMBDState(DeviceInfoData.DevInst) <> CM_PROB_DISABLED then Result := 2; end; if Result > 0 then break; Inc(ii); end; end; SetupDiDestroyDeviceInfoList(hdi); end;
hjkto: 不知能否帮小弟找下那篇帖子?
lhylhy:不知能否具体些?
谢谢你的回答。不知能否给点具体的提示。比方给段核心代码看下?
鄙视 #2 这类回复,
至少给出你的方案吧。
类似以上的回复,是说明你知道的多呢?还是说明你也不知道呢?lz,如果你的USB 是用于COM设备,通过一个 什么USBSeries的驱动的话,
#1楼是正解。
如果是,2个鼠标……呵呵,没有研究过,当偶是飘过的一片雾水好了。
谢谢你的回复。我目前的情况是: 一根USB线上接了三个设备(Hid设备、Flash芯片、声卡)。
如果有,好办一点,用注册表的方式可以得到。
如果没有,我没撤,或者需要研究一下那些个Device(Windows.pas)可能是方向。
你没见楼主说的是Hid设备、Flash芯片、声卡? 这些设备会映射成COM口?1楼说的"USB连到电脑上其实是映射成COM口的", 这个USB难道是特指Serial-USB设备?
GetDriveType
GetVolumeInformation用上面三个API函数即可解决你的问题一。
如果需要相关代码我也可以详细给你写出。
interfaceuses Windows, SysUtils, SetupApi, CfgMgr32;const
IOCTL_STORAGE_GET_DEVICE_NUMBER = 2953344;
type
DEVICE_TYPE = DWORD;
STORAGE_DEVICE_NUMBER = record
DeviceType: DEVICE_TYPE;
DeviceNumber: ULONG;
PartitionNumber: ULONG;
end;
PSTORAGE_DEVICE_NUMBER = ^STORAGE_DEVICE_NUMBER;/// <summary>
/// 根据盘符取硬件编号, 包括PID,VID,序列号
/// </summary>
/// <param name="Drive"></param>
/// <returns></returns>
function GetHardwardIDs(const Drive: Char): string;/// <summary>
/// 根据设备号取设备实例,函数名是GetDeviceInstanceByDeviceNumber的简称
/// </summary>
/// <param name="Num"></param>
/// <returns></returns>
function GetDevInstByNum(Num: Integer): DEVINST;/// <summary>
/// 根据盘符取设备号
/// </summary>
/// <param name="ADrive"></param>
/// <returns></returns>
function GetDeviceNumberByDrive(const ADrive: Char): Integer;implementation/// <summary>
/// 根据设备路径获取设备号
/// </summary>
/// <param name="DevicePath">设备路径</param>
/// <returns>失败返回-1</returns>
function GetDeviceNumberByPath(const DevicePath: string): Integer;
var
h: THandle;
sdn: STORAGE_DEVICE_NUMBER; dwBytesReturned: DWORD;
Res: BOOL;
begin
Result := -1; h := CreateFile(PChar(DevicePath),
0,
FILE_SHARE_READ or FILE_SHARE_WRITE,
nil, OPEN_EXISTING, 0, 0); if ( h <> INVALID_HANDLE_VALUE ) then
begin
dwBytesReturned := 0;
res := DeviceIoControl(h,
IOCTL_STORAGE_GET_DEVICE_NUMBER,
nil, 0, @sdn, sizeof(sdn),
dwBytesReturned, nil);
if (res) then
Result := sdn.DeviceNumber; CloseHandle(h);//关闭句柄
end;
end;//
function GetDevInstByNum(Num: Integer): DEVINST;
const
USBGUID: TGUID = '{53f56307-b6bf-11d0-94f2-00a0c91efb8b}';
var
// USBGuid: TGUID;
USBHandle: HDEVINFO; Devn: Integer;
DevData: TSPDevInfoData;
interfaceData: TSPDeviceInterfaceData;
detailData: PSPDeviceInterfaceDetailData;
BytesReturned: DWORD; DevicePath: String;
begin
Result := INVALID_HANDLE_VALUE; USBHandle := SetupDiGetClassDevsA(@USBGuid, nil, 0, DIGCF_PRESENT Or DIGCF_DEVICEINTERFACE); if USBHandle = Pointer(INVALID_HANDLE_VALUE) then Exit; Devn := 0;
while True do
begin
interfaceData.cbSize := SizeOf(TSPDeviceInterfaceData); if not SetupDiEnumDeviceInterfaces(USBHandle, Nil, USBGuid, Devn, interfaceData) then
Break; DevData.cbSize := SizeOf(DevData);
BytesReturned := 0;
SetupDiGetDeviceInterfaceDetailA(USBHandle, @interfaceData, Nil, 0, BytesReturned, @DevData); if (BytesReturned <> 0) And (GetLastError = ERROR_INSUFFICIENT_BUFFER) then
begin
detailData := AllocMem(BytesReturned);
try
detailData.cbSize := SizeOf(TSPDeviceInterfaceDetailData);
if SetupDiGetDeviceInterfaceDetailA(USBHandle, @interfaceData, detailData, BytesReturned, BytesReturned, @DevData) Then
begin
DevicePath := StrPas(PChar(@detailData.DevicePath)); if Num = GetDeviceNumberByPath(DevicePath) then
begin
Result := DevData.DevInst;
Break;
end;
end;
finally
FreeMem(detailData);
end;//try finally end
end;
Inc(Devn);
end;
SetupDiDestroyDeviceInfoList(USBHandle);
end;function GetDeviceNumberByDrive(const ADrive: Char): Integer;
const
DevicePath = '\\?\%s:';
begin
Result := GetDeviceNumberByPath(Format(DevicePath, [ADrive]));
end;function GetHardwardIDs(const Drive: Char): string;
var
Buffer: array[0..MAX_PATH- 1] of Char;
hDevInst, DevInstParent: DEVINST;
Num: Integer;
begin
Result := '';
//根据设备取得设备号
Num := GetDeviceNumberByDrive(Drive);
if Num = -1 then Exit; hDevInst := GetDevInstByNum(Num);
if hDevInst = INVALID_HANDLE_VALUE then Exit;
FillChar(Buffer, MAX_PATH, 0);
CM_Get_Parent(DevInstParent, hDevInst, 0);
CM_Get_Device_ID(DevInstParent, Buffer, MAX_PATH, 0);
Result := StrPas(Buffer);
end;initialization
LoadSetupApi;
CfgMgr32.LoadConfigManagerApi;finalization
Setupapi.UnloadSetupApi;
CfgMgr32.UnloadConfigManagerApi;
end.这是我帮你找到的,看看能不能用到,如果不能,就帮不了你了
// 1、本单元使用了jcl代码库中的Setupapi及CfgMgr32单元
// http://sourceforge.net/projects/jcl/
// http://jvcl.sourceforge.net/
// 2、Delphi 7.0
http://hi.baidu.com/combojiang/blog/item/035b332456a2eb074c088dca.html (一)
http://hi.baidu.com/combojiang/blog/item/7953d6d7a31edbdba144dfcb.html (二)我把他翻译成Delphi的了,想试试可以不可以满足我的需求。但现在的问题是我调用GetRootHubName时返回得总是空值。不知道问题出在哪里?关键代码如下:
function TForm1.GetRootHubName(AHostController: THandle): PChar;
var
bSuccess: Boolean;
nBytes: ULONG;
rootHubName: USB_ROOT_HUB_NAME;
rootHubNameW: PUSB_ROOT_HUB_NAME;
rootHubNameA: PChar; procedure GetRootHubNameError;
begin
if Assigned(rootHubNameW) then
begin
Dispose(rootHubNameW);
rootHubNameW := nil;
end;
end;begin
Result := nil;
rootHubNameW := nil;
rootHubNameA := nil;
bSuccess := DeviceIoControl(AHostController,
IOCTL_USB_GET_ROOT_HUB_NAME,
0,
0,
@rootHubName,
SizeOf(rootHubName),
nBytes,
nil); if not bSuccess then
begin
GetRootHubNameError;
Exit;
end; nBytes := rootHubName.ActualLength;
New(rootHubNameW); bSuccess := DeviceIoControl(AHostController,
IOCTL_USB_GET_ROOT_HUB_NAME,
0,
0,
rootHubNameW,
nBytes,
nBytes,
nil); if not bSuccess then
begin
GetRootHubNameError;
Exit;
end; rootHubNameA := WideStrToMultiStr(rootHubName.RootHubName);
Dispose(rootHubNameW);
Result := rootHubNameA;
end;
var
IOCTL_USB_GET_ROOT_HUB_NAME,
IOCTL_GET_HCD_DRIVERKEY_NAME: DWORD; type PUSB_ROOT_HUB_NAME = ^USB_ROOT_HUB_NAME;
USB_ROOT_HUB_NAME = packed record
ActualLength: ULONG;
RootHubName: array [0..0] of WCHAR;
end;
function CTL_CODE( _DeviceType, _Function, _Method, _Access:DWORD ):DWORD; implementationfunction CTL_CODE( _DeviceType, _Function, _Method, _Access:DWORD ):DWORD;
begin
Result:= (_DeviceType SHL 16) or (_Access SHL 14) or (_Function SHL 2) or _Method;
end;initializationIOCTL_USB_GET_ROOT_HUB_NAME :=
CTL_CODE(FILE_DEVICE_USB, USB_IOCTL_INDEX + 3, METHOD_BUFFERED, FILE_ANY_ACCESS);end.
// 不同类的设备,即使没有UID,也可以根据返回的不同名称区分不同的设备。
不知可否具体些?万分感谢!
ii: Integer;
gd: TGUID;
hdi: hDevInfo;
pszText: array[0..255] of char;
DeviceInfoData: TSPDevInfoData;
begin
ii := 0;
Result := 0;
gd := StringToGUID('{4D36E972-E325-11CE-BFC1-08002BE10318}');
DeviceInfoData.cbSize := SizeOf(TSPDevInfoData);
hdi := SetupDiGetClassDevs(@gd, PChar('USB'), 0, DIGCF_PRESENT);
if (hdi <> Pointer(INVALID_HANDLE_VALUE)) then
begin
while SetupDiEnumDeviceInfo(hdi, ii, DeviceInfoData) do
begin
ConstructDeviceName(hdi, DeviceInfoData, pszText, DWord(nil)); if Pos('Mobile-based',pszText) > 0 then
begin
Result := 1;
if CheckMBDState(DeviceInfoData.DevInst) <> CM_PROB_DISABLED then
Result := 2;
end; if Result > 0 then break;
Inc(ii);
end;
end;
SetupDiDestroyDeviceInfoList(hdi);
end;