最新消息:雨落星辰是一个专注网站SEO优化、网站SEO诊断、搜索引擎研究、网络营销推广、网站策划运营及站长类的自媒体原创博客

windows shell - Retrieve custom status set on a StorageFile in cloud file api - Stack Overflow

programmeradmin5浏览0评论

I have set some custom properties on a file in cloud file workspace using StorageProviderItemProperties.SetASync(IStorageItem, IEnumerable).

I am now trying to retrieve the values later using below code :

StorageFile file;
var properties = await file.Properties.RetrievePropertiesAsync(["System.StorageProviderCustomStates"])

It will provide me a single result in properties dictionary with a value of byte[]. I would like to deserialize it into something meaningful. I have tried to :

  • Deserialize it in to an object using MemoryStream. Deserialization failed.
  • Convert to string System.Text.Encoding.UTF8.GetString(byte[]), however, it did not provide any structured data that can be used to extract custom status (values and icons) that were set. I have also tried with different Encoding like ASCII and Unicode without success.

Please suggest if there is some structure to this data that we can work with or any alternative way to extract custom statuses previously set on a file.

I have set some custom properties on a file in cloud file workspace using StorageProviderItemProperties.SetASync(IStorageItem, IEnumerable).

I am now trying to retrieve the values later using below code :

StorageFile file;
var properties = await file.Properties.RetrievePropertiesAsync(["System.StorageProviderCustomStates"])

It will provide me a single result in properties dictionary with a value of byte[]. I would like to deserialize it into something meaningful. I have tried to :

  • Deserialize it in to an object using MemoryStream. Deserialization failed.
  • Convert to string System.Text.Encoding.UTF8.GetString(byte[]), however, it did not provide any structured data that can be used to extract custom status (values and icons) that were set. I have also tried with different Encoding like ASCII and Unicode without success.

Please suggest if there is some structure to this data that we can work with or any alternative way to extract custom statuses previously set on a file.

Share Improve this question asked Mar 26 at 6:42 Nish26Nish26 9879 silver badges16 bronze badges 3
  • 1 You must create an IPropertyStore COM reference with PSCreateMemoryPropertyStore then QueryInterface for IPersistStream and then IPersistStream::Load (the values are an array of bytes that you must convert to a stream). After that you can use IPropertyStore's methods like GetValue, etc. If it doesn't work instead of IPersistStream get IPersistSerializedPropStorage and use IPersistSerializedPropStorage::SetPropertyStorage and pass a pointer to the array of bytes – Simon Mourier Commented Mar 26 at 8:02
  • IPersistSerializedPropStorage::SetPropertyStorage worked. Thanks a lot. – Nish26 Commented Mar 27 at 6:21
  • You should answer yoursefl with some sample code – Simon Mourier Commented Mar 27 at 7:39
Add a comment  | 

1 Answer 1

Reset to default 0

Usage

 IStorageItem storageItem = await GetStorageItemAsync(path)
 using(var propertyStore = new StorageItemPropertyProvider())
 {
     if(storageItem is IStorageItemProperties storageItemProperties)
     {
        return await propertyStore.GetPropertiesAsync(storageItemProperties);
     }
 }

Required Classes ( Using Vanara library)

public sealed class StorageItemPropertyProvider : IDisposable
{
    private IPropertyStore? propertyStore;
    private bool isDisposed = false;

    public StorageItemPropertyProvider()
    {
        propertyStore = CreatePropertyStore() ?? throw new InvalidOperationException("Failed to create IPropertyStore"); 
    }

    /// <summary>
    /// Creates an instance of IPropertyStore using PSCreateMemoryPropertyStore function from Vanara
    /// </summary>
    /// <returns></returns>
    private static IPropertyStore? CreatePropertyStore()
    {
        Guid IID_IPropertyStore = typeof(IPropertyStore).GUID;
        PSCreateMemoryPropertyStore(IID_IPropertyStore, out object propStore).ThrowIfFailed();
        return propStore as IPropertyStore;
    }

    /// <summary>
    /// Retrieves the StorageProviderItemProperty of a storage item that were previously set on the storage item
    /// </summary>   
    public async Task<Dictionary<string, StorageProviderItemProperty>> GetPropertiesAsync(IStorageItemProperties storageItem)
    {
        ThrowIfDisposed();

        Dictionary<string, StorageProviderItemProperty> properties = new();
        var customStates = (await storageItem.Properties.RetrievePropertiesAsync(["System.StorageProviderCustomStates"])).FirstOrDefault();
        if (customStates.Value is byte[] customStatesValue)
        {
            LoadByteArrayIntoPersistStream(customStatesValue);

            //System.ItemCustomState.StateList holds the IDs of the custom states
            using PROPVARIANT stateList = GetProperty("System.ItemCustomState.StateList");
            if (stateList.Value is string[] states && states.Any())
            {
                //System.ItemCustomState.Values holds the values for each ID in System.ItemCustomState.StateList
                using PROPVARIANT valueList = GetProperty("System.ItemCustomState.Values");
                string[] values = valueList.Value as string[] ?? new string[states.Count()];

                //System.ItemCustomState.IconReferences holds the values for each ID in System.ItemCustomState.StateList
                using PROPVARIANT iconList = GetProperty("System.ItemCustomState.IconReferences");
                string[] icons = iconList.Value as string[] ?? new string[states.Count()];

                int index = 0;
                foreach (var propertyID in states)
                {
                    properties.Add(propertyID, new StorageProviderItemProperty()
                    {
                        Id = int.Parse(propertyID),
                        Value = (values)[index],
                        IconResource = (icons)[index]
                    });
                    index++;
                }
            }
        }
        return properties;
    }

    /// <summary>
    /// Loads the byte array representation of serialized StorageItemProperties of a IStorageITem into the IPersistSerializedPropStorage  
    /// </summary>
    /// <param name="data"></param>
    /// <exception cref="InvalidOperationException">When IPropertyStore is not a IPersistSerializedPropStorage</exception>
    private void LoadByteArrayIntoPersistStream(byte[] data)
    {
        if (data is not null)
        {
            // Allocate memory for the byte array
            IntPtr pData = Marshal.AllocHGlobal(data.Length);
            Marshal.Copy(data, 0, pData, data.Length);
            if (propertyStore is IPersistSerializedPropStorage persistStream)
            {   
                // Load the byte array into IPersistStream
                persistStream.SetPropertyStorage(pData, (uint)data.Length);
            }
            else
            {
                throw new InvalidOperationException("PropertyStore does not support IPersistSerializedPropStorage");
            }
            // Clean up
            Marshal.FreeHGlobal(pData);
        }
    }

    /// <summary>
    /// Retrieves the property value for the given property key
    /// </summary>
    /// <param name="propertyKey">Canonical name of the property</param>
    /// <returns></returns>
    PROPVARIANT GetProperty(string propertyKey)
    {
        PROPVARIANT result = new();
        PropSys.PSGetPropertyKeyFromName(propertyKey, out var key);
        propertyStore?.GetValue(key, result);
        return result;
    }

    /// <summary>
    /// Throws <see cref="ObjectDisposedException"/> if the object is disposed
    /// </summary>
    /// <exception cref="ObjectDisposedException"></exception>
    void ThrowIfDisposed()
    {
        if (isDisposed)
        {
            throw new ObjectDisposedException(nameof(StorageItemPropertyProvider));
        }
    }

    /// <inheritdoc/>
    public void Dispose()
    {
        if (!isDisposed)
        {
            Marshal.ReleaseComObject(propertyStore);
            propertyStore = null;
            isDisposed = true;
        }
    }
}
发布评论

评论列表(0)

  1. 暂无评论