none
WPD - Extract results from IPortableDevicePropVariantCollection RRS feed

  • Question

  • I'm trying to create an application which can delete files from portable device (camera, smartphone, etc.) by using PortableDeviceApiLib. Here is the code I use:

    public void DeleteFile(string fileId)
    {
        portableDevice.Content(out IPortableDeviceContent content);
    
        tag_inner_PROPVARIANT variant = new tag_inner_PROPVARIANT();
        StringToPropVariant(fileId, out variant);
    
        IPortableDevicePropVariantCollection objectIds 
    		= new PortableDeviceTypesLib.PortableDevicePropVariantCollection() as IPortableDevicePropVariantCollection;
        objectIds.Add(variant);
    
        IPortableDevicePropVariantCollection ppResults 
    		= new PortableDeviceTypesLib.PortableDevicePropVariantCollection() as IPortableDevicePropVariantCollection;
        content.Delete(0, objectIds, ref ppResults);
    }

    But this code does not delete files from my smartphone. I'm trying to find the reasone why but I can not extract the information from IPortableDevicePropVariantCollection ppResults.

    How can I get errors from the deleting and find out why this code does not delete files from the portable device?

    Wednesday, November 6, 2019 11:16 AM

Answers

  • This blog entry WPD property retrieval in C# shows how to get to the content of a tag_inner_PROPVARIANT.

    The documentation for ppResults parameter of the Delete method at IPortableDeviceContent::Delete method says "On return, this parameter contains a collection of VT_ERROR values indicating the success or failure of the operation. The first element returned in ppResults corresponds to the first object in the pObjectIDs collection, the second element returned in ppResults corresponds to the second object in the pObjectIDs collection, and so on."

    So you would obtain tag_inner_PROPVARIANT objects from ppResults by getting the number of contained items with GetCount, and then loop to retrieve individual items with GetAt.  Once you have a tag_inner_PROPVARIANT object you can use the code from the blog to get the content.  For each item the tag_inner_PROPVARIANT.vt value should be 10 (VT_ERROR).  I suggest you add an additional entry to the blog's PropVariant structure to accommodate the error code such as -

    [FieldOffset(8)]
    public int scode;
    

    • Marked as answer by Vangi Monday, November 11, 2019 7:36 PM
    Sunday, November 10, 2019 11:29 AM
  • The -2147024726 error code is hexadecimal 0x800700AA.  For a COM error code 0x8007 means that the error corresponds to a Win32 error code. 0x00AA is decimal 170.  The related win32 error code is -

    ERROR_BUSY

    170 (0xAA)

    The requested resource is in use.


    • Edited by RLWA32 Monday, November 11, 2019 4:44 PM typo
    • Marked as answer by Vangi Monday, November 11, 2019 7:36 PM
    Monday, November 11, 2019 4:42 PM

