提取Windows文件属性(自定义属性)C#

前端之家收集整理的这篇文章主要介绍了提取Windows文件属性(自定义属性)C#前端之家小编觉得挺不错的,现在分享给大家,也给大家做个参考。
在Word / Excel中,您必须添加自定义属性. (见图)
Custom Properties.
你可以看到有一个字段:“属性:”,你可以添加任何你想要的信息.
当您保存文件并转到文件夹中的文件位置时,可以右键单击 – >属性,您具有所有选项卡:常规/安全性/详细信息/以前的版本.使用该功能添加选项卡自定义.

现在我想通过编码获得这些信息:Custom Properties information.然后将其解压缩到记事本.
到目前为止,我使用的是Shell32,但是我只得到“详细信息”选项卡中的信息.我做了一些研究,并看到了DSOfile.dll的一些可能性.但是我想知道是否有可能在不安装其他DLL的情况下执行此操作?
这是我的代码到目前为止的Shell32.

static void Main(string[] args)
    {

        //using (StreamWriter writer = new StreamWriter(@"filepathhere"))
        //{
            //Console.SetOut(writer);
            ReadProperties();
        //}
    }
    static void ReadProperties()
    { 
        List<string> arrHeaders = new List<string>();
        Shell shell = new Shell();
        Folder objFolder = shell.NameSpace(@"filepathhere");
        FolderItem objFolderItem = objFolder.ParseName("filehere.doc");

        for (int i = 0; i < short.MaxValue; i++)
        {
            string header = objFolder.GetDetailsOf(objFolder,i);
            if (String.IsNullOrEmpty(header))
                break;
            arrHeaders.Add(header);
        }

        for ( int i = 0; i < arrHeaders.Count; i++)
        {
            Console.WriteLine("{0}\t{1}: {2}",i,arrHeaders[i],objFolder.GetDetailsOf(objFolderItem,i));
        }
        Console.ReadKey();
    }

提前致谢!

德苏

历史上,这些属性由称为“结构化存储”的技术定义.第一个结构化存储实现是古代(但还是很活跃)的 Compound File Format

之后,Microsoft添加了结构化存储功能directly into NTFS.这允许您在任何文件(甚至.txt)文件上定义属性,如作者或标题.尽管资源管理器UI不会因为某种原因让你这样做,但我认为它仍然以编程方式工作.

然后,随着Vista,微软重新启动所有这一切,并引入了所有这一切的超集:Windows Property System.

不幸的是,在所有这一切的框架中没有.NET API.但Microsoft创建了一个名为Windows API CodePack的开源.NET库.所以,您最简单的方法提取属性添加对WindowsAPICodePack Core NugetPackage的引用,您可以使用它:

static void Main(string[] args)
{
    foreach (var prop in new ShellPropertyCollection(@"mypath\myfile"))
    {
        Console.WriteLine(prop.CanonicalName + "=" + prop.ValueAsObject);
    }
}

如果您不想添加额外的DLL,则可以从WindowsAPICodePack源(Windows API Code Pack: Where is it?)中提取ShellPropertyCollection代码.这是一个很好的工作,但可行.

在您的情况下的另一个解决方案是使用旧的Structure Storage原生API.我提供了一个这样做的示例.这是你如何使用它:

static void Main(string[] args)
{
    foreach (var prop in new StructuredStorage(@"mypath\myfile").Properties)
    {
        Console.WriteLine(prop.Name + "=" + prop.Value);
    }            
}

public sealed class StructuredStorage
{
    public static readonly Guid SummaryInformationFormatId = new Guid("{F29F85E0-4FF9-1068-AB91-08002B27B3D9}");
    public static readonly Guid DocSummaryInformationFormatId = new Guid("{D5CDD502-2E9C-101B-9397-08002B2CF9AE}");
    public static readonly Guid UserDefinedPropertiesId = new Guid("{D5CDD505-2E9C-101B-9397-08002B2CF9AE}");

    private List<StructuredProperty> _properties = new List<StructuredProperty>();

    public StructuredStorage(string filePath)
    {
        if (filePath == null)
            throw new ArgumentNullException("filePath");

        FilePath = filePath;
        IPropertySetStorage propertySetStorage;
        int hr = StgOpenStorageEx(FilePath,STGM.STGM_READ | STGM.STGM_SHARE_DENY_NONE | STGM.STGM_DIRECT_SWMR,STGFMT.STGFMT_ANY,IntPtr.Zero,typeof(IPropertySetStorage).GUID,out propertySetStorage);
        if (hr == STG_E_FILENOTFOUND || hr == STG_E_PATHNOTFOUND)
            throw new FileNotFoundException(null,FilePath);

        if (hr != 0)
            throw new Win32Exception(hr);

        try
        {
            LoadPropertySet(propertySetStorage,SummaryInformationFormatId);
            LoadPropertySet(propertySetStorage,DocSummaryInformationFormatId);
        }
        finally
        {
            Marshal.ReleaseComObject(propertySetStorage);
        }

        // for some reason we can't read this one on the same COM ref?
        LoadProperties(UserDefinedPropertiesId);
    }

