c#使用wpd读取便携式设备信息二

版权声明:本文为转载文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。

在上节内容(c#使用wpd读取便携式设备信息一)中,我们已经获取到了设备名称,容量等信息,本节进行读写设备的存储内容操作。WPD对设备的操作都是基于对象的ID的,例如文件夹和文件都有各自的objectId,首先获取到要进行操作的对象的objectId,然后再进行读写。

这里以我的小米note手机为例,要对Android目录下的文件进行读取


需要用到的方法如下:


/// <summary>
        /// 获取设备ID
        /// </summary>
        /// <returns></returns>
        public string GetDeviceId()
        {
            uint devicesCount = 1;
            PortableDeviceManagerClass devMgr = new PortableDeviceManagerClass();
            string deviceID = string.Empty;
            //此处devicesCount为大于0的数,且只能获取一个便携式设备,如何获取多个设备会在之后的文章展现
            devMgr.GetDevices(ref deviceID, ref devicesCount);
            return deviceID;
        }


        /// <summary>
        /// 获取设备信息
        /// </summary>
        /// <param name="deviceId"></param>
        /// <returns></returns>
        public IPortableDeviceContent GetDeviceContent(string deviceId)
        {
            IPortableDeviceValues clientInfo = (IPortableDeviceValues)new PortableDeviceTypesLib.PortableDeviceValuesClass();
            PortableDeviceClass portableDevice = new PortableDeviceClass();
            portableDevice.Open(deviceId, clientInfo);


            IPortableDeviceContent content;
            portableDevice.Content(out content);
            return content;
        }

        /// <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);


                // Check if anything was retrieved.


                if (fetched > 0)
                {
                    childItems.Add(objectId);
                }
            } while (fetched > 0);
            return childItems;
        }

        /// <summary>
        /// 获取名称属性
        /// </summary>
        /// <param name="deviceValues"></param>
        /// <returns></returns>
        public string GetNameProperty(IPortableDeviceValues deviceValues)
        {
            _tagpropertykey nameKey = new _tagpropertykey();
            nameKey.fmtid= new Guid("EF6B490D-5CD8-437A-AFFC-DA8B60EE4A3C");//guid唯一值
            nameKey.pid = 4;//索引


            string nameProperty = null;
            deviceValues.GetStringValue(ref nameKey, out nameProperty);
            return nameProperty;
        }

要将数据写入到设备中,首先需要创建符合要求的文件或文件夹

