相關名詞解釋:
WPD( Windows Portable Devices)
譯作Windows 便攜設備 (WPD) 是一種驅動程序技術,可支持廣泛的可移動設備,比如移動電話、數碼相機和便攜媒體播放器。WPD 提供了標准化的基礎結構,以實現應用程序和連接到正在運行 Windows 的 PC 上的便攜設備之間的數據傳輸。WPD 還可為應用程序提供設備及其內容的統一視圖以及標准化機制,從而獲得訪問數據的權限並對數據進行傳輸。
MTP(Media Transfer Protocol)模式
MTP模式是微軟制訂的一套媒體傳輸協議,由微軟公司制定的在設備之間進行多媒體文件交換的通信協議,它實現的是把簡單的文件復制變成一種協議性的傳輸方式。MTP既可以實現在USB協議上,也可以實現在TCP/IP協議上,它屬於上層的應用協議,而不關心底層傳輸協議。目前大部分設備的應用都是基於USB協議。
PortableDeviceApiLib
這是微軟提供的一個COM類庫可以用於獲取WPD設備的信息和進行MTP模式的文件傳輸
完整源碼
using System; using System.Collections.Generic; using System.ComponentModel; using System.Data; using System.Drawing; using System.Text; using System.Windows.Forms; using PortableDeviceApiLib; using System.IO; using System.Runtime.InteropServices; using System.Linq; namespace WindowsFormsApplication1 { public partial class Form1 : Form { PortableDeviceManagerClass devMgr = new PortableDeviceApiLib.PortableDeviceManagerClass(); IPortableDeviceValues pValues = (IPortableDeviceValues)new PortableDeviceTypesLib.PortableDeviceValuesClass(); PortableDeviceClass pPortableDevice = new PortableDeviceClass(); PortableDeviceClass ppDevice = new PortableDeviceClass(); string deviceID = string.Empty; public Form1() { InitializeComponent(); this.Load += new EventHandler(Form1_Load); } void Form1_Load(object sender, EventArgs e) { string[] deviceIds = EnumerateDevices(); PortableDevice portableDevice; IPortableDeviceContent deviceContent; IPortableDeviceValues deviceValues = Connect(deviceIds[0], out portableDevice, out deviceContent); string deviceName = GetDeviceName(deviceValues); DeviceType deviceType = GetDeviceType(deviceValues); string firmwareVersion = GetFirmwareVersion(deviceValues); string manufacturer = GetManufacturer(deviceValues); string model = GetModel(deviceValues); List<string> storagesIds = GetChildrenObjectIds(deviceContent, "DEVICE"); StringBuilder storagesSb = new StringBuilder(); //設備支持WIFI則包含網絡這個假設備,也是無法獲取到容量的 foreach (string storageId in storagesIds.Where(s=>!s.Contains("網絡"))) { ulong freeSpace; ulong storageCapacity; GetStorageCapacityAnFreeSpace(deviceContent, storageId, out freeSpace, out storageCapacity); storagesSb.AppendFormat("可用容量為{0}GB,總容量為{1}GB", Math.Round((double)freeSpace / 1024 / 1024 / 1024, 3), Math.Round((double)storageCapacity / 1024 / 1024 / 1024, 3)); } Disconnect(portableDevice); textBox1.AppendText(string.Format("當前設備數目:{0}個\r\n", deviceIds.Length)); textBox1.AppendText(string.Format("連接的設備名稱:{0}\r\n", deviceName)); textBox1.AppendText(string.Format("連接的設備類型:{0}\r\n", deviceType.ToString())); textBox1.AppendText(string.Format("連接的設備固件版本:{0}\r\n", firmwareVersion)); textBox1.AppendText(string.Format("連接的設備制造廠商:{0}\r\n", manufacturer)); textBox1.AppendText(string.Format("連接的設備型號:{0}\r\n", model)); textBox1.AppendText(storagesSb.ToString()); } /// <summary> /// 枚舉所有便攜式設備(MTP模式) /// </summary> /// <returns>返回設備id數組</returns> public string[] EnumerateDevices() { string[] devicesIds = null; PortableDeviceManagerClass deviceManager = new PortableDeviceManagerClass(); uint deviceCount = 1;//設備數目初始值必須大於0 deviceManager.GetDevices(null, ref deviceCount);//獲取設備數目必須置第一個參數為null if (deviceCount > 0) { devicesIds = new string[deviceCount]; deviceManager.GetDevices(devicesIds, ref deviceCount); } return devicesIds; } /// <summary> /// 連接設備 /// </summary> /// <param name="DeviceId"></param> /// <param name="portableDevice"></param> /// <param name="deviceContent"></param> /// <returns></returns> public IPortableDeviceValues Connect(string DeviceId, out PortableDevice portableDevice, out IPortableDeviceContent deviceContent) { IPortableDeviceValues clientInfo = (IPortableDeviceValues)new PortableDeviceTypesLib.PortableDeviceValuesClass(); portableDevice = new PortableDeviceClass(); portableDevice.Open(DeviceId, clientInfo); portableDevice.Content(out deviceContent); IPortableDeviceProperties deviceProperties; deviceContent.Properties(out deviceProperties); IPortableDeviceValues deviceValues; deviceProperties.GetValues("DEVICE", null, out deviceValues); return deviceValues; } /// <summary> /// 斷開設備 /// </summary> /// <param name="portableDevice"></param> public void Disconnect(PortableDevice portableDevice) { portableDevice.Close(); } /// <summary> /// 設備類型 /// </summary> public enum DeviceType { Generic = 0, Camera = 1, MediaPlayer = 2, Phone = 3, Video = 4, PersonalInformationManager = 5, AudioRecorder = 6 }; /// <summary> /// 獲取設備類型 /// </summary> /// <param name="DeviceValues"></param> /// <returns></returns> public DeviceType GetDeviceType(IPortableDeviceValues DeviceValues) { _tagpropertykey deviceTypeKey = new _tagpropertykey() { fmtid = new Guid("26d4979a-e643-4626-9e2b-736dc0c92fdc"), pid = 15 }; uint propertyValue; DeviceValues.GetUnsignedIntegerValue(ref deviceTypeKey, out propertyValue); DeviceType deviceType = (DeviceType)propertyValue; return deviceType; } /// <summary> /// 獲取設備名 /// </summary> /// <param name="DeviceValues"></param> /// <returns></returns> public string GetDeviceName(IPortableDeviceValues DeviceValues) { _tagpropertykey property = new _tagpropertykey() { fmtid = new Guid("ef6b490d-5cd8-437a-affc-da8b60ee4a3c"), pid = 4 }; string name; DeviceValues.GetStringValue(ref property, out name); return name; } /// <summary> /// 獲取固件版本 /// </summary> /// <param name="DeviceValues"></param> /// <returns></returns> public string GetFirmwareVersion(IPortableDeviceValues DeviceValues) { _tagpropertykey deviceTypeKey = new _tagpropertykey() { fmtid = new Guid("26d4979a-e643-4626-9e2b-736dc0c92fdc"), pid = 3 }; string firmwareVersion; DeviceValues.GetStringValue(ref deviceTypeKey, out firmwareVersion); return firmwareVersion; } /// <summary> /// 獲取制造商 /// </summary> /// <param name="DeviceValues"></param> /// <returns></returns> public string GetManufacturer(IPortableDeviceValues DeviceValues) { _tagpropertykey property = new _tagpropertykey() { fmtid = new Guid("26d4979a-e643-4626-9e2b-736dc0c92fdc"), pid = 7 }; string manufacturer; DeviceValues.GetStringValue(ref property, out manufacturer); return manufacturer; } /// <summary> /// 獲取型號 /// </summary> /// <param name="DeviceValues"></param> /// <returns></returns> public string GetModel(IPortableDeviceValues DeviceValues) { _tagpropertykey property = new _tagpropertykey() { fmtid = new Guid("26d4979a-e643-4626-9e2b-736dc0c92fdc"), pid = 8 }; string model; DeviceValues.GetStringValue(ref property, out model); return model; } /// <summary> /// 獲取設備或設備下文件夾的所有對象(文件、文件夾)的ObjectId /// </summary> /// <param name="deviceId"></param> /// <param name="parentId"></param> /// <returns></returns> public List<string> GetChildrenObjectIds(IPortableDeviceContent content, string parentId) { IEnumPortableDeviceObjectIDs objectIds; content.EnumObjects(0, parentId, null, out objectIds); List<string> childItems = new List<string>(); uint fetched = 0; do { string objectId; objectIds.Next(1, out objectId, ref fetched); if (fetched > 0) { childItems.Add(objectId); } } while (fetched > 0); return childItems; } /// <summary> /// 獲取總容量和可用容量 /// </summary> /// <param name="deviceContent"></param> /// <param name="storageId"></param> /// <param name="freeSpace"></param> /// <param name="storageCapacity"></param> public void GetStorageCapacityAnFreeSpace(IPortableDeviceContent deviceContent, string storageId, out ulong freeSpace, out ulong storageCapacity) { IPortableDeviceProperties deviceProperties; deviceContent.Properties(out deviceProperties); IPortableDeviceKeyCollection keyCollection = (IPortableDeviceKeyCollection)new PortableDeviceTypesLib.PortableDeviceKeyCollectionClass(); _tagpropertykey freeSpaceKey = new _tagpropertykey(); freeSpaceKey.fmtid = new Guid("01a3057a-74d6-4e80-bea7-dc4c212ce50a"); freeSpaceKey.pid = 5; _tagpropertykey storageCapacityKey = new _tagpropertykey(); storageCapacityKey.fmtid = new Guid("01a3057a-74d6-4e80-bea7-dc4c212ce50a"); storageCapacityKey.pid = 4; keyCollection.Add(ref freeSpaceKey); keyCollection.Add(ref storageCapacityKey); IPortableDeviceValues deviceValues; deviceProperties.GetValues(storageId, keyCollection, out deviceValues); deviceValues.GetUnsignedLargeIntegerValue(ref freeSpaceKey, out freeSpace); deviceValues.GetUnsignedLargeIntegerValue(ref storageCapacityKey, out storageCapacity); } } }
運行截圖
一點感想
最近在重構一個PDA程序就是WinCE的。是的老掉牙的設備(系統),工控行業有些地方還在用。早幾年前就轉了安卓了,這次重構這么個項目其實還是挺用心的。分層開發,用了ORM,還把PDA程序的功能做成了可配置,有時間會另外寫文分享。在收集資料的時候發現網上基本上是沒有可以使用的源碼,現在DIY了一份,送給有緣人吧: