Get the "Tags" property in C#

Dave Gray 586 Reputation points
2022-11-16T16:07:59.083+00:00

Hello

Can anyone please tell me how I can get the value of the "Tags" column as shown in Windows Explorer using C#?

e.g.
261006-image.png

Very simple Console app using FileInfo but there's no attribute for Tags" as far as I can see.

260990-image.png

Thanks in advance.

Developer technologies | C#
{count} votes

2 answers

Sort by: Most helpful
  1. Bruce (SqlWork.com) 77,926 Reputation points Volunteer Moderator
    2022-11-16T17:43:50.83+00:00

    this a windows only feature called extended properties. you will need to the system shell:

    https://learn.microsoft.com/en-us/windows/win32/shell/shellfolderitem-extendedproperty?redirectedfrom=MSDN

    0 comments No comments

  2. Castorix31 90,686 Reputation points
    2022-11-16T17:59:16.617+00:00

    You can use IPropertyStore

    For example :

            string sFileName = @"E:\test.jpg";  
            IPropertyStore pPropertyStore = null;  
            Guid PropertyStoreGuid = typeof(IPropertyStore).GUID;  
            HRESULT hr = SHGetPropertyStoreFromParsingName(sFileName, IntPtr.Zero, GETPROPERTYSTOREFLAGS.GPS_READWRITE, ref PropertyStoreGuid, out pPropertyStore);  
            if (hr == HRESULT.S_OK)  
            {  
                var pv = new PROPVARIANT();  
                hr = pPropertyStore.GetValue(PKEY_Keywords, out pv);  
                if (pv.varType == (ushort)(VARENUM.VT_VECTOR | VARENUM.VT_LPWSTR))  
                {  
                    for (uint i=0; i<pv.ca.cElems; i++)  
                    {    
                        IntPtr pString = Marshal.ReadIntPtr(pv.ca.pElems, (int) i * IntPtr.Size);  
                        string sKeyWord = Marshal.PtrToStringUni(pString);  
                        Marshal.FreeCoTaskMem(pString);  
                        Console.WriteLine("Tag({0}) : {1}", i, sKeyWord);  
                    }  
                }  
                Marshal.ReleaseComObject(pPropertyStore);  
            }  
    

    with declarations :

        public enum HRESULT : int  
        {  
            S_OK = 0,  
            S_FALSE = 1,  
            E_NOINTERFACE = unchecked((int)0x80004002),  
            E_NOTIMPL = unchecked((int)0x80004001),  
            E_FAIL = unchecked((int)0x80004005),  
            E_UNEXPECTED = unchecked((int)0x8000FFFFL)  
        }  
    
        [DllImport("Shell32.dll", SetLastError = true, CharSet = CharSet.Unicode)]  
        public static extern HRESULT SHGetPropertyStoreFromParsingName(string pszPath, IntPtr pbc, GETPROPERTYSTOREFLAGS flags, ref Guid iid, [MarshalAs(UnmanagedType.Interface)] out IPropertyStore propertyStore);  
    
        public enum GETPROPERTYSTOREFLAGS  
        {  
            GPS_DEFAULT = 0,  
            GPS_HANDLERPROPERTIESONLY = 0x1,  
            GPS_READWRITE = 0x2,  
            GPS_TEMPORARY = 0x4,  
            GPS_FASTPROPERTIESONLY = 0x8,  
            GPS_OPENSLOWITEM = 0x10,  
            GPS_DELAYCREATION = 0x20,  
            GPS_BESTEFFORT = 0x40,  
            GPS_NO_OPLOCK = 0x80,  
            GPS_PREFERQUERYPROPERTIES = 0x100,  
            GPS_EXTRINSICPROPERTIES = 0x200,  
            GPS_EXTRINSICPROPERTIESONLY = 0x400,  
            GPS_VOLATILEPROPERTIES = 0x800,  
            GPS_VOLATILEPROPERTIESONLY = 0x1000,  
            GPS_MASK_VALID = 0x1FFF  
        }  
    
        [ComImport, Guid("886D8EEB-8CF2-4446-8D02-CDBA1DBDCF99"), InterfaceType(ComInterfaceType.InterfaceIsIUnknown)]  
        public interface IPropertyStore  
        {  
            HRESULT GetCount([Out] out uint propertyCount);  
            HRESULT GetAt([In] uint propertyIndex, [Out, MarshalAs(UnmanagedType.Struct)] out PROPERTYKEY key);  
            HRESULT GetValue([In, MarshalAs(UnmanagedType.Struct)] ref PROPERTYKEY key, [Out, MarshalAs(UnmanagedType.Struct)] out PROPVARIANT pv);  
            HRESULT SetValue([In, MarshalAs(UnmanagedType.Struct)] ref PROPERTYKEY key, [In, MarshalAs(UnmanagedType.Struct)] ref PROPVARIANT pv);  
            HRESULT Commit();  
        }  
    
        [StructLayout(LayoutKind.Sequential, Pack = 4)]  
        public struct PROPERTYKEY  
        {  
            private readonly Guid _fmtid;  
            private readonly uint _pid;  
    
            public PROPERTYKEY(Guid fmtid, uint pid)  
            {  
                _fmtid = fmtid;  
                _pid = pid;  
            }    
        }  
    
        public static readonly PROPERTYKEY PKEY_Title = new PROPERTYKEY(new Guid("F29F85E0-4FF9-1068-AB91-08002B27B3D9"), 2);  
        public static readonly PROPERTYKEY PKEY_Keywords = new PROPERTYKEY(new Guid("F29F85E0-4FF9-1068-AB91-08002B27B3D9"), 5);  
     
        [StructLayout(LayoutKind.Sequential, Pack = 0)]  
        public struct PROPARRAY  
        {  
            public UInt32 cElems;  
            public IntPtr pElems;  
        }  
    
        [StructLayout(LayoutKind.Explicit, Pack = 1)]  
        public struct PROPVARIANT  
        {  
            [FieldOffset(0)]  
            public ushort varType;  
            [FieldOffset(2)]  
            public ushort wReserved1;  
            [FieldOffset(4)]  
            public ushort wReserved2;  
            [FieldOffset(6)]  
            public ushort wReserved3;  
    
            [FieldOffset(8)]  
            public byte bVal;  
            [FieldOffset(8)]  
            public sbyte cVal;  
            [FieldOffset(8)]  
            public ushort uiVal;  
            [FieldOffset(8)]  
            public short iVal;  
            [FieldOffset(8)]  
            public UInt32 uintVal;  
            [FieldOffset(8)]  
            public Int32 intVal;  
            [FieldOffset(8)]  
            public UInt64 ulVal;  
            [FieldOffset(8)]  
            public Int64 lVal;  
            [FieldOffset(8)]  
            public float fltVal;  
            [FieldOffset(8)]  
            public double dblVal;  
            [FieldOffset(8)]  
            public short boolVal;  
            [FieldOffset(8)]  
            public IntPtr pclsidVal; // GUID ID pointer  
            [FieldOffset(8)]  
            public IntPtr pszVal; // Ansi string pointer  
            [FieldOffset(8)]  
            public IntPtr pwszVal; // Unicode string pointer  
            [FieldOffset(8)]  
            public IntPtr punkVal; // punkVal (interface pointer)  
            [FieldOffset(8)]  
            public PROPARRAY ca;  
            [FieldOffset(8)]  
            public System.Runtime.InteropServices.ComTypes.FILETIME filetime;  
        }  
    
        public enum VARENUM  
        {  
            VT_EMPTY = 0,  
            VT_NULL = 1,  
            VT_I2 = 2,  
            VT_I4 = 3,  
            VT_R4 = 4,  
            VT_R8 = 5,  
            VT_CY = 6,  
            VT_DATE = 7,  
            VT_BSTR = 8,  
            VT_DISPATCH = 9,  
            VT_ERROR = 10,  
            VT_BOOL = 11,  
            VT_VARIANT = 12,  
            VT_UNKNOWN = 13,  
            VT_DECIMAL = 14,  
            VT_I1 = 16,  
            VT_UI1 = 17,  
            VT_UI2 = 18,  
            VT_UI4 = 19,  
            VT_I8 = 20,  
            VT_UI8 = 21,  
            VT_INT = 22,  
            VT_UINT = 23,  
            VT_VOID = 24,  
            VT_HRESULT = 25,  
            VT_PTR = 26,  
            VT_SAFEARRAY = 27,  
            VT_CARRAY = 28,  
            VT_USERDEFINED = 29,  
            VT_LPSTR = 30,  
            VT_LPWSTR = 31,  
            VT_RECORD = 36,  
            VT_INT_PTR = 37,  
            VT_UINT_PTR = 38,  
            VT_FILETIME = 64,  
            VT_BLOB = 65,  
            VT_STREAM = 66,  
            VT_STORAGE = 67,  
            VT_STREAMED_OBJECT = 68,  
            VT_STORED_OBJECT = 69,  
            VT_BLOB_OBJECT = 70,  
            VT_CF = 71,  
            VT_CLSID = 72,  
            VT_VERSIONED_STREAM = 73,  
            VT_BSTR_BLOB = 0xfff,  
            VT_VECTOR = 0x1000,  
            VT_ARRAY = 0x2000,  
            VT_BYREF = 0x4000,  
            VT_RESERVED = 0x8000,  
            VT_ILLEGAL = 0xffff,  
            VT_ILLEGALMASKED = 0xfff,  
            VT_TYPEMASK = 0xfff  
        };
    
    0 comments No comments

Your answer

Answers can be marked as Accepted Answers by the question author, which helps users to know the answer solved the author's problem.