    public string FilePath { get; private set; }
    public IReadOnlyList<StructuredProperty> Properties
    {
        get
        {
            return _properties;
        }
    }

    private void LoadPropertySet(IPropertySetStorage propertySetStorage,Guid fmtid)
    {
        IPropertyStorage propertyStorage;
        int hr = propertySetStorage.Open(fmtid,STGM.STGM_READ | STGM.STGM_SHARE_EXCLUSIVE,out propertyStorage);
        if (hr == STG_E_FILENOTFOUND || hr == STG_E_ACCESSDENIED)
            return;

        if (hr != 0)
            throw new Win32Exception(hr);

        IEnumSTATPROPSTG es;
        propertyStorage.Enum(out es);
        if (es == null)
            return;

        try
        {
            var stg = new STATPROPSTG();
            int fetched;
            do
            {
                hr = es.Next(1,ref stg,out fetched);
                if (hr != 0 && hr != 1)
                    throw new Win32Exception(hr);

                if (fetched == 1)
                {
                    string name = GetPropertyName(fmtid,propertyStorage,stg);

                    var propsec = new PROPSPEC[1];
                    propsec[0] = new PROPSPEC();
                    propsec[0].ulKind = stg.lpwstrName != null ? PRSPEC.PRSPEC_LPWSTR : PRSPEC.PRSPEC_PROPID;
                    IntPtr lpwstr = IntPtr.Zero;
                    if (stg.lpwstrName != null)
                    {
                        lpwstr = Marshal.StringToCoTaskMemUni(stg.lpwstrName);
                        propsec[0].union.lpwstr = lpwstr;
                    }
                    else
                    {
                        propsec[0].union.propid = stg.propid;
                    }

                    var vars = new PROPVARIANT[1];
                    vars[0] = new PROPVARIANT();
                    try
                    {
                        hr = propertyStorage.ReadMultiple(1,propsec,vars);
                        if (hr != 0)
                            throw new Win32Exception(hr);

                    }
                    finally
                    {
                        if (lpwstr != IntPtr.Zero)
                        {
                            Marshal.FreeCoTaskMem(lpwstr);
                        }
                    }

                    object value;
                    try
                    {
                        switch (vars[0].vt)
                        {
                            case VARTYPE.VT_BOOL:
                                value = vars[0].union.boolVal != 0 ? true : false;
                                break;

                            case VARTYPE.VT_BSTR:
                                value = Marshal.PtrToStringUni(vars[0].union.bstrVal);
                                break;

                            case VARTYPE.VT_CY:
                                value = decimal.FromOACurrency(vars[0].union.cyVal);
                                break;

                            case VARTYPE.VT_DATE:
                                value = DateTime.FromOADate(vars[0].union.date);
                                break;

                            case VARTYPE.VT_DECIMAL:
                                IntPtr dec = IntPtr.Zero;
                                Marshal.StructureToPtr(vars[0],dec,false);
                                value = Marshal.PtrToStructure(dec,typeof(decimal));
                                break;

                            case VARTYPE.VT_DISPATCH:
                                value = Marshal.GetObjectForIUnknown(vars[0].union.pdispVal);
                                break;

                            case VARTYPE.VT_ERROR:
                            case VARTYPE.VT_HRESULT:
                                value = vars[0].union.scode;
                                break;

                            case VARTYPE.VT_FILETIME:
                                value = DateTime.FromFileTime(vars[0].union.filetime);
                                break;

                            case VARTYPE.VT_I1:
                                value = vars[0].union.cVal;
                                break;

                            case VARTYPE.VT_I2:
                                value = vars[0].union.iVal;
                                break;

                            case VARTYPE.VT_I4:
                                value = vars[0].union.lVal;
                                break;

                            case VARTYPE.VT_I8:
                                value = vars[0].union.hVal;
                                break;

                            case VARTYPE.VT_INT:
                                value = vars[0].union.intVal;
                                break;

                            case VARTYPE.VT_LPSTR:
                                value = Marshal.PtrToStringAnsi(vars[0].union.pszVal);
                                break;

                            case VARTYPE.VT_LPWSTR:
                                value = Marshal.PtrToStringUni(vars[0].union.pwszVal);
                                break;

                            case VARTYPE.VT_R4:
                                value = vars[0].union.fltVal;
                                break;

                            case VARTYPE.VT_R8:
                                value = vars[0].union.dblVal;
                                break;

                            case VARTYPE.VT_UI1:
                                value = vars[0].union.bVal;
                                break;

                            case VARTYPE.VT_UI2:
                                value = vars[0].union.uiVal;
                                break;

                            case VARTYPE.VT_UI4:
                                value = vars[0].union.ulVal;
                                break;

                            case VARTYPE.VT_UI8:
                                value = vars[0].union.uhVal;
                                break;

                            case VARTYPE.VT_UINT:
                                value = vars[0].union.uintVal;
                                break;

                            case VARTYPE.VT_UNKNOWN:
                                value = Marshal.GetObjectForIUnknown(vars[0].union.punkVal);
                                break;

                            default:
                                value = null;
                                break;
                        }
                    }
                    finally
                    {
                        PropVariantClear(ref vars[0]);
                    }

                    var property = new StructuredProperty(fmtid,name,stg.propid);
                    property.Value = value;
                    _properties.Add(property);
                }
            }
            while (fetched == 1);
        }
        finally
        {
            Marshal.ReleaseComObject(es);
        }
    }

    private static string GetPropertyName(Guid fmtid,IPropertyStorage propertyStorage,STATPROPSTG stg)
    {
        if (!string.IsNullOrEmpty(stg.lpwstrName))
            return stg.lpwstrName;

        var propids = new int[1];
        propids[0] = stg.propid;
        var names = new string[1];
        names[0] = null;
        int hr = propertyStorage.ReadPropertyNames(1,propids,names);
        if (hr == 0)
            return names[0];

        return null;
    }

    public void LoadProperties(Guid formatId)
    {
        IPropertySetStorage propertySetStorage;
        int hr = StgOpenStorageEx(FilePath,formatId);
        }
        finally
        {
            Marshal.ReleaseComObject(propertySetStorage);
        }
    }

    private const int STG_E_FILENOTFOUND = unchecked((int)0x80030002);
    private const int STG_E_PATHNOTFOUND = unchecked((int)0x80030003);
    private const int STG_E_ACCESSDENIED = unchecked((int)0x80030005);

    private enum PRSPEC
    {
        PRSPEC_LPWSTR = 0,PRSPEC_PROPID = 1
    }

    private enum STGFMT
    {
        STGFMT_ANY = 4,}

    [Flags]
    private enum STGM
    {
        STGM_READ = 0x00000000,STGM_READWRITE = 0x00000002,STGM_SHARE_DENY_NONE = 0x00000040,STGM_SHARE_DENY_WRITE = 0x00000020,STGM_SHARE_EXCLUSIVE = 0x00000010,STGM_DIRECT_SWMR = 0x00400000
    }

    // we only define what we handle
    private enum VARTYPE : short
    {
        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_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_HRESULT = 25,VT_LPSTR = 30,VT_LPWSTR = 31,VT_FILETIME = 64,}

    [StructLayout(LayoutKind.Explicit)]
    private struct PROPVARIANTunion
    {
        [FieldOffset(0)]
        public sbyte cVal;
        [FieldOffset(0)]
        public byte bVal;
        [FieldOffset(0)]
        public short iVal;
        [FieldOffset(0)]
        public ushort uiVal;
        [FieldOffset(0)]
        public int lVal;
        [FieldOffset(0)]
        public uint ulVal;
        [FieldOffset(0)]
        public int intVal;
        [FieldOffset(0)]
        public uint uintVal;
        [FieldOffset(0)]
        public long hVal;
        [FieldOffset(0)]
        public ulong uhVal;
        [FieldOffset(0)]
        public float fltVal;
        [FieldOffset(0)]
        public double dblVal;
        [FieldOffset(0)]
        public short boolVal;
        [FieldOffset(0)]
        public int scode;
        [FieldOffset(0)]
        public long cyVal;
        [FieldOffset(0)]
        public double date;
        [FieldOffset(0)]
        public long filetime;
        [FieldOffset(0)]
        public IntPtr bstrVal;
        [FieldOffset(0)]
        public IntPtr pszVal;
        [FieldOffset(0)]
        public IntPtr pwszVal;
        [FieldOffset(0)]
        public IntPtr punkVal;
        [FieldOffset(0)]
        public IntPtr pdispVal;
    }

    [StructLayout(LayoutKind.Sequential)]
    private struct PROPSPEC
    {
        public PRSPEC ulKind;
        public PROPSPECunion union;
    }

    [StructLayout(LayoutKind.Explicit)]
    private struct PROPSPECunion
    {
        [FieldOffset(0)]
        public int propid;
        [FieldOffset(0)]
        public IntPtr lpwstr;
    }

    [StructLayout(LayoutKind.Sequential)]
    private struct PROPVARIANT
    {
        public VARTYPE vt;
        public ushort wReserved1;
        public ushort wReserved2;
        public ushort wReserved3;
        public PROPVARIANTunion union;
    }

    [StructLayout(LayoutKind.Sequential)]
    private struct STATPROPSTG
    {
        [MarshalAs(UnmanagedType.LPWStr)]
        public string lpwstrName;
        public int propid;
        public VARTYPE vt;
    }

    [StructLayout(LayoutKind.Sequential)]
    private struct STATPROPSETSTG
    {
        public Guid fmtid;
        public Guid clsid;
        public uint grfFlags;
        public System.Runtime.InteropServices.ComTypes.FILETIME mtime;
        public System.Runtime.InteropServices.ComTypes.FILETIME ctime;
        public System.Runtime.InteropServices.ComTypes.FILETIME atime;
        public uint dwOSVersion;
    }

    [DllImport("ole32.dll")]
    private static extern int StgOpenStorageEx([MarshalAs(UnmanagedType.LPWStr)] string pwcsName,STGM grfMode,STGFMT stgfmt,int grfAttrs,IntPtr pStgOptions,IntPtr reserved2,[MarshalAs(UnmanagedType.LPStruct)] Guid riid,out IPropertySetStorage ppObjectOpen);

    [DllImport("ole32.dll")]
    private static extern int PropVariantClear(ref PROPVARIANT pvar);

    [Guid("0000013B-0000-0000-C000-000000000046"),InterfaceType(ComInterfaceType.InterfaceIsIUnknown)]
    private interface IEnumSTATPROPSETSTG
    {
        [PreserveSig]
        int Next(int celt,ref STATPROPSETSTG rgelt,out int pceltFetched);
        // rest ommited
    }

    [Guid("00000139-0000-0000-C000-000000000046"),InterfaceType(ComInterfaceType.InterfaceIsIUnknown)]
    private interface IEnumSTATPROPSTG
    {
        [PreserveSig]
        int Next(int celt,ref STATPROPSTG rgelt,out int pceltFetched);
        // rest ommited
    }

    [Guid("00000138-0000-0000-C000-000000000046"),InterfaceType(ComInterfaceType.InterfaceIsIUnknown)]
    private interface IPropertyStorage
    {
        [PreserveSig]
        int ReadMultiple(uint cpspec,[MarshalAs(UnmanagedType.LPArray,SizeParamIndex = 0)] PROPSPEC[] rgpspec,[Out,MarshalAs(UnmanagedType.LPArray,SizeParamIndex = 0)] PROPVARIANT[] rgpropvar);
        [PreserveSig]
        int WriteMultiple(uint cpspec,SizeParamIndex = 0)]  PROPSPEC[] rgpspec,SizeParamIndex = 0)]  PROPVARIANT[] rgpropvar,uint propidNameFirst);
        [PreserveSig]
        int DeleteMultiple(uint cpspec,SizeParamIndex = 0)] PROPSPEC[] rgpspec);
        [PreserveSig]
        int ReadPropertyNames(uint cpropid,SizeParamIndex = 0)] int[] rgpropid,ArraySubType = UnmanagedType.LPWStr,SizeParamIndex = 0)] string[] rglpwstrName);
        [PreserveSig]
        int NotDeclared1();
        [PreserveSig]
        int NotDeclared2();
        [PreserveSig]
        int Commit(uint grfCommitFlags);
        [PreserveSig]
        int NotDeclared3();
        [PreserveSig]
        int Enum(out IEnumSTATPROPSTG ppenum);
        // rest ommited
    }

    [Guid("0000013A-0000-0000-C000-000000000046"),InterfaceType(ComInterfaceType.InterfaceIsIUnknown)]
    private interface IPropertySetStorage
    {
        [PreserveSig]
        int Create([MarshalAs(UnmanagedType.LPStruct)] Guid rfmtid,[MarshalAs(UnmanagedType.LPStruct)] Guid pclsid,uint grfFlags,out IPropertyStorage ppprstg);
        [PreserveSig]
        int Open([MarshalAs(UnmanagedType.LPStruct)] Guid rfmtid,out IPropertyStorage ppprstg);
        [PreserveSig]
        int NotDeclared3();
        [PreserveSig]
        int Enum(out IEnumSTATPROPSETSTG ppenum);
    }
}

public sealed class StructuredProperty
{
    public StructuredProperty(Guid formatId,string name,int id)
    {
        FormatId = formatId;
        Name = name;
        Id = id;
    }

    public Guid FormatId { get; private set; }
    public string Name { get; private set; }
    public int Id { get; private set; }
    public object Value { get; set; }

    public override string ToString()
    {
        return Name;
    }
}

猜你在找的Windows相关文章