/// <summary>
        /// 创建符合要求的文件
        /// </summary>
        /// <param name="sourcePath"></param>
        /// <param name="parentId"></param>
        /// <returns></returns>
        private static IPortableDeviceValues GetRequiredPropertiesForContentType(string sourcePath,string parentId)
        {
            IPortableDeviceValues values = new PortableDeviceTypesLib.PortableDeviceValues() as IPortableDeviceValues;


            _tagpropertykey WPD_OBJECT_PARENT_ID = new _tagpropertykey();
            WPD_OBJECT_PARENT_ID.fmtid = new Guid(0xEF6B490D, 0x5CD8, 0x437A, 0xAF, 0xFC, 0xDA, 0x8B, 0x60, 0xEE, 0x4A, 0x3C);
            WPD_OBJECT_PARENT_ID.pid = 3;
            values.SetStringValue(ref WPD_OBJECT_PARENT_ID, parentId);


            _tagpropertykey WPD_OBJECT_SIZE = new _tagpropertykey();
            WPD_OBJECT_SIZE.fmtid = new Guid(0xEF6B490D, 0x5CD8, 0x437A, 0xAF, 0xFC, 0xDA, 0x8B, 0x60, 0xEE, 0x4A, 0x3C);
            WPD_OBJECT_SIZE.pid = 11;


            FileInfo fileInfo = new FileInfo(sourcePath);
            values.SetUnsignedLargeIntegerValue(WPD_OBJECT_SIZE, (ulong)fileInfo.Length);


            _tagpropertykey WPD_OBJECT_ORIGINAL_FILE_NAME = new _tagpropertykey();
            WPD_OBJECT_ORIGINAL_FILE_NAME.fmtid = new Guid(0xEF6B490D, 0x5CD8, 0x437A, 0xAF, 0xFC, 0xDA, 0x8B, 0x60, 0xEE, 0x4A, 0x3C);
            WPD_OBJECT_ORIGINAL_FILE_NAME.pid = 12;
            values.SetStringValue(WPD_OBJECT_ORIGINAL_FILE_NAME, Path.GetFileName(sourcePath));


            _tagpropertykey WPD_OBJECT_NAME = new _tagpropertykey();
            WPD_OBJECT_NAME.fmtid = new Guid(0xEF6B490D, 0x5CD8, 0x437A, 0xAF, 0xFC, 0xDA, 0x8B, 0x60, 0xEE, 0x4A, 0x3C);
            WPD_OBJECT_NAME.pid = 4;
            values.SetStringValue(WPD_OBJECT_NAME, Path.GetFileName(sourcePath));


            return values;
        }


        /// <summary>
        /// 创建符合要求的文件夹
        /// </summary>
        /// <param name="parentId"></param>
        /// <param name="folderName"></param>
        /// <returns></returns>
        private IPortableDeviceValues GetRequiredPropertiesForFolder(string parentId, string folderName)
        {
            IPortableDeviceValues values = new PortableDeviceTypesLib.PortableDeviceValues() as IPortableDeviceValues;


            _tagpropertykey WPD_OBJECT_PARENT_ID = new _tagpropertykey();
            WPD_OBJECT_PARENT_ID.fmtid = new Guid(0xEF6B490D, 0x5CD8, 0x437A, 0xAF, 0xFC, 0xDA, 0x8B, 0x60, 0xEE, 0x4A, 0x3C);
            WPD_OBJECT_PARENT_ID.pid = 3;
            values.SetStringValue(ref WPD_OBJECT_PARENT_ID, parentId);


            _tagpropertykey WPD_OBJECT_NAME = new _tagpropertykey();
            WPD_OBJECT_NAME.fmtid = new Guid(0xEF6B490D, 0x5CD8, 0x437A, 0xAF, 0xFC, 0xDA, 0x8B, 0x60, 0xEE, 0x4A, 0x3C);
            WPD_OBJECT_NAME.pid = 4;
            values.SetStringValue(WPD_OBJECT_NAME, folderName);


            _tagpropertykey WPD_OBJECT_ORIGINAL_FILE_NAME = new _tagpropertykey();
            WPD_OBJECT_ORIGINAL_FILE_NAME.fmtid = new Guid(0xEF6B490D, 0x5CD8, 0x437A, 0xAF, 0xFC, 0xDA, 0x8B, 0x60, 0xEE, 0x4A, 0x3C);
            WPD_OBJECT_ORIGINAL_FILE_NAME.pid = 12;
            values.SetStringValue(WPD_OBJECT_ORIGINAL_FILE_NAME, folderName);


            _tagpropertykey WPD_OBJECT_CONTENT_TYPE = new _tagpropertykey();
            WPD_OBJECT_CONTENT_TYPE.fmtid = new Guid(0xEF6B490D, 0x5CD8, 0x437A, 0xAF, 0xFC, 0xDA, 0x8B, 0x60, 0xEE, 0x4A, 0x3C);
            WPD_OBJECT_CONTENT_TYPE.pid = 12;
            values.SetStringValue(WPD_OBJECT_ORIGINAL_FILE_NAME, folderName);


            return values;
        }

创建完毕后,进行数据的写入

最后写入数据