All replies

  • Hi Vangi,

    Thank you for posting here.

    This is question about WPD. I am not very familiar with this, can you provide more information to me?

    For example, please provide the dll I need to install, and the specific information of the variables that appear in the code.

    Looking forward for your reply.

    Best Regards,

    Timon


    MSDN Community Support
    Please remember to click "Mark as Answer" the responses that resolved your issue, and to click "Unmark as Answer" if not. This can be beneficial to other community members reading this thread. If you have any compliments or complaints to MSDN Support, feel free to contact MSDNFSF@microsoft.com.

    Friday, November 8, 2019 1:37 AM
  • Hi Timon,

    Thank you for your quick response.

    I could not find the proper place to post my question therefore I wrote it here.

    The official information about how to delete file from portable device is found it here: 

    Deleting Content from the Device. The example is written in C++ and it does not explain how to take result of the IPortableDevicePropVariantCollection of the deleting. I also used the following post in C# WPD: Deleting Resources but there is no information about my case.

    About the libraries you can add COM reference to PortableDeviceApi 1.0 Type Library and PortableDeviceTypes 1.0 Type Library. The varible in the example is the ID of the file you want to delete. To get the ID of the file, first you have to find and connect to the device and then to get the ID from the list of all content. Let me know if you want to send you complete sample code at C#.

    Kind regards,

    Vangi

    Friday, November 8, 2019 4:48 PM
  • Are you forced to use PortableDeviceApi ?

    I did a quick test with my Smartphone and I can delete files with

    IFileOperation.DeleteItem (P/Invoke)

    (like Explorer in fact)

    Friday, November 8, 2019 5:21 PM
  • @Castorix31, thank you for your suggestion but I must use PortableDeviceApi. Anyway, I think this approach will not work for portable devices like cameras.

    Friday, November 8, 2019 7:55 PM
  • This blog entry WPD property retrieval in C# shows how to get to the content of a tag_inner_PROPVARIANT.

    The documentation for ppResults parameter of the Delete method at IPortableDeviceContent::Delete method says "On return, this parameter contains a collection of VT_ERROR values indicating the success or failure of the operation. The first element returned in ppResults corresponds to the first object in the pObjectIDs collection, the second element returned in ppResults corresponds to the second object in the pObjectIDs collection, and so on."

    So you would obtain tag_inner_PROPVARIANT objects from ppResults by getting the number of contained items with GetCount, and then loop to retrieve individual items with GetAt.  Once you have a tag_inner_PROPVARIANT object you can use the code from the blog to get the content.  For each item the tag_inner_PROPVARIANT.vt value should be 10 (VT_ERROR).  I suggest you add an additional entry to the blog's PropVariant structure to accommodate the error code such as -

    [FieldOffset(8)]
    public int scode;
    

    • Marked as answer by Vangi Monday, November 11, 2019 7:36 PM
    Sunday, November 10, 2019 11:29 AM
  • @RLWA32, thank you for your answer, this is exactly what I was looking for.

    But now I get the error -2147024726 which I don't know what exactly is. Do you know where can I get more readable description of these error codes?

    Here is the complete code:
    public void DeleteFile(string fileId)
    {
        portableDevice.Content(out IPortableDeviceContent content);
    
        tag_inner_PROPVARIANT variant = new tag_inner_PROPVARIANT();
    
        IPortableDeviceValues pValues = (IPortableDeviceValues)new PortableDeviceTypesLib.PortableDeviceValuesClass();
        pValues.SetStringValue(ref PortableDevicePKeys.WPD_OBJECT_ID, fileId);
        pValues.GetValue(ref PortableDevicePKeys.WPD_OBJECT_ID, out variant);
    
        IPortableDevicePropVariantCollection objectIds
            = new PortableDeviceTypesLib.PortableDevicePropVariantCollection() as IPortableDevicePropVariantCollection;
        objectIds.Add(variant);
    
        IPortableDevicePropVariantCollection ppResults
            = new PortableDeviceTypesLib.PortableDevicePropVariantCollection() as IPortableDevicePropVariantCollection;
        content.Delete(0, objectIds, ref ppResults);
    
        uint resultsCount = 0;
        ppResults.GetCount(ref resultsCount);
        for (uint i = 0; i < resultsCount; i++)
        {
            tag_inner_PROPVARIANT pValue = new tag_inner_PROPVARIANT();
            ppResults.GetAt(i, ref pValue);
            IntPtr ptrValue = Marshal.AllocHGlobal(Marshal.SizeOf(pValue));
            Marshal.StructureToPtr(pValue, ptrValue, false);
    
            /*
            [StructLayout(LayoutKind.Explicit, Size = 16)]
            internal struct PropVariant
            {
                [FieldOffset(0)]
                public short variantType;
                [FieldOffset(8)]
                public IntPtr pointerValue;
                [FieldOffset(8)]
                public byte byteValue;
                [FieldOffset(8)]
                public long intValue;
                [FieldOffset(8)]
                public long longValue;
                [FieldOffset(8)]
                public double dateValue;
                [FieldOffset(8)]
                public short boolValue;
                [FieldOffset(8)]
                public int sCode;
                }
                */
            PropVariant propVariant = (PropVariant)Marshal.PtrToStructure(ptrValue, typeof(PropVariant));
    
            // returned value is -2147024726
            string propVariantString = propVariant.AsString(); 
        }
    }
    Monday, November 11, 2019 4:27 PM
  • The -2147024726 error code is hexadecimal 0x800700AA.  For a COM error code 0x8007 means that the error corresponds to a Win32 error code. 0x00AA is decimal 170.  The related win32 error code is -

    ERROR_BUSY

    170 (0xAA)

    The requested resource is in use.


    • Edited by RLWA32 Monday, November 11, 2019 4:44 PM typo
    • Marked as answer by Vangi Monday, November 11, 2019 7:36 PM
    Monday, November 11, 2019 4:42 PM
  • @RLWA32 thank you again, you are awesome!

    I simply get the readable message from exception by the error code:

    Marshal.GetExceptionForHR(int.Parse(propVariantString)).Message

    Monday, November 11, 2019 7:36 PM