相关名词解释:

WPD( Windows Portable Devices)

译作Windows 便携设备 (WPD) 是一种驱动程序技术,可支持广泛的可移动设备,比如移动电话、数码相机和便携媒体播放器。WPD 提供了标准化的基础结构,以实现应用程序和连接到正在运行 Windows 的 PC 上的便携设备之间的数据传输。WPD 还可为应用程序提供设备及其内容的统一视图以及标准化机制,从而获得访问数据的权限并对数据进行传输。

MTP(Media Transfer Protocol)模式

MTP模式是微软制订的一套媒体传输协议,由微软公司制定的在设备之间进行多媒体文件交换的通信协议,它实现的是把简单的文件复制变成一种协议性的传输方式。MTP既可以实现在USB协议上,也可以实现在TCP/IP协议上,它属于上层的应用协议,而不关心底层传输协议。目前大部分设备的应用都是基于USB协议。

PortableDeviceApiLib

这是微软提供的一个COM类库可以用于获取WPD设备的信息和进行MTP模式的文件传输

完整源码

  1. using System;
  2. using System.Collections.Generic;
  3. using System.ComponentModel;
  4. using System.Data;
  5. using System.Drawing;
  6. using System.Text;
  7. using System.Windows.Forms;
  8. using PortableDeviceApiLib;
  9. using System.IO;
  10. using System.Runtime.InteropServices;
  11. using System.Linq;
  12.  
  13. namespace WindowsFormsApplication1
  14. {
  15. public partial class Form1 : Form
  16. {
  17. PortableDeviceManagerClass devMgr = new PortableDeviceApiLib.PortableDeviceManagerClass();
  18. IPortableDeviceValues pValues = (IPortableDeviceValues)new PortableDeviceTypesLib.PortableDeviceValuesClass();
  19. PortableDeviceClass pPortableDevice = new PortableDeviceClass();
  20. PortableDeviceClass ppDevice = new PortableDeviceClass();
  21. string deviceID = string.Empty;
  22. public Form1()
  23. {
  24. InitializeComponent();
  25. this.Load += new EventHandler(Form1_Load);
  26. }
  27.  
  28. void Form1_Load(object sender, EventArgs e)
  29. {
  30. string[] deviceIds = EnumerateDevices();
  31. PortableDevice portableDevice;
  32. IPortableDeviceContent deviceContent;
  33. IPortableDeviceValues deviceValues = Connect(deviceIds[], out portableDevice, out deviceContent);
  34. string deviceName = GetDeviceName(deviceValues);
  35. DeviceType deviceType = GetDeviceType(deviceValues);
  36. string firmwareVersion = GetFirmwareVersion(deviceValues);
  37. string manufacturer = GetManufacturer(deviceValues);
  38. string model = GetModel(deviceValues);
  39. List<string> storagesIds = GetChildrenObjectIds(deviceContent, "DEVICE");
  40. StringBuilder storagesSb = new StringBuilder();
  41. //设备支持WIFI则包含网络这个假设备,也是无法获取到容量的
  42. foreach (string storageId in storagesIds.Where(s=>!s.Contains("网络")))
  43. {
  44. ulong freeSpace;
  45. ulong storageCapacity;
  46. GetStorageCapacityAnFreeSpace(deviceContent, storageId, out freeSpace, out storageCapacity);
  47. storagesSb.AppendFormat("可用容量为{0}GB,总容量为{1}GB",
  48. Math.Round((double)freeSpace / / / , ), Math.Round((double)storageCapacity / / / , ));
  49. }
  50. Disconnect(portableDevice);
  51. textBox1.AppendText(string.Format("当前设备数目:{0}个\r\n", deviceIds.Length));
  52. textBox1.AppendText(string.Format("连接的设备名称:{0}\r\n", deviceName));
  53. textBox1.AppendText(string.Format("连接的设备类型:{0}\r\n", deviceType.ToString()));
  54. textBox1.AppendText(string.Format("连接的设备固件版本:{0}\r\n", firmwareVersion));
  55. textBox1.AppendText(string.Format("连接的设备制造厂商:{0}\r\n", manufacturer));
  56. textBox1.AppendText(string.Format("连接的设备型号:{0}\r\n", model));
  57. textBox1.AppendText(storagesSb.ToString());
  58. }
  59.  
  60. /// <summary>
  61. /// 枚举所有便携式设备(MTP模式)
  62. /// </summary>
  63. /// <returns>返回设备id数组</returns>
  64. public string[] EnumerateDevices()
  65. {
  66. string[] devicesIds = null;
  67. PortableDeviceManagerClass deviceManager = new PortableDeviceManagerClass();
  68. uint deviceCount = ;//设备数目初始值必须大于0
  69. deviceManager.GetDevices(null, ref deviceCount);//获取设备数目必须置第一个参数为null
  70. if (deviceCount > )
  71. {
  72. devicesIds = new string[deviceCount];
  73. deviceManager.GetDevices(devicesIds, ref deviceCount);
  74. }
  75. return devicesIds;
  76. }
  77.  
  78. /// <summary>
  79. /// 连接设备
  80. /// </summary>
  81. /// <param name="DeviceId"></param>
  82. /// <param name="portableDevice"></param>
  83. /// <param name="deviceContent"></param>
  84. /// <returns></returns>
  85. public IPortableDeviceValues Connect(string DeviceId, out PortableDevice portableDevice, out IPortableDeviceContent deviceContent)
  86. {
  87. IPortableDeviceValues clientInfo = (IPortableDeviceValues)new PortableDeviceTypesLib.PortableDeviceValuesClass();
  88. portableDevice = new PortableDeviceClass();
  89. portableDevice.Open(DeviceId, clientInfo);
  90. portableDevice.Content(out deviceContent);
  91.  
  92. IPortableDeviceProperties deviceProperties;
  93. deviceContent.Properties(out deviceProperties);
  94.  
  95. IPortableDeviceValues deviceValues;
  96. deviceProperties.GetValues("DEVICE", null, out deviceValues);
  97. return deviceValues;
  98. }
  99. /// <summary>
  100. /// 断开设备
  101. /// </summary>
  102. /// <param name="portableDevice"></param>
  103. public void Disconnect(PortableDevice portableDevice)
  104. {
  105. portableDevice.Close();
  106. }
  107.  
  108. /// <summary>
  109. /// 设备类型
  110. /// </summary>
  111. public enum DeviceType
  112. {
  113. Generic = ,
  114. Camera = ,
  115. MediaPlayer = ,
  116. Phone = ,
  117. Video = ,
  118. PersonalInformationManager = ,
  119. AudioRecorder =
  120. };
  121. /// <summary>
  122. /// 获取设备类型
  123. /// </summary>
  124. /// <param name="DeviceValues"></param>
  125. /// <returns></returns>
  126. public DeviceType GetDeviceType(IPortableDeviceValues DeviceValues)
  127. {
  128. _tagpropertykey deviceTypeKey = new _tagpropertykey() { fmtid = new Guid("26d4979a-e643-4626-9e2b-736dc0c92fdc"), pid = };
  129. uint propertyValue;
  130. DeviceValues.GetUnsignedIntegerValue(ref deviceTypeKey, out propertyValue);
  131. DeviceType deviceType = (DeviceType)propertyValue;
  132. return deviceType;
  133. }
  134. /// <summary>
  135. /// 获取设备名
  136. /// </summary>
  137. /// <param name="DeviceValues"></param>
  138. /// <returns></returns>
  139. public string GetDeviceName(IPortableDeviceValues DeviceValues)
  140. {
  141. _tagpropertykey property = new _tagpropertykey() { fmtid = new Guid("ef6b490d-5cd8-437a-affc-da8b60ee4a3c"), pid = };
  142. string name;
  143. DeviceValues.GetStringValue(ref property, out name);
  144. return name;
  145. }
  146. /// <summary>
  147. /// 获取固件版本
  148. /// </summary>
  149. /// <param name="DeviceValues"></param>
  150. /// <returns></returns>
  151. public string GetFirmwareVersion(IPortableDeviceValues DeviceValues)
  152. {
  153. _tagpropertykey deviceTypeKey = new _tagpropertykey() { fmtid = new Guid("26d4979a-e643-4626-9e2b-736dc0c92fdc"), pid = };
  154. string firmwareVersion;
  155. DeviceValues.GetStringValue(ref deviceTypeKey, out firmwareVersion);
  156. return firmwareVersion;
  157. }
  158. /// <summary>
  159. /// 获取制造商
  160. /// </summary>
  161. /// <param name="DeviceValues"></param>
  162. /// <returns></returns>
  163. public string GetManufacturer(IPortableDeviceValues DeviceValues)
  164. {
  165. _tagpropertykey property = new _tagpropertykey() { fmtid = new Guid("26d4979a-e643-4626-9e2b-736dc0c92fdc"), pid = };
  166. string manufacturer;
  167. DeviceValues.GetStringValue(ref property, out manufacturer);
  168. return manufacturer;
  169. }
  170. /// <summary>
  171. /// 获取型号
  172. /// </summary>
  173. /// <param name="DeviceValues"></param>
  174. /// <returns></returns>
  175. public string GetModel(IPortableDeviceValues DeviceValues)
  176. {
  177. _tagpropertykey property = new _tagpropertykey()
  178. {
  179. fmtid = new Guid("26d4979a-e643-4626-9e2b-736dc0c92fdc"),
  180. pid =
  181. };
  182. string model;
  183. DeviceValues.GetStringValue(ref property, out model);
  184. return model;
  185. }
  186. /// <summary>
  187. /// 获取设备或设备下文件夹的所有对象(文件、文件夹)的ObjectId
  188. /// </summary>
  189. /// <param name="deviceId"></param>
  190. /// <param name="parentId"></param>
  191. /// <returns></returns>
  192. public List<string> GetChildrenObjectIds(IPortableDeviceContent content, string parentId)
  193. {
  194. IEnumPortableDeviceObjectIDs objectIds;
  195. content.EnumObjects(, parentId, null, out objectIds);
  196. List<string> childItems = new List<string>();
  197. uint fetched = ;
  198. do
  199. {
  200. string objectId;
  201. objectIds.Next(, out objectId, ref fetched);
  202. if (fetched > )
  203. {
  204. childItems.Add(objectId);
  205. }
  206. }
  207. while (fetched > );
  208. return childItems;
  209. }
  210. /// <summary>
  211. /// 获取总容量和可用容量
  212. /// </summary>
  213. /// <param name="deviceContent"></param>
  214. /// <param name="storageId"></param>
  215. /// <param name="freeSpace"></param>
  216. /// <param name="storageCapacity"></param>
  217. public void GetStorageCapacityAnFreeSpace(IPortableDeviceContent deviceContent, string storageId, out ulong freeSpace, out ulong storageCapacity)
  218. {
  219. IPortableDeviceProperties deviceProperties;
  220. deviceContent.Properties(out deviceProperties);
  221.  
  222. IPortableDeviceKeyCollection keyCollection = (IPortableDeviceKeyCollection)new PortableDeviceTypesLib.PortableDeviceKeyCollectionClass();
  223. _tagpropertykey freeSpaceKey = new _tagpropertykey();
  224. freeSpaceKey.fmtid = new Guid("01a3057a-74d6-4e80-bea7-dc4c212ce50a");
  225. freeSpaceKey.pid = ;
  226.  
  227. _tagpropertykey storageCapacityKey = new _tagpropertykey();
  228. storageCapacityKey.fmtid = new Guid("01a3057a-74d6-4e80-bea7-dc4c212ce50a");
  229. storageCapacityKey.pid = ;
  230.  
  231. keyCollection.Add(ref freeSpaceKey);
  232. keyCollection.Add(ref storageCapacityKey);
  233.  
  234. IPortableDeviceValues deviceValues;
  235. deviceProperties.GetValues(storageId, keyCollection, out deviceValues);
  236.  
  237. deviceValues.GetUnsignedLargeIntegerValue(ref freeSpaceKey, out freeSpace);
  238. deviceValues.GetUnsignedLargeIntegerValue(ref storageCapacityKey, out storageCapacity);
  239. }
  240. }
  241. }