/// <summary>
        /// 写入数据
        /// </summary>
        /// <param name="sourceFile"></param>
        /// <param name="portableDevice"></param>
        /// <param name="parentId"></param>
        public void TransferContentToDevice(string sourceFile, PortableDeviceClass portableDevice,string parentId)
        {
            IPortableDeviceContent content;
            portableDevice.Content(out content);


            IPortableDeviceValues values = GetRequiredPropertiesForContentType(sourceFile, parentId);


            IStream tempStream;
            uint optimalTransferSizeBytes = 0;
            content.CreateObjectWithPropertiesAndData(values, out tempStream, ref optimalTransferSizeBytes, null);


            System.Runtime.InteropServices.ComTypes.IStream targetStream = (System.Runtime.InteropServices.ComTypes.IStream)tempStream;


            try
            {
                using (FileStream sourceStream = new FileStream(sourceFile, FileMode.Open, FileAccess.Read))
                {
                    int bytesRead = 0;
                    do
                    {
                        int count = 1024 * 1024;
                        byte[] buffer = new byte[count];
                        bytesRead = sourceStream.Read(buffer, 0, count);


                        IntPtr pcbWritten = IntPtr.Zero;
                        targetStream.Write(buffer, bytesRead, pcbWritten);
                    }
                    while (bytesRead > 0);
                }
                targetStream.Commit(0);
            }
            finally
            {
                Marshal.ReleaseComObject(tempStream);
            }
        }


整理上述方法,调用顺序如下

 private void button2_Click(object sender, EventArgs e)
        {
            string deviceId = GetDeviceId();
            IPortableDeviceContent content = GetDeviceContent(deviceId);


            IPortableDeviceProperties properties;
            content.Properties(out properties);


            IPortableDeviceValues deviceValues;
            properties.GetValues("DEVICE", null, out deviceValues);
            
            List<string> storagesId = GetChildrenObjectIds(content, "DEVICE");//这里小米note手机由于没有外置sd卡,所以storagesId只有一个,即为内置存储
            foreach (string storageId in storagesId)
            {
                List<string> objectsId = GetChildrenObjectIds(content, storageId);
                string androidId = null;
                foreach (string objectId in objectsId)
                {
                    IPortableDeviceValues objectValues;
                    properties.GetValues(objectId, null, out objectValues);
                    string objectName = GetNameProperty(objectValues);
                    if (objectName == "Android")
                    {
                        androidId = objectId;
                        break;
                    }
                }
                TransferContentToDevice(@"C:\Users\Administrator\Desktop\tmp.png", content, androidId);
            }
        }

最后结果


最后再奉上拷贝设备上的数据到PC的代码

 public void TransferContentFromDevice(string destPath,IPortableDeviceContent deviceContent,string objectId)
        {
            // TODO: Clean this up.


            IPortableDeviceResources resources;
            deviceContent.Transfer(out resources);


            IStream wpdStream = null;
            uint optimalTransferSize = 0;


            _tagpropertykey property = new _tagpropertykey { fmtid = new Guid("E81E79BE-34F0-41BF-B53F-F1A06AE87842"), pid = 0 };


            System.Runtime.InteropServices.ComTypes.IStream sourceStream = null;
            try
            {
                resources.GetStream(objectId, ref property, 0, ref optimalTransferSize, out wpdStream);
                sourceStream = (System.Runtime.InteropServices.ComTypes.IStream)wpdStream;


                FileStream targetStream = new FileStream(destPath, FileMode.Create, FileAccess.Write);
                unsafe
                {
                    try
                    {
                        var buffer = new byte[1024];
                        int bytesRead;
                        do
                        {
                            sourceStream.Read(buffer, 1024, new IntPtr(&bytesRead));
                            targetStream.Write(buffer, 0, 1024);
                        } while (bytesRead > 0);
                    }
                    finally
                    {
                        targetStream.Close();
                    }
                }
            }
            finally
            {
                Marshal.ReleaseComObject(sourceStream);
                Marshal.ReleaseComObject(wpdStream);
            }
        }

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 2
    评论
好的,以下是使用 Windows SDK 版本为 8.1 实现枚举 WPD 设备内容的基本步骤: 1. 初始化 WPD API,并获取 WPD 服务的 IUnknown 接口。 ``` CoInitialize(NULL); HRESULT hr = CoCreateInstance( __uuidof(PortableDeviceManager), NULL, CLSCTX_INPROC_SERVER, __uuidof(IPortableDeviceManager), (VOID**)&pPortableDeviceManager ); ``` 2. 使用 IPortableDeviceManager::GetDevices 方法获取连接到计算机上的 WPD 设备。 ``` GUID guid = { 0 }; DWORD dwCount = 0; hr = pPortableDeviceManager->GetDevices(&guid, NULL, &dwCount); if (SUCCEEDED(hr) && dwCount > 0) { PWSTR* pDeviceIDs = new PWSTR[dwCount]; hr = pPortableDeviceManager->GetDevices(&guid, pDeviceIDs, &dwCount); if (SUCCEEDED(hr)) { // 枚举设备内容 for (DWORD i = 0; i < dwCount; i++) { EnumerateDeviceContent(pDeviceIDs[i]); } } // 释放设备 ID 数组 for (DWORD i = 0; i < dwCount; i++) { CoTaskMemFree(pDeviceIDs[i]); } delete[] pDeviceIDs; } ``` 3. 枚举设备内容,使用 IPortableDeviceContent 接口获取设备内容信息。 ``` void EnumerateDeviceContent(PCWSTR pszDeviceID) { IPortableDevice* pPortableDevice = NULL; IPortableDeviceContent* pPortableDeviceContent = NULL; // 连接到设备 HRESULT hr = CoCreateInstance( __uuidof(PortableDevice), NULL, CLSCTX_INPROC_SERVER, __uuidof(IPortableDevice), (VOID**)&pPortableDevice ); if (SUCCEEDED(hr)) { hr = pPortableDevice->Open(pszDeviceID, pPortableDeviceCallback); if (SUCCEEDED(hr)) { hr = pPortableDevice->Content(&pPortableDeviceContent); if (SUCCEEDED(hr)) { // 枚举设备内容 EnumerateContent(pPortableDeviceContent, L""); } } // 关闭设备连接 pPortableDevice->Close(); } // 释放设备对象 if (pPortableDevice) { pPortableDevice->Release(); } if (pPortableDeviceContent) { pPortableDeviceContent->Release(); } } ``` 4. 使用 IPortableDeviceContent::EnumObjects 方法枚举设备内容。 ``` void EnumerateContent(IPortableDeviceContent* pContent, PCWSTR pszObjectID) { IEnumPortableDeviceObjectIDs* pEnum = NULL; // 枚举对象 ID HRESULT hr = pContent->EnumObjects(0, pszObjectID, NULL, &pEnum); if (SUCCEEDED(hr)) { DWORD dwFetched = 0; PWSTR pszObjectIDs[MAX_OBJECTS] = { 0 }; // 获取对象 ID 数组 hr = pEnum->Next(MAX_OBJECTS, pszObjectIDs, &dwFetched); if (SUCCEEDED(hr)) { // 枚举每个对象 for (DWORD i = 0; i < dwFetched; i++) { EnumerateObject(pContent, pszObjectIDs[i]); } } // 释放对象 ID 数组 for (DWORD i = 0; i < dwFetched; i++) { CoTaskMemFree(pszObjectIDs[i]); } } // 释放枚举器对象 if (pEnum) { pEnum->Release(); } } ``` 5. 使用 IPortableDeviceContent::Properties 方法获取对象属性。 ``` void EnumerateObject(IPortableDeviceContent* pContent, PCWSTR pszObjectID) { IPortableDeviceProperties* pProperties = NULL; // 获取对象属性 HRESULT hr = pContent->Properties(&pProperties); if (SUCCEEDED(hr)) { IPortableDeviceValues* pValues = NULL; // 获取对象属性值 hr = pProperties->GetValues(pszObjectID, NULL, &pValues); if (SUCCEEDED(hr)) { // 输出对象属性值 OutputObjectProperties(pValues); } // 释放属性值对象 if (pValues) { pValues->Release(); } } // 释放属性对象 if (pProperties) { pProperties->Release(); } } ``` 以上就是使用 Windows SDK 版本为 8.1 实现枚举 WPD 设备内容的基本步骤。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值