Как получить доступное устройство хранения MTP с помощью C#?

Я использую PortableDevice API для получения определения устройства MTP и свойств устройства. Я хочу получить MTP Device Storage, такой как емкость и доступное хранилище. Вот мой пример кода для получения понятного названия устройства:

public string FriendlyName
    {
        get
        {
            if (!this._isConnected)
            {
                throw new InvalidOperationException("Not connected to device.");
            }

            // Retrieve the properties of the device
            IPortableDeviceContent content;
            IPortableDeviceProperties properties;
            this._device.Content(out content);
            content.Properties(out properties);

            // Retrieve the values for the properties
            IPortableDeviceValues propertyValues;
            properties.GetValues("DEVICE", null, out propertyValues);

            // Identify the property to retrieve
            var property = new _tagpropertykey();
            property.fmtid = new Guid(0x26D4979A, 0xE643, 0x4626, 0x9E, 0x2B,
                                      0x73, 0x6D, 0xC0, 0xC9, 0x2F, 0xDC);
            property.pid = 12;

            // Retrieve the friendly name
            string propertyValue;
            propertyValues.GetStringValue(ref property, out propertyValue);

            return propertyValue;
        }
    }

Точно так же я хочу прочитать устройство хранения и свободного места с устройства MTP.

Я пытался так, но мне чего-то не хватает,

IPortableDeviceKeyCollection keys;
        properties.GetSupportedProperties(objectId, out keys);

        IPortableDeviceValues values;
        properties.GetValues(objectId, keys, out values);

        // Get the name of the object
        string name;
        var property = new _tagpropertykey();            
        property.fmtid = new Guid(0x01A3057A, 0x74D6, 0x4E80, 0xBE, 0xA7, 0xDC, 0x4C, 0x21, 0x2C, 0xE5, 0x0A);
        property.pid = 7;
        values.GetStringValue(property, out name);

        // Get the type of the object
        Guid contentType;
        property = new _tagpropertykey();

        property.fmtid = new Guid(0x01A3057A, 0x74D6, 0x4E80, 0xBE, 0xA7, 0xDC, 0x4C, 0x21, 0x2C, 0xE5, 0x0A);

        property.pid = 5;
        values.GetGuidValue(property, out contentType);

        var storageType = new Guid(0xEF6B490D, 0x5CD8, 0x437A, 0xAF, 0xFC, 0xDA, 0x8B, 0x60, 0xEE, 0x4A, 0x3C);

        var functionalType = new Guid(0x8F052D93, 0xABCA, 0x4FC5, 0xA5, 0xAC, 0xB0, 0x1D, 0xF4, 0xDB, 0xE5, 0x98);

.........................................................................

Заранее спасибо.

1 ответ

//Collecting the supported keys
IPortableDeviceKeyCollection keys;
properties.GetSupportedProperties(objectId, out keys);

//Init
_tagpropertykey key = new _tagpropertykey();
uint count = 0;
keys.GetCount(ref count);

//temporarily store each key and display
for (uint i = 0; i < count; i++)
{
    keys.GetAt(i, ref key);
    Console.WriteLine("fmtid " + key.fmtid + " pid " + key.pid);
}

Просто к сведению, это некоторый код для отображения поддерживаемых ключей свойств. Если вы передадите objectID не корневой папки, а первой папки (в Проводнике, например, "Внутреннее хранилище"), вы увидите

WPD_STORAGE_CAPACITY _tagpropertykey

Я настоятельно рекомендую создать класс для хранения всех PropertyKeys¹, он будет выглядеть намного лучше.

Я думаю, что вы, вероятно, должны взглянуть на учебники cgeers, поэтому я возьму это за основу.

  1. Добавьте корневую папку в свой PortableDevice класс для легкого доступа:

    private readonly PortableDeviceFolder root = new PortableDeviceFolder("DEVICE", "DEVICE");
    public PortableDeviceFolder Root
    {
        get
        {
            return root;
        }
    }
    
  2. Используйте этот код для objectId вашей папки (как упоминалось ранее, например, Internal Storage)

    IPortableDeviceProperties properties;
    content.Properties(out properties);
    
    IPortableDeviceValues values;
    properties.GetValues(objectId, keys, out values);
    
    //capacity stored as UI8 in PropVariant as stated in ² -> ulong
    ulong capacity = 0;
    values.GetUnsignedLargeIntegerValue(WPD_STORAGE_CAPACITY_IN_OBJECTS, out capacity); 
    

Этот код очень похож на части метода Refresh (и подметодов) от cgeers, поэтому ваш объект папки уже должен быть создан.

Тот факт, что вы можете извлечь эту информацию из этой папки, является либо чистым знанием / здравым смыслом (Win Explorer также показывает информацию об этой папке), либо может быть изучен путем выполнения первых строк кода в верхней части.

Я - для себя - изменил PortableDeviceFolder структура, которая теперь содержит коллекцию PortableDeviceObjects, которые находятся в папке, и каждый из них также сохраняет своего родителя.
Таким образом, доступ к папкам очень прост, например, чтобы получить желаемый folderId Я бы просто использовал этот код:

PortableDeviceCollection c = new PortableDeviceCollection();
c.Refresh();
PortableDevice device = c.First();
device.Root.RefreshFiles();
PortableDeviceFolder internalstorageFolder = (PortableDeviceFolder)device.Root.Files.First();

Вы можете попытаться реализовать такую ​​структуру самостоятельно или пойти другим путем, я думаю, что нет идеальной структуры для доступа, поэтому нужно выяснить, что подходит лучше всего.

¹: https://github.com/gtaglang/WpdLib/blob/master/src/WpdLib/WpdProperties.cs

²: https://msdn.microsoft.com/de-de/library/ff597918(v=vs.85).aspx

Другие вопросы по тегам