二話不說,直接給代碼,如果您真想做這方面的東西,還是稍微研究下,沒有現成的好類用,就需要自己了解其原理
//引用空間
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Text;
using System.Windows.Forms;
using System.Runtime.InteropServices;
using System.Threading;
using System.Collections;
using System.IO;
//以下是調用windows的API的函數
//獲得GUID
[DllImport("hid.dll")]
public static extern void HidD_GetHidGuid(ref Guid HidGuid);
Guid guidHID = Guid.Empty;
//過濾裝置,擷取需要的裝置
[DllImport("setupapi.dll", SetLastError = true)]
public static extern IntPtr SetupDiGetClassDevs(ref Guid ClassGuid, uint Enumerator, IntPtr HwndParent, DIGCF Flags);
IntPtr hDevInfo;
//擷取裝置,true擷取到
[DllImport("setupapi.dll", CharSet = CharSet.Auto, SetLastError = true)]
public static extern Boolean SetupDiEnumDeviceInterfaces(IntPtr hDevInfo, IntPtr devInfo, ref Guid interfaceClassGuid, UInt32 memberIndex, ref SP_DEVICE_INTERFACE_DATA deviceInterfaceData);
public struct SP_DEVICE_INTERFACE_DATA
{
public int cbSize ;
public Guid interfaceClassGuid;
public int flags;
public int reserved;
}
// 擷取接口的詳細資訊 必須調用兩次 第1次傳回長度 第2次擷取資料
[DllImport("setupapi.dll", SetLastError = true, CharSet = CharSet.Auto)]
private static extern bool SetupDiGetDeviceInterfaceDetail(IntPtr deviceInfoSet, ref SP_DEVICE_INTERFACE_DATA deviceInterfaceData, IntPtr deviceInterfaceDetailData,
int deviceInterfaceDetailDataSize, ref int requiredSize, SP_DEVINFO_DATA deviceInfoData);
[StructLayout(LayoutKind.Sequential)]
public class SP_DEVINFO_DATA
public int cbSize = Marshal.SizeOf(typeof(SP_DEVINFO_DATA));
public Guid classGuid = Guid.Empty; // temp
public int devInst = 0; // dumy
public int reserved = 0;
[StructLayout(LayoutKind.Sequential, Pack = 2)]
internal struct SP_DEVICE_INTERFACE_DETAIL_DATA
internal int cbSize;
internal short devicePath;
public enum DIGCF
DIGCF_DEFAULT = 0x1,
DIGCF_PRESENT = 0x2,
DIGCF_ALLCLASSES = 0x4,
DIGCF_PROFILE = 0x8,
DIGCF_DEVICEINTERFACE = 0x10
//擷取裝置檔案
[DllImport("kernel32.dll", SetLastError = true)]
private static extern int CreateFile(
string lpFileName, // file name
uint dwDesiredAccess, // access mode
uint dwShareMode, // share mode
uint lpSecurityAttributes, // SD
uint dwCreationDisposition, // how to create
uint dwFlagsAndAttributes, // file attributes
uint hTemplateFile // handle to template file
);
//讀取裝置檔案
[DllImport("Kernel32.dll",SetLastError = true)]
private static extern bool ReadFile
(
IntPtr hFile,
byte[] lpBuffer,
uint nNumberOfBytesToRead,
ref uint lpNumberOfBytesRead,
IntPtr lpOverlapped
//釋放裝置
static public extern bool HidD_FreePreparsedData(ref IntPtr PreparsedData);
//關閉通路裝置句柄,結束程序的時候把這個加上保險點
[DllImport("kernel32.dll")]
static public extern int CloseHandle(int hObject);
接下來是通路裝置的代碼
//代碼暫時沒有整理,傳入參數是裝置序号,
//有些USB裝置其實有很多HID裝置,就是一個接口上有幾個裝置,這個時候需要
//用index++來逐個循環,直到擷取裝置傳回false後,跳出去,把擷取的裝置
//路徑全記錄下來就好了,我這裡知道具體裝置号,是以沒有循環,浪費我時間
//定于句柄序号和一些參數,具體可以去網上找這些API的參數說明,後文我看能不能把資料也寫上去
int HidHandle = -1;
public const uint GENERIC_READ = 0x80000000;
public const uint GENERIC_WRITE = 0x40000000;
public const uint FILE_SHARE_READ= 0x00000001;
public const uint FILE_SHARE_WRITE = 0x00000002;
public const int OPEN_EXISTING = 3;
private void UsBMethod(int index)
HidD_GetHidGuid(ref guidHID);
hDevInfo = SetupDiGetClassDevs(ref guidHID, 0, IntPtr.Zero, DIGCF.DIGCF_PRESENT | DIGCF.DIGCF_DEVICEINTERFACE);
int bufferSize = 0;
ArrayList HIDUSBAddress = new ArrayList();
//while (true)
//{
//擷取裝置,true擷取到
SP_DEVICE_INTERFACE_DATA DeviceInterfaceData = new SP_DEVICE_INTERFACE_DATA();
DeviceInterfaceData.cbSize = Marshal.SizeOf(DeviceInterfaceData);
//for (int i = 0; i < 3; i++)
bool result = SetupDiEnumDeviceInterfaces(hDevInfo, IntPtr.Zero, ref guidHID, (UInt32)index, ref DeviceInterfaceData);
//}
//第一次調用出錯,但可以傳回正确的Size
SP_DEVINFO_DATA strtInterfaceData = new SP_DEVINFO_DATA();
result = SetupDiGetDeviceInterfaceDetail(hDevInfo, ref DeviceInterfaceData, IntPtr.Zero, 0, ref bufferSize, strtInterfaceData);
//第二次調用傳遞傳回值,調用即可成功
IntPtr detailDataBuffer = Marshal.AllocHGlobal(bufferSize);
SP_DEVICE_INTERFACE_DETAIL_DATA detailData = new SP_DEVICE_INTERFACE_DETAIL_DATA();
detailData.cbSize = Marshal.SizeOf(typeof(SP_DEVICE_INTERFACE_DETAIL_DATA));
Marshal.StructureToPtr(detailData, detailDataBuffer, false);
result = SetupDiGetDeviceInterfaceDetail(hDevInfo, ref DeviceInterfaceData, detailDataBuffer, bufferSize, ref bufferSize, strtInterfaceData);
if (result == false)
{
//break;
}
//擷取裝置路徑訪
IntPtr pdevicePathName = (IntPtr)((int)detailDataBuffer + 4);
string devicePathName = Marshal.PtrToStringAuto(pdevicePathName);
HIDUSBAddress.Add(devicePathName);
//index++;
//break;
//連接配接裝置檔案
int aa = CT_CreateFile(devicePathName);
bool bb = USBDataRead(HidHandle);
//建立和裝置的連接配接
public unsafe int CT_CreateFile(string DeviceName)
HidHandle = CreateFile(
DeviceName,
GENERIC_READ,// | GENERIC_WRITE,//讀寫,或者一起
FILE_SHARE_READ,// | FILE_SHARE_WRITE,//共享讀寫,或者一起
0,
OPEN_EXISTING,
0);
if (HidHandle == -1)
return 0;
else
return 1;
//根據CreateFile拿到的裝置handle通路檔案,并傳回資料
public unsafe bool USBDataRead(int handle)
while (true)
uint read = 0;
//注意位元組的長度,我這裡寫的是8位,其實可以通過API擷取具體的長度,這樣安全點,
//具體方法我知道,但是沒有寫,過幾天整理完代碼,一起給出來
Byte[] m_rd_data = new Byte[8];
bool isread = ReadFile((IntPtr)handle, m_rd_data, (uint)8, ref read, IntPtr.Zero);
//這裡已經是拿到的資料了
Byte[] m_rd_dataout = new Byte[read];
Array.Copy(m_rd_data, m_rd_dataout, read);
OK,如果隻是擷取USB傳過來的資料,這裡已經足夠了,但是有點要注意,2000和XP如果要擷取HID鍵盤和滑鼠的資料,readfile是不行的,;
在Win2000和WinXP下不能用CreateFile+ReadFile/WriteFile的方式來讀寫标準滑鼠和标準鍵盤的資料,因為它們是系統獨占的(Exlusive)。
如果你是其他HID類裝置,比如遊戲搖桿或者自定義HID裝置,都可以用上面的方式來收發資料,
怎麼通路我暫時也不知道,估計要用它方法,看到有些軟體是用截取的手段,估計是用鈎子了吧。。
還有擷取封包長度的代碼,如果不确定封包長度,或者為了驅動适應變化,就用一下代碼來确定封包的長度
//擷取裝置具體資訊
[DllImport("hid.dll", SetLastError = true)]
private unsafe static extern int HidP_GetCaps(
int pPHIDP_PREPARSED_DATA, // IN PHIDP_PREPARSED_DATA PreparsedData,
ref HIDP_CAPS myPHIDP_CAPS); // OUT PHIDP_CAPS Capabilities
private unsafe static extern int HidD_GetPreparsedData(
int hObject, // IN HANDLE HidDeviceObject,
ref int pPHIDP_PREPARSED_DATA);
// HIDP_CAPS
[StructLayout(LayoutKind.Sequential)]
public unsafe struct HIDP_CAPS
{
public System.UInt16 Usage; // USHORT
public System.UInt16 UsagePage; // USHORT
public System.UInt16 InputReportByteLength;
public System.UInt16 OutputReportByteLength;
public System.UInt16 FeatureReportByteLength;
[MarshalAs(UnmanagedType.ByValArray, SizeConst = 17)]
public System.UInt16[] Reserved; // USHORT Reserved[17];
public System.UInt16 NumberLinkCollectionNodes;
public System.UInt16 NumberInputButtonCaps;
public System.UInt16 NumberInputValueCaps;
public System.UInt16 NumberInputDataIndices;
public System.UInt16 NumberOutputButtonCaps;
public System.UInt16 NumberOutputValueCaps;
public System.UInt16 NumberOutputDataIndices;
public System.UInt16 NumberFeatureButtonCaps;
public System.UInt16 NumberFeatureValueCaps;
public System.UInt16 NumberFeatureDataIndices;
}
int reportLength = 8;
//擷取裝置發送的位元組的長度(也有其他資訊)
int myPtrToPreparsedData = -1;
int result1 = HidD_GetPreparsedData(handle, ref myPtrToPreparsedData);
HIDP_CAPS myHIDP_CAPS = new HIDP_CAPS();
int result2 = HidP_GetCaps(myPtrToPreparsedData, ref myHIDP_CAPS);
reportLength = myHIDP_CAPS.InputReportByteLength;
再補充點,釋放裝置資源的時候需要用到
//釋放裝置的通路
internal static extern int CloseHandle(int hObject);
//釋放裝置
internal static extern IntPtr SetupDiDestroyDeviceInfoList(IntPtr DeviceInfoSet);
public void Dispost()
//釋放裝置資源(hDevInfo是SetupDiGetClassDevs擷取的)
SetupDiDestroyDeviceInfoList(hDevInfo);
//關閉連接配接(HidHandle是Create的時候擷取的)
CloseHandle(HidHandle);
ok
了.