运行截图

一点感想

最近在重构一个PDA程序就是WinCE的。是的老掉牙的设备(系统),工控行业有些地方还在用。早几年前就转了安卓了,这次重构这么个项目其实还是挺用心的。分层开发,用了ORM,还把PDA程序的功能做成了可配置,有时间会另外写文分享。在收集资料的时候发现网上基本上是没有可以使用的源码,现在DIY了一份,送给有缘人吧:

PortableDeviceApiLib读取WPD设备信息

c#使用PortableDeviceApiLib读取便携式设备(WPD:Windows Portable Devices)信息的更多相关文章

  1. 虚拟机下Linux读取USB设备的问题虚拟机下Linux无法读取USB设备的解决方案

    我们在虚拟机中识别USB设备有三种情况导致Linux系统不能读取到USB设备: 1. .当虚拟机的USB服务没有开启的时候 2. 若虚拟机的USB连接的设置选项没有设置好 3. Widows抢先一步, ...

  2. 读取Android设备的MAC地址

    读取Android设备的MAC地址   AndroidUtil.java package com.csdn.android.util; import com.csdn.android.framewor ...

  3. Windows 10 版本信息

    原文 https://technet.microsoft.com/zh-cn/windows/release-info Windows 10 版本信息 Microsoft 已更新其服务模型. 半年频道 ...

  4. 浅谈.NET(C#)与Windows用户账户信息的获取

    原文:浅谈.NET(C#)与Windows用户账户信息的获取 目录 1. 用户账户名称 - 使用Environment类 2. 用户账户信息 - 使用WindowsIdentity和IdentityR ...

  5. 。 (有些情况下通过 lsof(8) 或 fuser(1) 可以 找到有关使用该设备的进程的有用信息)

    umount时目标忙解决办法 标签(空格分隔): ceph ceph运维 osd 在删除osd后umount时,始终无法umonut,可以通过fuser查看设备被哪个进程占用,之后杀死进程,就可以顺利 ...

  6. USB系列之二:读取USB设备的描述符

    在前面的文章中,我们已经给出了USB协议的链接地址,从这篇文章起,我们会涉及到许多USB 1.1的内容,我们的指导思想是先从熟悉USB 1.1协议入手,先使用现成的HCD和USBD,直接面对客户端驱动 ...

  7. 使用恶意USB设备解锁 Windows & Mac 锁屏状态

    NSA专业物理入侵设备——USB Armory,可解锁任意锁屏状态的下的Windows和Mac操作系统,含最新发布的Windows10.及较早的Mac OSX El Capitan / Maveric ...

  8. 读取注册表获取Windows系统XP/7/8/10类型(使用wcscmp比较wchar[]内容)

    很多方案是采用GetVersion.GetVersionEx这两个API来查询操作系统的版本号来判断当前的操作系统是Windows系列中的哪个,在Win10没有出现前,这种方法是行的通的,但是Win1 ...

  9. 开源的excel读取库libxls在windows下的编译,且支持中文,全网首发

    转载请注明出处:http://www.cnblogs.com/superbi/p/5482516.html 到目前为止,网络和官网上并没有关于libxls在windows下支持中文的教程,也没有现成的 ...

随机推荐

  1. web前端开发初学者必看的学习路线(附思维导图)

    很多同学想学习WEB前端开发,虽然互联网有很多的教程.网站.书籍,可是却又不知从何开始如何选取.看完网友高等游民白乌鸦无私分享的原标题为<写给同事的前端学习路线>这篇文章,相信你会有所收获 ...

  2. .Net Web开发技术栈

    有很多朋友有的因为兴趣,有的因为生计而走向了.Net中,有很多朋友想学,但是又不知道怎么学,学什么,怎么系统的学,为此我以我微薄之力总结归纳写了一篇.Net web开发技术栈,以此帮助那些想学,却不知 ...

  3. 【UML 建模】活动图介绍

    1.活动图,即Activity Diagram,是UML中用于对系统的动态行为建模的一种常用工具,它描述活动的顺序,展现从一种活动到另一种活动的控制流.其本质上是一种流程图,着重表现从一个活动到另一个 ...

  4. MySQL索引(2)

    一.索引基础 1. B-Tree索引 <1> 所有的值都是按顺序存储的,并且每一个叶子页到根的距离相同. <2> 顺序组织存储,很适合查找范围数据,效率会非常高. <3& ...

  5. PHP异常处理机制

    1. 异常: 异常(Exception)用于在指定的错误发生时改变脚本的正常流程. 当异常被触发时,通常会发生: (1)当前代码状态被保存: (2)代码执行被切换到预定义的异常处理器函数: (3)根据 ...

  6. LeetCode 1. Two Sum (两数之和)

    Given an array of integers, return indices of the two numbers such that they add up to a specific ta ...

  7. CNCC2017梳理

    大牛云集的中国计算机大会:大会日程表:http://cncc.ccf.org.cn/cn/news/schedule_empty 早上的论坛可以在爱奇艺下载视频 下午的分论坛是多个同时进行的,我也只去 ...

  8. 前后端分离跨服务器文件上传-Java SpringMVC版

    近来工作上不上特别忙,加上对后台java了解一点,所以就抽时间,写了一个java版本的前后端分离的跨服务器文件上传功能,包括前后端代码. 一.Tomcat服务器部分 1.Tomcat服务器 单独复制一 ...

  9. js中判断鼠标滚轮方向的方法

      前  言 LiuDaP 最近无聊,在做自己的个人站,其中用到了一个关于鼠标滚轮方向判断的方法,今天闲来无聊,就给大家介绍一下吧!!!! 在介绍鼠标事件案例前,让我们先稍微了解一下js中的event ...

  10. poj 2345 Central heating

    Central heating Time Limit: 1000MS   Memory Limit: 65536K Total Submissions: 678   Accepted: 310 Des ...