看过很多blog,也各种搜集链接,但是想好好的整理一下自己的开发历程,就打算开博写东西,空了把以前的项目问题搬上来。
2015.11.04 这是一个值得纪念的日子。
问题描述:
目前正在着手弄一个android 平板用数据线连接的问题,怎么实现连接先搁置一下,谈一下这两天想破头的问题。
正式由于平板的插拔问题,为了反正意外的掉线问题,必须时刻保持对设备与主机连接状态的检测,所以我希望通过pc端定时获取当前连接的便携设备。
历程: 最开始的时候,我不知道当前用的平板是便携设备,以为通过简单的usb 插拔消息句柄可以控制,然后获取C#中用 driverInfo 封装好的设备信息。
后来在各种更改driverType后仍然检测不到已经插好的android 平板,遂通过设备管理器查看才知道其显示为便携设备,并不具备盘符,无法通过driverInfo获取。
然后又在各种百度下,才知道便携设备的检测需要用到 Windows PortableDeviceApi. 既然有api是肯定好的,但是问题总是一堆一堆的。
首先网上相关的资料不算太多,同时微软msdn文档中用的是C++的方法,并不满足我的需求。后来才找到几个链接接近我的想法。http://blog.csdn.net/yu0zhuo/article/details/5728605/、、、、、、、http://blogs.msdn.com/b/dimeby8/archive/2006/12/05/enumerating-wpd-devices-in-c.aspx
本来想直接使用第一个链接中的代码,无奈编译出错,主要问题出在 devMgr.GetDevices(strPnPDeviceIDs, ref cDevices)这个方法中,官方api第一个参数类型为 string,
而代码中为string[],显然这是不匹配的,但是又不知道怎么解决,遂科普到第二个链接,由于英文水平不太好的问题,折腾半天才看到
Mike R. brought to my notice that the above sample only enumerates one device even if more than one are connected. This is a marshalling restriction - we can work around it by manually fixing up the generated Interop assembly. Follow the steps below to edit the assembly:
- Disassemble the PortableDeviceApi interop using the command -
ildasm Interop.PortableDeviceApiLib.dll /out:pdapi.il - Open the IL in Notepad and search for the following string
instance void GetDevices([in][out] string& marshal( lpwstr) pPnPDeviceIDs, - Replace all instances of the string above with the following string
instance void GetDevices([in][out] string[] marshal([]) pPnPDeviceIDs, - Save the IL and reassemble the interop using the command -
ilasm pdapi.il /dll /output=Interop.PortableDeviceApiLib.dll
You can now rebuild your project. You can now first call GetDevices with a NULL parameter to get the count of devices and then call it again with an array to get the device IDs.
这是在告诉我们,使用官方原定的api有局限性,不支持 string[] 那个类型的参数,需要我们手工改动PortableDeviceApiLib的dll文件,修改其中的方法 GetDevices([in][out] string[] marshal([]) pPnPDeviceIDs)
关键之处:先把原来的PortableDeviceApiLib.dll用(ILDASM)反编译,得到PortableDeviceApiLib.il ,然后修改文中的代码:
修改方式为 将文件中的instance void GetDevices([in][out] string& marshal( lpwstr) pPnPDeviceIDs 替换为
instance void GetDevices([in][out] string[] marshal([]) pPnPDeviceIDs,
然后回到程序界面,编译问题消失,貌似得以解决。
再然后,问题又来了,当调试程序时,爆出了另一个错误 Marshaler restriction: Excessively long string.
这个问题使得程序执行到getDevice时终止。又各种查阅,才知道参数依旧不匹配,继续修改参数
修改方式为:将文件中的instance void GetDevices([in][out] string& marshal( lpwstr) pPnPDeviceIDs
替换为 instance void GetDevices([in][out] string[] marshal(lpwstr) pPnPDeviceIDs,
目前的问题初步得到解决。