Можно ли использовать часть имени синтаксического анализа объекта Shell в API переносного устройства windows (WPD) для получения потока файлов? - PullRequest
0 голосов
/ 19 февраля 2020

Всегда ли правильно использовать первую часть последнего guid из windows api codepack Имя синтаксического анализа ShellObject, представляющее путь к USB-подключенному устройству android или iphone при передаче файла в локальное хранилище в windows переносное устройство (WPD) api?

Например. Пример синтаксического анализа имени из ShellObject: вызов имени синтаксического анализа:

::{20D04FE0-3AEA-1069-A2D8-08002B30309D}\\\?\usb#vid_22b8&pid_2e82#zy322kldjb#{6ac27878-a6fa-4155-ba85-f98f491d4f33}\{00000009-0001-0001-0000-000000000000}\{00000009-0001-0001-0000-000000000000}\{00005461-0001-0001-0000-000000000000}

Насколько я могу судить, это означает:

- My Computer    ::{20D04FE0-3AEA-1069-A2D8-08002B30309D}\
- USB device     \\?\usb#vid_22b8&pid_2e82#zy322kldjb#{6ac27878-a6fa-4155-ba85-f98f491d4f33}\
- Root folder    SID-{10001,,26401026048}\
- Folder 1       {00000009-0001-0001-0000-000000000000}\
- Folder 2       {00000075-0001-0001-0000-000000000000}\
- File           {00005461-0001-0001-0000-000000000000}

Перечисление содержимого Folder 2 на устройстве используя WPD API, я вижу, что тот же файл имеет идентификатор файла, например o5461 - это похоже на часть File выше.

Всегда ли это предположение правильно - могу ли я всегда использовать его как в следующем коде скопировать один файл с телефона android в локальное хранилище на c -приводе? Или есть иногда несоответствие? Кроме того, что означает «o» в идентификаторе файла?

Кажется, это работает, но я не решаюсь использовать его в готовом к использованию коде.

using System.IO;
using PortableDeviceApiLib;

public class Copier
{
  public void PerformCopy()
  {
    var deviceId = @"\\?\usb#vid_22b8&pid_2e82#zy322kldjb#{6ac27878-a6fa-4155-ba85-f98f491d4f33}";
    var sourceItemGuidString = "{00005461-0001-0001-0000-000000000000}";
    var destinationPath = @"C:\Test\";
    var fileName = "Testing.jpg";
    var size = 3738545;

    // get "o5461" from the parsing path from the Shell libraries
    var fileId = "o" + sourceItemGuidString.Replace("{", string.Empty).Replace("}", string.Empty).Split('-')[0].TrimStart('0');

    this.TransferContentFromDevice(deviceId, fileId, size, destinationPath, fileName);
  }

  private void TransferContentFromDevice(string deviceId, string fileId, long length, string saveToPath, string fileName)
  {
    PortableDeviceClass device;

    try
    {
      device = SomehowGetOnePortableDeviceAndConnectToIt(deviceId);

      // Make sure that the target dir exists.
      Directory.CreateDirectory(saveToPath);

      device.Content(out var content);
      content.Transfer(out var resources);

      var property = new _tagpropertykey
      {
        fmtid = new Guid(0xE81E79BE, 0x34F0, 0x41BF, 0xB5, 0x3F, 0xF1, 0xA0, 0x6A, 0xE8, 0x78, 0x42),
        pid = 0
      };

      uint optimalTransferSize = 0;
      resources.GetStream(fileId, ref property, 0, ref optimalTransferSize, out IStream wpdStream);

      var sourceStream = (System.Runtime.InteropServices.ComTypes.IStream)wpdStream;
      using (var targetStream = new FileStream(Path.Combine(saveToPath, fileName), FileMode.Create, FileAccess.Write))
      {
        // Get the total size.
        long written = 0;
        long lPCt = 0;
        unsafe
        {
          var buffer = new byte[1024];
          int bytesRead;
          do
          {
            sourceStream.Read(buffer, 1024, new IntPtr(&bytesRead));
            targetStream.Write(buffer, 0, bytesRead);

            written += 1024;
            long PCt = length > 0 ? (100 * written) / length : 100;
            if (PCt != lPCt)
            {
              lPCt = PCt;
              Console.WriteLine("Progress: " + lPCt);
            }
          } while (bytesRead > 0);
        }
      }          
    }
    finally
    {
      Disconnect(device);
    }
  }
} 

1 Ответ

0 голосов
/ 20 февраля 2020

Если item имеет имя для разбора, как показано ниже, я был после части 5461 из окончательного guid:

::{20D04FE0-3AEA-1069-A2D8-08002B30309D}\\\?\usb#vid_22b8&pid_2e82#zy322kldjb#{6ac27878-a6fa-4155-ba85-f98f491d4f33}\SID-{10001,,26401026048}\{00000009-0001-0001-0000-000000000000}\{00000075-0001-0001-0000-000000000000}\{00005461-0001-0001-0000-000000000000}

Мы можем использовать следующий код, который получит свойство WPD_OBJECT_ID от ShellObject. Подробнее об этом и связанных свойствах здесь :

string GetFileId(ShellObject item)
{
  const int WPD_OBJECT_ID = 2;      
  var property = item.Properties.GetProperty(new PropertyKey(new Guid("{ef6b490d-5cd8-437a-affc-da8b60ee4a3c}"), WPD_OBJECT_ID));
  return property.ValueAsObject as string;
}

Возвращает идентификатор файла o5641, который затем можно напрямую использовать в моем методе TransferContentFromDevice.

Спасибо @SimonMourier за то, что указал мне правильное направление.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...