惯性聚合 高效追踪和阅读你感兴趣的博客、新闻、科技资讯
阅读原文 在惯性聚合中打开

推荐订阅源

P
Privacy & Cybersecurity Law Blog
Vercel News
Vercel News
Cyber Security Advisories - MS-ISAC
Cyber Security Advisories - MS-ISAC
N
Netflix TechBlog - Medium
罗磊的独立博客
F
Fortinet All Blogs
T
Threatpost
Y
Y Combinator Blog
博客园_首页
美团技术团队
Security Latest
Security Latest
博客园 - 三生石上(FineUI控件)
T
Tailwind CSS Blog
V
V2EX - 技术
The Cloudflare Blog
L
LINUX DO - 热门话题
博客园 - 司徒正美
Jina AI
Jina AI
P
Proofpoint News Feed
宝玉的分享
宝玉的分享
C
CXSECURITY Database RSS Feed - CXSecurity.com
C
Cybersecurity and Infrastructure Security Agency CISA
钛媒体:引领未来商业与生活新知
钛媒体:引领未来商业与生活新知
WordPress大学
WordPress大学
The Hacker News
The Hacker News
P
Privacy International News Feed
T
The Exploit Database - CXSecurity.com
Scott Helme
Scott Helme
有赞技术团队
有赞技术团队
V
V2EX
Stack Overflow Blog
Stack Overflow Blog
M
MIT News - Artificial intelligence
Latest news
Latest news
NISL@THU
NISL@THU
Google DeepMind News
Google DeepMind News
cs.CL updates on arXiv.org
cs.CL updates on arXiv.org
C
Cisco Blogs
雷峰网
雷峰网
Application and Cybersecurity Blog
Application and Cybersecurity Blog
B
Blog RSS Feed
W
WeLiveSecurity
D
DataBreaches.Net
G
Google Developers Blog
奇客Solidot–传递最新科技情报
奇客Solidot–传递最新科技情报
G
GRAHAM CLULEY
Spread Privacy
Spread Privacy
Know Your Adversary
Know Your Adversary
TaoSecurity Blog
TaoSecurity Blog
S
Securelist
Help Net Security
Help Net Security

博客园 - 昨夜飘风

WPF 通过共享内存播放视频 C# 模拟网页拖拽 .net4.0中wpf单例启动 wpf 自定义ContextMenu样式,可以调节ContextMenu的宽度 Oracle 开发经验 WPF跑马灯效果 android私有文件夹的访问 [转]C#内存操作 C#串口发送接受数据 C# 制作外挂常用的API silverlight 动画 性能优化 SilverLight 动画缓冲(Animation Easing) - 昨夜飘风 体面地处理程序的未捕获异常 收藏一个地址(居然说我标题已经存在) 收藏一个地址 (2009-06-24) SqlCommandBuilder使用的注意事项 助睡眠音乐 (2009-06-22) 班德瑞官方试听网站 - 昨夜飘风 (2009-06-18)今日收获 工厂方法 (2009-06-17)今日收获-只读列隐藏-win2003 dll文件下载
C# 访问USB(HID)设备
昨夜飘风 · 2009-09-08 · via 博客园 - 昨夜飘风

二话不说,直接给代码,如果您真想做这方面的东西,还是稍微研究下,没有现成的好类用,就需要自己了解其原理

        //以下是调用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
            );
//释放设备
        [DllImport("hid.dll")]
        
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, 0ref 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,
                
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)8ref 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设备,都可以用上面的方式来收发数据,
怎么访问我暂时也不知道,估计要用它方法,看到有些软件是用截取的手段,估计是用钩子了吧。。

最后忘记引用空间了,其实大家都知道的
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;