c#使用PortableDeviceApiLib讀取便攜式設備(WPD:Windows Portable Devices)信息


相關名詞解釋:

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了一份,送給有緣人吧:

PortableDeviceApiLib讀取WPD設備信息

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM